Interview ‐ Spring Data (JpaRepository, MongoRepository) - Yash-777/MyWorld GitHub Wiki

Download and install Rancher Desktop : https://rancherdesktop.io/

After installation, verify Docker: Portable console emulator for Windows λcmder

λ docker --version
Docker version 29.1.4-rd, build 3c6914c
🐳 MSSQL Setup using Docker (Rancher Desktop)

🚀 Step 1 — Run Microsoft SQL Server Container

docker run -e "ACCEPT_EULA=Y" ^
-e "MSSQL_SA_PASSWORD=Strong@123" ^
-p 1433:1433 ^
--name mssql ^
-d mcr.microsoft.com/mssql/server:2019-latest

If image is not present locally:

λ docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=Strong@123" -p 1433:1433 --name mssql -d mcr.microsoft.com/mssql/server:2019-latest

Unable to find image 'mcr.microsoft.com/mssql/server:2019-latest' locally
2019-latest: Pulling from mssql/server
8e76b0919436: Pull complete
e012aedd45a6: Pull complete
306fbe3b6736: Pull complete
Digest: sha256:e7ef04aca478b8aa8dd6380297bdae4969c9ae03cf39de3af94bb6ce3273ca53
Status: Downloaded newer image for mcr.microsoft.com/mssql/server:2019-latest
acc164ea3b4205b6ff5988f0276756ff7d216ca2be9e05fdb6008bae93331fe0

→ ⚠ Container Name Already Exists Error

If you see: Conflict. The container name "/mssql" is already in use. It means container already exists.

docker: Error response from daemon: Conflict. 
 The container name "/mssql" is already in use by container "acc164ea3b4205b6f...".
 You have to remove (or rename) that container to be able to reuse that name.

Run 'docker run --help' for more information

🔎 Step 2 — Check SQL Server Container Name, Verify Container is Running. (RUN: docker ps)

Example output:

λ docker ps
CONTAINER ID   IMAGE                                        PORTS                      NAMES
71912fdfc7a0   mcr.microsoft.com/mssql/server:2019-latest   0.0.0.0:1433->1433/tcp    mssql

✅ Confirm port mapping: 1433 -> 1433 (TCP)


🧪 Step 3 — Test SQL Server Connection

Run SQL command using mssql-tools container:

docker run -it --rm mcr.microsoft.com/mssql-tools \
/opt/mssql-tools/bin/sqlcmd \
-S host.docker.internal,1433 \
-U sa \
-P "Strong@123" \
-Q "SELECT 1"

Expected Output:

λ docker run -it --rm mcr.microsoft.com/mssql-tools /opt/mssql-tools/bin/sqlcmd -S host.docker.internal,1433 -U sa -P "Strong@123" -Q "SELECT 1"

-----------
          1

(1 rows affected)

🗄 Step 4 — Create Database (One-Line Command)

docker run -it --rm mcr.microsoft.com/mssql-tools \
/opt/mssql-tools/bin/sqlcmd \
-S host.docker.internal,1433 \
-U sa \
-P "Strong@123" \
-Q "CREATE DATABASE finance"

----> 🚀 One-Line Shortcut (Without Entering Shell) (Using mssql-tools Container)
C:\Users\ymerugu>docker run -it --rm mcr.microsoft.com/mssql-tools /opt/mssql-tools/bin/sqlcmd -S host.docker.internal,1433 -U sa -P "Strong@123" -Q "CREATE DATABASE finance"
---> ✅ Verify Database Exists
C:\Users\ymerugu>docker run -it --rm mcr.microsoft.com/mssql-tools /opt/mssql-tools/bin/sqlcmd -S host.docker.internal,1433 -U sa -P "Strong@123" -Q "SELECT name FROM sys.databases"
name                                                                                                                    
--------------------------------------------------------------------------------------------------------------------------------
master                                                                                                                  
tempdb                                                                                                                  
model                                                                                                                   
msdb                                                                                                                    
finance                                                                                                                 

(5 rows affected)

🛑 Step 5 — Stop and Remove Container

C:\Users\ymerugu>docker.exe stop mssql
mssql

C:\Users\ymerugu>docker.exe rm mssql
mssql

🧰 Step 6 — Install MSSQL GUI Client (SSMS): Download SQL Server Management Studio (SSMS)

Installer: https://aka.ms/ssms/22/release/vs_SSMS.exe
Documentation: https://learn.microsoft.com/en-us/ssms/install/install

SSMS Connection Settings

Connection String
Data Source=localhost,1433;
Persist Security Info=True;
User ID=sa;
Password=Strong@123;
Pooling=False;
MultipleActiveResultSets=False;
Encrypt=false;
TrustServerCertificate=False;
Application Name="SQL Server Management Studio";
Command Timeout=0

⚠ Important: Encrypt=false Required for local Docker SQL Server.


🍃 MongoDB Setup using Docker (Rancher Desktop)

🚀 Step 1 — Run MongoDB Container

docker run -d --name mongodb -p 27017:27017 mongo:latest

If image is not available locally:

Unable to find image 'mongo:latest' locally
Pulling from library/mongo
Status: Downloaded newer image for mongo:latest

Container will start automatically after download.


🔎 Step 2 — Verify MongoDB Container docker ps

Example output: ✅ MongoDB default port: TCP 27017

CONTAINER ID   IMAGE          PORTS                        NAMES
77ca86c14ee8   mongo:latest   0.0.0.0:27017->27017/tcp    mongodb

🧰 Step 3 — Install MongoDB GUI Client

MongoDB Compass (Official GUI Tool) for MongoDB data exploration and management.

Download

Product Page: https://www.mongodb.com/products/tools/compass
Direct Download: https://downloads.mongodb.com/compass/mongodb-compass-1.49.2-win32-x64.exe


🔌 Step 4 — Connect MongoDB using Compass

Open MongoDB Compass → New Connection

Connection String

mongodb://localhost:27017

Click: Connect




EAGER vs LAZY loading

Relationship Default Fetch Type Explanation
@OneToOne EAGER Associated entity loaded immediately
@ManyToOne EAGER Parent entity loaded immediately
@OneToMany LAZY Child entities loaded when accessed
@ManyToMany LAZY Associated collection loaded when accessed
jakarta.persistence-api-2.2.3.jar<.code> - source code of Relationship's
javax.persistence.FetchType.EAGER javax.persistence.FetchType.LAZY;
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToOne {
    /** 
     * (Optional) Whether the association should be lazily 
     * loaded or must be eagerly fetched. The EAGER 
     * strategy is a requirement on the persistence provider runtime that 
     * the associated entity must be eagerly fetched. The LAZY 
     * strategy is a hint to the persistence provider runtime.
     */
    FetchType fetch() default EAGER;
	// ...
}
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
    /** 
     * (Optional) Whether the association should be lazily 
     * loaded or must be eagerly fetched. The EAGER
     * strategy is a requirement on the persistence provider runtime that 
     * the associated entity must be eagerly fetched. The LAZY 
     * strategy is a hint to the persistence provider runtime.
     */
    FetchType fetch() default EAGER;
}
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
    /** (Optional) Whether the association should be lazily loaded or
     * must be eagerly fetched. The EAGER strategy is a requirement on
     * the persistence provider runtime that the associated entities
     * must be eagerly fetched.  The LAZY strategy is a hint to the
     * persistence provider runtime.
     */
    FetchType fetch() default LAZY;
}
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ManyToMany {
/** (Optional) Whether the association should be lazily loaded or
* must be eagerly fetched. The EAGER strategy is a requirement on
* the persistence provider runtime that the associated entities
* must be eagerly fetched.  The LAZY strategy is a hint to the
* persistence provider runtime.
*/
FetchType fetch() default LAZY;
}

⭐ Golden Rule

  • Lazy loading works only within an active transactional persistence context.
  • ❌ LazyInitializationException happens when a LAZY field is accessed outside an active Persistence Context (Hibernate Session / Transaction).

📘 Spring Data Repository Interface

Repository Hierarchy

Repository<T, ID>                               ← Marker interface (no methods)
  └── CrudRepository<T, ID>                     ← Basic CRUD operations
        └── PagingAndSortingRepository<T, ID>   ← + Sorting & Pagination
              ├── JpaRepository<T, ID>          ← + JPA-specific (flush, batch delete, getOne)
              └── MongoRepository<T, ID>        ← + Mongo-specific (insert)

Both JpaRepository and MongoRepository also extend QueryByExampleExecutor<T>.

JpaRepository MongoRepository
package org.springframework.data.jpa.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@org.springframework.data.repository.NoRepositoryBean
public interface JpaRepository<T, ID> extends 
                       PagingAndSortingRepository<T, ID>,
                       QueryByExampleExecutor<T> {
    @Override
    List<T> findAll();
    @Override
    List<T> findAll(Sort sort);
    @Override
    List<T> findAllById(Iterable<ID> ids);
    @Override
    <S extends T> List<S> saveAll(Iterable<S> entities);
    // Flushes all pending changes to the database.
    void flush();
    // Saves an entity and flushes changes instantly.
    <S extends T> S saveAndFlush(S entity);
    void deleteInBatch(Iterable<T> entities);
    void deleteAllInBatch();
    T getOne(ID id);
    @Override
    <S extends T> List<S> findAll(Example<S> example);
    @Override
    <S extends T> List<S> findAll(Example<S> example, Sort sort);
}
package org.springframework.data.mongodb.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@org.springframework.data.repository.NoRepositoryBean
public interface MongoRepository<T, ID> extends 
                       PagingAndSortingRepository<T, ID>,
                       QueryByExampleExecutor<T> {
    @Override
    <S extends T> List<S> saveAll(Iterable<S> entities);
    @Override
    List<T> findAll();
    @Override
    List<T> findAll(Sort sort);
    <S extends T> S insert(S entity);
    <S extends T> List<S> insert(Iterable<S> entities);
    @Override
    <S extends T> List<S> findAll(Example<S> example);
    @Override
    <S extends T> List<S> findAll(Example<S> example, Sort sort);
}
package org.springframework.data.repository;

// ── Paging & Sorting ──────────────────────────────────────────────────────────
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
    Iterable<T> findAll(org.springframework.data.domain.Sort sort);      // All records, sorted
    Page<T> findAll(org.springframework.data.domain.Pageable pageable);  // Paginated + sorted result
}
// ── Basic CRUD ────────────────────────────────────────────────────────────────
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S entity);                          // Insert or Update (upsert)
    <S extends T> Iterable<S> saveAll(Iterable<S> entities); // Bulk upsert
    Optional<T> findById(ID id);                             // Find by PK → Optional (never null)
    boolean existsById(ID id);                               // Check existence by PK
    Iterable<T> findAll();                                   // Fetch all records
    Iterable<T> findAllById(Iterable<ID> ids);               // Fetch by list of PKs
    long count();                                            // Total row/document count
    void deleteById(ID id);                                  // Delete by PK
    void delete(T entity);                                   // Delete given entity
    void deleteAll(Iterable<? extends T> entities);          // Delete given list
    void deleteAll();                                        // Delete everything — USE WITH CAUTION
}
// ── Marker interface ──────────────────────────────────────────────────────────
@Indexed
public interface Repository<T, ID> { }

Maven Dependency, application.properties

spring-boot-starter-data-jpa spring-boot-starter-data-mongodb
Maven Dependency
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <!-- Exclude HikariCP if using Tomcat JDBC pool instead -->
        <exclusion>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- SQL Server JDBC driver -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- Tomcat JDBC Connection Pool (if replacing HikariCP) -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
</dependency>
application.properties
#-----------------------------------------
# SQL Server DataBase Properties
#-----------------------------------------
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=finance
spring.datasource.username=sa
spring.datasource.password=Strong@123
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect

#-----------------------------------------
# DataBase Connection Pool (Tomcat JDBC)
#-----------------------------------------
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.test-while-idle=true
spring.datasource.tomcat.test-on-return=false
spring.datasource.tomcat.validation-query=select 1
spring.datasource.tomcat.initial-size=15
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.max-idle=15
spring.datasource.tomcat.min-idle=8
spring.datasource.tomcat.default-auto-commit=true
spring.datasource.tomcat.log-validation-errors=true
spring.datasource.log-abandoned=true

#-----------------------------------------
# JPA / Hibernate Properties
#-----------------------------------------
# none | validate | update | create | create-drop
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
# Preserve column names as declared in @Column(name="...")
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# Required for @CreatedDate / @LastModifiedDate to work
spring.jpa.properties.javax.persistence.validation.mode=none
Maven Dependency
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
#-----------------------------------------
# MongoDB Properties
#-----------------------------------------
spring.data.mongodb.uri=mongodb://localhost:27017/local?authSource=admin&ssl=false&maxPoolSize=1000

# Alternative: individual properties
# spring.data.mongodb.host=localhost
# spring.data.mongodb.port=27017
# spring.data.mongodb.database=local
# spring.data.mongodb.username=admin
# spring.data.mongodb.password=secret

JpaRepository vs MongoRepository

Note

⚠️ Avoid @Data on JPA @Entity classes@EqualsAndHashCode and @ToString can trigger lazy-load exceptions and cause infinite loops with bidirectional relationships. Use @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + @Builder separately instead.

🚀 Main Application
🗄️ JPA Side — Product (SQL Entity) 🍃 MongoDB Side — Order (NoSQL Document)
BaseEntity.java — Abstract JPA base class
package com.example.shop.entity;

/**
 * Abstract base for all JPA entities.
 *
 * @MappedSuperclass   — Fields are inherited into child entity tables (no separate table created).
 * @EntityListeners    — Activates Spring's JPA auditing for @CreatedDate / @LastModifiedDate.
 */
@Getter @Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @org.springframework.data.annotation.Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // Auto-increment PK (Long)
    private Long id;

    @Column(name = "active_status", nullable = false)
    private boolean activeStatus = true;

    @org.springframework.data.annotation.CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @org.springframework.data.annotation.LastModifiedDate
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
}
BaseDocument.java — Abstract MongoDB base class
package com.example.shop.document;

/**
 * Abstract base for all MongoDB documents.
 *
 * @Id — Maps to MongoDB's _id field. Spring stores the ObjectId as a String.
 *       Unlike JPA, there is no @GeneratedValue — MongoDB generates ObjectId automatically.
 *
 * No @MappedSuperclass needed — MongoDB has no schema inheritance constraint.
 * No @EntityListeners needed — @EnableMongoAuditing handles @CreatedDate / @LastModifiedDate.
 * @Getter / @Setter   — Lombok: generates all getters and setters automatically.
 */
@Getter @Setter
public abstract class BaseDocument implements Serializable {
    private static final long serialVersionUID = 1L;

    @org.springframework.data.annotation.Id
    private String id;  // MongoDB ObjectId (auto-generated as 24-char hex string)

    private boolean active = true;

    @org.springframework.data.annotation.CreatedDate
    private LocalDateTime createdAt;

    @org.springframework.data.annotation.LastModifiedDate
    private LocalDateTime updatedAt;
}
ProductEntity.java — Concrete JPA Entity
package com.example.shop.entity;

import javax.persistence.*;

/**
 * Maps to the "products" table in the SQL database.
 *
 * @Entity             — Marks this class as a JPA-managed table.
 * @Table              — Specifies the exact table name in the DB.
 * @Getter / @Setter   — Lombok: all getters & setters.
 * @NoArgsConstructor  — Lombok: no-arg constructor (required by JPA).
 * @AllArgsConstructor — Lombok: constructor with all fields.
 * @Builder            — Lombok: fluent builder pattern  e.g. ProductEntity.builder().name("X").build()
 * @ToString           — Lombok: generates toString() (excludes BaseEntity fields via callSuper=false)
 */
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder @ToString @Entity
@Table(name = "products")
public class ProductEntity extends BaseEntity {
    private static final long serialVersionUID = 2L;

    @Column(name = "product_name", nullable = false)
    private String name;
    @Column(name = "category")
    private String category;
    @Column(name = "price", nullable = false)
    private double price;
    @Column(name = "stock_quantity")
    private int stockQuantity;
    @Column(name = "sku", unique = true)
    private String sku;  // Stock Keeping Unit — unique product code
}
  • OrderStatus.java — Enum
  • OrderItem.java — Embedded sub-document (not a separate collection)
  • OrderDocument.java — Concrete MongoDB Document
package com.example.shop.document;

public enum OrderStatus {
    PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED
}
/**
 * Embedded object stored inside OrderDocument as a nested BSON field.
 * NOT a separate MongoDB collection — no @Document annotation.
 *
 * @Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
 */
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public class OrderItem {
    private String sku;
    private String productName;
    private int quantity;
    private double unitPrice;

    // Derived field — not stored in DB, computed on read
    public double getTotalPrice() {
        return quantity * unitPrice;
    }
}

/**
 * Maps to the "orders" collection in MongoDB.
 *
 * @org.springframework.data.mongodb.core.mapping.Document(collection = "orders")
 *   Equivalent of @Entity + @Table in JPA.
 *   Specifies the MongoDB collection name explicitly.
 *
 * @com.fasterxml.jackson.annotation.JsonIgnoreProperties({"createdAt","updatedAt"})
 *   Excludes audit fields from JSON REST responses.
 *
 * @Indexed — Creates a MongoDB index on the annotated field for faster queries.
 */
@Data @NoArgsConstructor @AllArgsConstructor @Builder
@org.springframework.data.mongodb.core.mapping.Document(collection = "orders")
@JsonIgnoreProperties({ "createdAt", "updatedAt" })
public class OrderDocument extends BaseDocument {
    private static final long serialVersionUID = 2L;

    @org.springframework.data.mongodb.core.index.Indexed  // MongoDB index — speeds up queries by customerId
    private String customerId;
    private String customerName;
    private List<OrderItem> items; // Embedded list of sub-documents (no separate collection)
    private OrderStatus status;
    private double totalAmount;
    private String deliveryAddress;
    private String remarks;
}
  • BaseRepository.java — Abstract JPA base repository
  • ProductRepository.java — Concrete JPA Repository
package com.example.shop.repository;

import com.example.shop.entity.BaseEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @NoRepositoryBean — Spring will NOT instantiate this interface as a bean.
 *                     Only concrete child interfaces get Spring-managed beans.
 *
 * Generic bound  ensures only proper entities extend this.
 */
@org.springframework.data.repository.NoRepositoryBean
public interface BaseRepository<E extends BaseEntity>
        extends JpaRepository<E, Long> {
    // Shared custom query methods go here (e.g. findAllByActiveStatus)
}

import com.example.shop.entity.ProductEntity;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

/**
 * Spring creates a bean for this interface (it is concrete, not @NoRepositoryBean).
 * All CRUD + paging + sorting methods are inherited automatically.
 */
@Repository
public interface ProductRepository extends BaseRepository<ProductEntity> {

    // Derived query — Spring generates: WHERE category = ? AND active_status = ?
    List<ProductEntity> findByCategoryAndActiveStatus(
            @Param("category") String category,
            @Param("activeStatus") boolean activeStatus);

    // Derived query — Spring generates: WHERE sku = ?
    Optional<ProductEntity> findBySku(@Param("sku") String sku);

    // Derived count — Spring generates: SELECT COUNT(*) WHERE category = ?
    long countByCategory(@Param("category") String category);

    // Derived exists — Spring generates: SELECT CASE WHEN COUNT(*) > 0 WHERE sku = ?
    boolean existsBySku(@Param("sku") String sku);
}
  • BaseDocumentRepository.java — Abstract MongoDB base repository
  • OrderRepository.java — Concrete MongoDB Repository
package com.example.shop.repository;

import com.example.shop.document.BaseDocument;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;

/**
 * @NoRepositoryBean — Spring will NOT create a bean for this interface.
 *
 * ID is String because MongoDB ObjectId is serialized as a 24-char hex String.
 */
@NoRepositoryBean
public interface BaseDocumentRepository<D extends BaseDocument>
        extends MongoRepository<D, String> {
    // Shared Mongo query methods can go here
}

import com.example.shop.document.OrderDocument;
import com.example.shop.document.OrderStatus;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends BaseDocumentRepository<OrderDocument> {

    // Derived query — WHERE customerId = ?
    List<OrderDocument> findByCustomerId(@Param("customerId") String customerId);

    // Derived query — WHERE customerId = ? AND status = ?
    List<OrderDocument> findByCustomerIdAndStatus(
            @Param("customerId") String customerId,
            @Param("status") OrderStatus status);

    // Derived count — SELECT COUNT(*) WHERE status = ?
    long countByStatus(@Param("status") OrderStatus status);

    // Derived exists — WHERE customerId = ?
    boolean existsByCustomerId(@Param("customerId") String customerId);
}
package com.example.shop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.mongodb.config.EnableMongoAuditing;

@SpringBootApplication
@EnableJpaAuditing       // Activates @CreatedDate / @LastModifiedDate for JPA entities
@EnableMongoAuditing     // Activates @CreatedDate / @LastModifiedDate for Mongo documents
public class ShopApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShopApplication.class, args);
    }
}
⚠️ **GitHub.com Fallback** ⚠️