SprinBoot Interview Question

 🔑 Dependency Injection (DI) — Easy Explanation


👉 Definition:
Dependency Injection is a design pattern where the object’s dependencies are provided (injected) by the Spring Container instead of the object creating them itself.

✅ Simply put: Don’t create things yourself, ask Spring to give them to you.


🚗 Example without DI:

class Car {

    private Engine engine = new Engine(); // Car is creating its own Engine

}

❌ Problem → Car is tightly coupled with Engine. Hard to test, hard to change engine type.


🚗 Example with DI:

class Car {

    private Engine engine;  // Car depends on Engine


    // Constructor Injection

    public Car(Engine engine) {

        this.engine = engine;

    }

}

Now Spring will inject the Engine into Car.
Loose coupling, easy to test, flexible.


📌 Types of Dependency Injection

1️⃣ Constructor Injection (Recommended)
👉 Dependencies are provided through the class constructor.


@Component

class Car {

    private final Engine engine;


    @Autowired

    public Car(Engine engine) {

        this.engine = engine;

    }

}

✅ Best practice (especially for mandatory dependencies).
✅ Makes the class immutable & good for testing.


2️⃣ Setter Injection
👉 Dependencies are injected via setter methods.

@Component
class Car {
    private Engine engine;

    @Autowired
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
}
✅ Useful for optional dependencies.
    
3️⃣ Field Injection (Not Recommended)
👉 Spring injects directly into fields.

@Component
class Car {
    @Autowired
    private Engine engine;
}
⚠️ Easy but bad for testing & immutability.
(Spring team itself recommends constructor over field injection).


🎯 Interview Tips

  • What is DI? → “DI is when Spring creates and supplies dependencies instead of us creating them manually.”

  • Types of DI? → Constructor, Setter, Field.

  • Which one to use? → Prefer Constructor Injection (clear, immutable, test-friendly).




Q: What’s the difference between IoC and DI?
✅ Answer:
“IoC is the general concept where Spring takes control of object creation and management from the programmer. Dependency Injection is a specific way of implementing IoC — by injecting required dependencies into a class instead of the class creating them itself.”



  • Inversion of Control (IOC): It is a design principle where the control of object creation and lifecycle is managed by a framework or container rather than by the developer. Spring IOC Container is responsible for creating, configuring, and managing the lifecycle of objects called beans.
  • Dependency Injection: It is a design pattern and a part of IOC container. It allows objects to be injected with their dependencies rather than creating those dependencies themselves

🔑 Key Idea

  • IoC (Inversion of Control) → Big concept: Spring container is responsible for creating objects (beans) and managing their lifecycle (initialization, destruction).

  • DI (Dependency Injection) → Narrow concept: A way of implementing IoC, where Spring injects the required dependencies into a class instead of the class creating them.

🔑 @Primary vs @Qualifier

1️⃣ @Primary

  • Marks a bean as the default choice if multiple beans of the same type exist.

  • Spring will inject the @Primary bean only if no @Qualifier is specified.

  • @Component

    @Primary

    class PetrolEngine implements Engine { }


    @Component

    class DieselEngine implements Engine { }


  • @Autowired

    private Engine engine; // ✅ PetrolEngine (because it’s @Primary)

2️⃣ @Qualifier

  • Used when you want to explicitly tell Spring which bean to inject.

  • Overrides @Primary if both are present.


@Component
class PetrolEngine implements Engine { }

@Component
@Primary
class DieselEngine implements Engine { }

@Component
class Car {
    @Autowired
    @Qualifier("petrolEngine")   // ✅ Even though Diesel is @Primary, PetrolEngine will be injected
    private Engine engine;
}

⚖️ Priority Rule

👉 @Qualifier always wins over @Primary

  • If @Qualifier present → Spring uses that bean.

  • If no @Qualifier but multiple beans → Spring uses @Primary.

  • If neither given & multiple beans exist → Spring throws NoUniqueBeanDefinitionException.


🎯 Interview One-Liner

👉 “@Primary marks a bean as default, but if @Qualifier is used, it takes higher priority and overrides @Primary.”


How to create bean manually ?


In Spring, most beans are created automatically using @Component, @Service, etc.
But sometimes you need to create a bean manually (e.g., 3rd-party library class, or when you need custom config).


🔑 Ways to Create a Bean Manually


1️⃣ Using @Bean inside a @Configuration class

This is the most common way.

@Configuration

public class AppConfig {


    @Bean

    public Engine engineBean() {

        return new Engine("V8"); // custom object creation

    }

}


3️⃣ Using ApplicationContext programmatically

(Spring container lets you register beans at runtime)

@Configuration

public class DynamicConfig implements ApplicationContextAware {

    private ApplicationContext context;


    @Override

    public void setApplicationContext(ApplicationContext applicationContext) {

        this.context = applicationContext;


        // Register a bean manually at runtime

        ((ConfigurableApplicationContext) context)

            .getBeanFactory()

            .registerSingleton("myBean", new Engine("Turbo"));

    }

}


🎯 Interview One-Liner

👉 “We create beans manually using the @Bean annotation inside a @Configuration class. This is useful when the class is from a third-party library or when we need custom initialization logic. By default, we use stereotype annotations (@Component, @Service, etc.), but @Bean gives more control.”


🔑 Spring Bean Lifecycle (Easy Way)

Whenever you declare a bean (@Component, @Bean, etc.), Spring IoC Container manages its entire lifecycle.

Here are the steps in order 👇

The lifecycle order is: Instantiation → Dependency Injection → Initialization → Ready to use → Destruction.”

Instantiation – Bean is created by Spring IoC.

Populate Properties – Dependencies are injected.

Initialization@PostConstruct, afterPropertiesSet(), or custom initMethod.

Destruction@PreDestroy, destroy(), or custom destroyMethod.


The lifecycle of a Spring bean consists of the following phases, which are listed below

  • Container Started: The Spring IoC container is initialized.
  • Bean Instantiated: The container creates an instance of the bean.
  • Dependencies Injected: The container injects the dependencies into the bean.
  • Custom init() method: If the bean implements InitializingBean or has a custom initialization method specified via @PostConstruct or init-method.
  • Bean is Ready: The bean is now fully initialized and ready to be used.
  • Custom utility method: This could be any custom method you have defined in your bean.
  • Custom destroy() method: If the bean implements DisposableBean or has a custom destruction method specified via @PreDestroy or destroy-method, it is called when the container is shutting down.




Q4. Can we have multiple initialization methods in a bean?

Answer:
“Yes, order is → @PostConstructafterPropertiesSet()initMethod. All will be called if defined.”


Q5. What is BeanPostProcessor in the lifecycle?

Answer:
BeanPostProcessor is a special interface that allows you to run custom logic before and after bean initialization. For example, we can use it to wrap a bean with a proxy or log initialization.”


Q7. When does bean destruction happen?

Answer:
“When the ApplicationContext is closed (e.g., context.close() in standalone apps, or when the app shuts down in web apps). Then Spring calls @PreDestroy, DisposableBean.destroy(), or destroyMethod.”


Q8. How does singleton vs prototype affect bean lifecycle?

Answer:

  • Singleton → Full lifecycle is managed (creation → destruction).

  • Prototype → Spring creates and injects the bean, but doesn’t manage destruction (no @PreDestroy).


🔑 Difference Between @Controller and @RestController


1️⃣ @Controller

  • Used in Spring MVC (web applications).

  • Returns views (HTML, JSP, Thymeleaf, etc.), not JSON by default.

  • If you want to return JSON, you must use @ResponseBody manually.

  •  must use @ResponseBody on methods to return JSON/XML instead of a view.

  •  

    @RestController

  • Used to build REST APIs (return JSON/XML responses).
  • Returns data (JSON/XML) directly in the HTTP response body.
  • @RestController = @Controller + @ResponseBody

🔑 What does @SpringBootApplication do?


it is  the entry point of every Spring Boot app.


👉 @SpringBootApplication is a convenience annotation that combines 3 important Spring annotations:

@SpringBootApplication

= @Configuration 

+ @EnableAutoConfiguration 

+ @ComponentScan



1️⃣ @Configuration

  • Marks the class as a configuration class.

  • Allows defining beans with @Bean methods.

  • public class AppConfig {

        @Bean

        public Engine engine() {

            return new Engine();

        }

    }

2️⃣ @EnableAutoConfiguration

  • Tells Spring Boot to auto-configure beans based on the dependencies in the classpath.

  • Example:

    • If you add spring-boot-starter-web, Spring Boot auto-configures Tomcat server + DispatcherServlet.

    • If you add spring-boot-starter-data-jpa, Spring Boot auto-configures Hibernate + Datasource.

👉 Saves you from writing huge XML or Java config manually.


3️⃣ @ComponentScan

  • Automatically scans the package where your main app class is, and all its sub-packages, for beans (@Component, @Service, @Repository, @Controller).


🎯 Interview One-Liner

👉 “@SpringBootApplication is a shortcut annotation in Spring Boot that combines @Configuration, @EnableAutoConfiguration, and @ComponentScan. It marks the class as a configuration class, enables auto-configuration, and scans for components — basically, it makes your class the entry point of a Spring Boot application.”


🎭 Stereotype Annotations in Spring

👉 Definition:
Stereotype annotations are specialized forms of @Component that tell Spring what role a bean plays in your application (business logic, DAO, controller, etc.).
They improve readability and help Spring apply extra behaviors automatically.


🔑 Types of Stereotype Annotations

1️⃣ @Component

2️⃣ @Service
3️⃣ @Repository
4️⃣ @Controller
5️⃣ @RestController

🌱 @Component in Spring

📌 Definition

@Component is the most generic stereotype annotation in Spring.

  • It tells Spring “Hey, create an object of this class and manage it in the IoC container.”

  • Any class marked with @Component becomes a Spring Bean.

📌 Why use it?

Without @Component, you would have to manually configure the bean in @Configuration class using @Bean.
With @Component, Spring auto-detects the class during component scanning and registers it as a bean automatically.



🎯 Interview One-Liner

👉 “Stereotype annotations in Spring are specialized versions of @Component that define the role of a class in the application. @Service for business logic, @Repository for DAO, @Controller for MVC, and @RestController for REST APIs. They help Spring organize beans better and add extra behaviors.”



🔑 What is @PathVariable?

  • @PathVariable is used in Spring MVC / Spring Boot to extract values from the URL path and map them to method parameters.

  • It is commonly used in REST APIs when you pass data as part of the URL.

@RestController
@RequestMapping("/cars")
public class CarController {

    // Example: GET /cars/101
    @GetMapping("/{id}")
    public String getCarById(@PathVariable("id") int carId) {
        return "Car ID: " + carId;
    }
}
✅ If you hit → http://localhost:8080/cars/101
👉 Response → Car ID: 101


Interview one-liner:
@PathVariable is used to bind dynamic values from the URL path directly into method parameters. It’s different from @RequestParam, which fetches values from query parameters.”



📌 Difference: @PathVariable vs @RequestParam



@RequestParam – Easy Explanation

  • It is used to take values from URL query string.

  • Example:
    URL → http://localhost:8080/hello?name=shivam&age=25

  • 🔹 Key Points

    • Comes from query string (after ? in URL).

    • required=true by default → must be present.

    • You can use defaultValue if not passed.


Interview One-liner
@RequestParam is used to bind query parameters (or form data) from the request URL into method parameters. Unlike @PathVariable, which extracts values from the URL path itself, @RequestParam works with query strings.”


@RequestParam is used for searching/filtering (like /cars?owner=shivam&color=red).


Spring Boot, the default server is Tomcat. 🚀

🔹 Explanation

  • Spring Boot uses embedded servers so you don’t need to install a server separately.

  • By default, Spring Boot includes Embedded Tomcat.

  • When you run your Spring Boot app, Tomcat starts automatically and listens on port 8080.

Interview one-liner:
“Spring Boot’s default embedded server is Tomcat, but it also supports Jetty and Undertow if configured.”


how do you configure different enviornment in springboot ?

🔹 Why Different Environments?

  • In real projects, we run apps in different environments:

    • dev → for developers

    • test/qa → for testing team

    • prod → live system

Each environment may need different configs (DB URL, username, logging, etc.).


🔹 How to Configure in Spring Boot

✅ 1. Use application.properties / application.yml

Spring Boot allows you to create multiple property files:

application.properties        → default

application-dev.properties    → dev environment

application-test.properties   → test environment

application-prod.properties   → production


✅ 2. Activate Profile

Tell Spring Boot which environment to use by setting spring.profiles.active.

👉 Example: in application.properties

spring.profiles.active=dev

👉 Or pass as VM argument when running:
-Dspring.profiles.active=prod
java -jar app.jar --spring.profiles.active=test


✅ 4. Using @Profile Annotation

You can also load beans only for a specific environment:


@Component

@Profile("dev")

public class DevDatabaseConfig {

    // only loads in dev

}


@Component

@Profile("prod")

public class ProdDatabaseConfig {

    // only loads in prod

}


🔹 Interview One-Liner

“In Spring Boot, we configure different environments using profiles. We create environment-specific property files like application-dev.properties, and activate them using spring.profiles.active. We can also use @Profile to load beans conditionally.”



🔹 Exception Handling in Spring Boot

👉 Definition: Exception handling means catching errors gracefully in your application and returning a meaningful response instead of showing a server crash/stack trace to the user.

  • Without handling → user sees ugly 500 Internal Server Error.

  • With handling → user gets clear JSON error message like:

  • {

      "error": "User Not Found",

      "status": 404,

      "timestamp": "2025-08-16T10:30:00"

    }

🔹 How to Handle Exceptions in Spring?

1. @ExceptionHandler

  • Handle exceptions inside a controller.

  • @RestController

    public class UserController {


        @GetMapping("/user/{id}")

        public String getUser(@PathVariable int id) {

            if (id == 0) {

                throw new IllegalArgumentException("Invalid ID");

            }

            return "User found!";

        }


        @ExceptionHandler(IllegalArgumentException.class)

        public String handleInvalidId(IllegalArgumentException ex) {

            return "Error: " + ex.getMessage();

        }

    }

👉 Here only UserController handles this error.

2. @ControllerAdvice / @RestControllerAdvice (Advisor)

👉 This is what you meant by advisor.

  • It is a global exception handler.

  • Works for all controllers in the project.

  • @RestControllerAdvice = @ControllerAdvice + @ResponseBody (returns JSON).


👉 Now all controllers will use this handler if exception occurs.


Interview One-Liner:
“Exception handling in Spring Boot is done using @ExceptionHandler for local handling and @ControllerAdvice / @RestControllerAdvice (Advisor) for global handling. Advisor acts like a centralized error handler for all controllers.”



🔹 What is @Transactional in Spring?

  • It tells Spring that a method/class should run inside a database transaction.

  • A transaction = a unit of work where either all steps succeed ✅ or none succeed (rollback) ❌.

👉 Example: In banking — transfer money

  1. Deduct ₹100 from Account A

  2. Add ₹100 to Account B

If step 1 succeeds but step 2 fails → both should rollback (otherwise money vanishes).
That’s where @Transactional helps.


🔹 How @Transactional Works?

When you put @Transactional on a method/class:

  1. Spring creates a proxy around the method.

  2. When the method starts → it opens a transaction.

  3. If method finishes successfully → commit changes.

  4. If exception occurs → rollback changes.


🔹 Interview One-Liner

"@Transactional in Spring manages database transactions. It ensures atomicity: either all operations inside a method complete successfully and are committed, or if an exception occurs, all are rolled back. This prevents data inconsistency."

🔹 What are Design Patterns?

  • Design patterns are reusable solutions to common software design problems.

  • Spring Boot internally uses many design patterns to make development easy.


🔹 Common Design Patterns in Spring Boot

1️⃣ Singleton Pattern

  • What: Only one instance of a bean is created per Spring container (default scope).

  • Where in Spring: All @Component, @Service, @Repository, @Controller beans are Singleton by default.

  • 2️⃣ Factory Pattern

    • What: Instead of creating objects with new, delegate creation to a factory.

    • Where in Spring: BeanFactory and ApplicationContext are factories that create beans.


3️⃣ Proxy Pattern

  • What: A proxy object wraps the real object to add extra behavior (logging, transaction, security).

  • Where in Spring:

    • AOP (@Aspect)

    • @Transactional (creates proxy around methods)

4️⃣ Observer Pattern

5️⃣ Template Method Pattern

  • What: Define steps of an algorithm in a base class, subclasses provide implementation.

  • Where in Spring:

6️⃣ Dependency Injection (DI) / Inversion of Control (IoC)

  • What: Don’t create dependencies manually → framework injects them.

  • Where in Spring: Everywhere! @Autowired, @Qualifier.


7️⃣ Builder Pattern (Lombok, Spring APIs)

  • What: Step-by-step object construction.

  • Where in Spring: Many request/response builders, also in Lombok (@Builder).


🔹 What is Microservice Architecture?

👉 Microservice Architecture is a way of building applications by breaking them into small, independent services, where each service focuses on a single business capability and can be developed, deployed, and scaled separately.



🔹 Features of Microservice Architecture

  1. Independent Services – Each service has its own code, database, and logic.

  2. Loose Coupling – Services don’t depend tightly on each other.

  3. Technology Freedom – One service can use Java + MySQL, another can use Python + MongoDB.

  4. Scalability – You can scale only the service that needs more load (e.g., Payment Service during sales).

  5. Resilience – If one service fails, others still work.

  6. Faster Development – Teams work independently on different services.


🔹 Interview One-Liner Answer

👉 “Microservice architecture is an approach where an application is divided into small, independent services. Each service focuses on a single business capability, has its own database, can be deployed and scaled independently, and communicates with other services through APIs or messaging systems like Kafka.”


Synchronous Communication and ASynchronous Communication

One-liner answer for interview:
👉 “Synchronous communication means the service waits for a response (like REST), while asynchronous means it just sends the request and moves on (like Kafka). Sync is simple but tightly coupled, Async is scalable and fault-tolerant but more complex.”



Interview One-liner:
"Kafka communication is asynchronous — producer doesn’t wait for consumer. It may wait for broker ACKs (depending on config), but overall it’s non-blocking compared to synchronous REST calls."



🔹 Kafka & ACKs

  • Kafka is asynchronous because the producer doesn’t block for full processing of the message.

  • BUT… producer can wait for ACK from Kafka broker, depending on acks config.

🔹 acks Config in Kafka Producer

  1. acks=0 → Fire and forget. ✅ Don’t wait at all.

  2. acks=1 → Wait only for leader broker to confirm.

  3. acks=all (-1) → Wait until all replicas confirm. (Most reliable)

🔹 So is Kafka Async or Sync?

  • By default, Kafka is asynchronous → producer sends message to buffer and continues.

  • If you set acks=1 or acks=all, producer waits for confirmation, but still doesn’t wait for consumer to read.

👉 So compared to REST call (sync), Kafka is async because the producer doesn’t wait for consumer response, only (optionally) broker ACK.


🔹 “Kafka does not block message” means:

When a producer sends a message → it doesn’t stop (block) and wait for the consumer to finish processing.

  • Producer just puts the message into Kafka broker (queue/log).

  • Then producer continues its work immediately.

  • Consumer can read it later, anytime.

🔹 About ACKs

Even if producer waits for acknowledgement from Kafka broker (acks=1 or acks=all),
👉 it only confirms the message reached broker storage,
👉 not that consumer has processed it.

So still non-blocking with respect to consumer.


✅ Things to consider while building a REST API

1. Resource design (URL naming)

  • Use nouns not verbs → /users, /orders/{id} (❌ /getUsers).

  • Use plural for collections → /products not /productList.

  • Hierarchy → /users/{id}/orders (nested resources).

  • Keep URLs clean, lowercase, and predictable.

. HTTP methods correctly

  • GET → fetch

  • POST → create

  • PUT → full update

  • PATCH → partial update

  • DELETE → remove

(Interviewers love when you show you know idempotency: GET, PUT, DELETE are idempotent; POST is not).


3. Status codes

  • 200 OK → success

  • 201 CREATED → after POST

  • 204 NO CONTENT → after DELETE

  • 400 BAD REQUEST → client error

  • 401 UNAUTHORIZED → not logged in

  • 403 FORBIDDEN → not allowed

  • 404 NOT FOUND → resource missing

  • 500 INTERNAL SERVER ERROR → server error

4. Validation & Exception Handling

  • Validate inputs (@Valid, Bean Validation).

  • Use @ControllerAdvice + @ExceptionHandler for global error handling.

  • Return clear error messages (never stack traces).

5. Versioning

  • APIs evolve → support versions:

    • In path → /api/v1/users

    • In header → Accept: application/vnd.company.v1+json

6. Security

  • Use HTTPS always.

  • Authentication → JWT / OAuth2.

  • Authorization → roles/permissions.

  • Never expose sensitive info (stack traces, SQL errors).


7. Pagination & Sorting

  • For large datasets →

    • GET /users?page=1&size=20&sort=name,asc

  • Prevents performance issues.

8. Idempotency

  • Retry-safe APIs: e.g. if client retries POST /payment, don’t charge twice → use idempotency keys.

  • For PUT/DELETE → safe to call multiple times.

10. Performance

  • Enable caching (ETag, Cache-Control).

  • Use gzip compression for payloads.

  • Keep responses small (don’t return unnecessary fields).

11. Documentation

  • Use Swagger / OpenAPI → auto-documentation.

  • Makes it easy for front-end / other teams.


12. Monitoring & Logging

  • Log requests/responses (but mask sensitive info).

  • Metrics (Prometheus, Micrometer).

  • Trace requests (Zipkin, Sleuth).

🎯 Interview-ready short answer

“When building REST APIs, I focus on clean resource design, using proper HTTP methods/status codes, input validation & error handling, supporting versioning, ensuring security with HTTPS + JWT/OAuth2, handling pagination & sorting for large data, making APIs idempotent, adding caching & performance improvements, and documenting with Swagger/OpenAPI. I also ensure centralized logging, monitoring, and tracing for debugging in production.”


@PostMapping, @PutMapping, and @PatchMapping

🔑 Easy Interview Keywords

  • POST → Create new (❌ not idempotent)

  • PUT → Replace full (✅ idempotent)

  • PATCH → Update partial (✅ usually idempotent)

 1. POST → Create (Not Idempotent)

  • Used to create a new resource.

  • Every call creates a new object.

  • Not idempotent (same request twice = two resources).

  • 🔹 2. PUT → Replace (Idempotent)

    • Used to update/replace entire resource.

    • If resource doesn’t exist → sometimes creates it.

    • Idempotent (same request many times = no change after first).

  • 🔹 3. PATCH → Partial Update (Idempotent by intention)

    • Used to partially update a resource.

    • Sends only the fields that should be changed.

    • Generally treated as idempotent (depends on implementation).


Interview-ready 1-liner:
"POST is for creating new resources, PUT is for fully replacing an existing resource, and PATCH is for partially updating a resource. POST is not idempotent, but PUT and PATCH are idempotent."


🔹 What is Idempotency?

👉 Idempotency means → making the same request once or multiple times results in the same outcome (no side effects after the first execution).

Think of it like a remote control power button:

  • Press once → TV turns ON.

  • Press again → TV stays ON (no extra effect).
    ✅ That’s idempotent.

But if every time you press it, a new TV appears in your room → 😅 ❌ That’s not idempotent (like POST).

Why is Idempotency Important?

  1. Reliability in network calls

    • In real systems, requests may be retried (due to timeout, crash, load balancer retry).

    • Idempotency ensures no duplicate actions (e.g., multiple charges in payment).

  2. Safe APIs

    • Clients can retry safely without worrying about unexpected behavior.

  3. Consistency

    • Helps avoid data corruption when the same request is sent many times.


 ✅ Interview-Ready Answer (1-liner):

"Idempotency means that making the same request multiple times has the same effect as making it once. It’s important in REST APIs to avoid duplicates, ensure safe retries, and maintain consistency."

2️⃣ Idempotency Keys (Most Common in Payments & Orders)

  • Client generates a unique request ID / token for every request.

  • Server stores this key and ensures the same request is not processed twice.

  • If the same key comes again → server returns the same result, not a new transaction.

  • This is how Stripe, PayPal, UPI ensure no double charges.


4️⃣ Check Before Write

  • Before creating data, check if it already exists.

    • Example: if orderId exists → don’t insert again.

5️⃣ Caching Responses

  • Store response for a given request (with idempotency key).

  • If the same request comes again → return cached response instead of re-processing.

🔹 Example: Payment API with Idempotency

  1. Client sends payment request with unique idempotency key.

  2. Server checks DB if key exists:

    • If yes → return old response.

    • If no → process payment, store key + response, return success.

Interview-Ready Answer:
"We achieve idempotency by using the right HTTP methods, idempotency keys (like in payment APIs), database constraints, and by checking before writing. In real projects, I’ve used idempotency keys and unique transaction IDs to ensure safe retries without duplicates."


Spring Boot makes payload validation using annotations + @Valid.


🔹 How to Validate Incoming Payload

1️⃣ Add Dependency (if not already)

In pom.xml (Spring Boot starter has it by default, but explicitly:):

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-validation</artifactId>

</dependency>

✅ Here we’re using annotations like:

  • @NotNull → field must not be null

  • @NotBlank → not empty & not just spaces

  • @Email → must be valid email format

  • @Min / @Max → number limits

👉 @Valid ensures Spring validates the incoming payload before reaching the method.
If validation fails → Spring throws MethodArgumentNotValidException.


🔥 Interview-Ready Answer:

"We validate incoming payloads in Spring Boot using Jakarta Validation annotations like @NotNull, @Email, @Min.
We apply them on DTO fields, and use @Valid in controller methods. If validation fails, Spring throws an exception which we handle with @RestControllerAdvice.
This ensures clean validation without manual checks."


2️⃣ Types of Tests in Spring Boot

  1. Unit Test → test single class/method without Spring context.

  2. Integration Test → load Spring context and test multiple layers together.

  3. Web Layer Test → test only controller layer (mock MVC).



🔥 Interview-Ready Answer

*"In Spring Boot, I test applications in three levels:

  • Unit Tests with JUnit & Mockito for service/business logic,

  • Integration Tests with @SpringBootTest to load context,

  • Web Layer Tests using MockMvc to test controllers and REST APIs.
    I also configure a separate test profile with H2 DB for database testing.
    This ensures full coverage without depending on production services."*



 Ways to Handle Exceptions in Spring Boot

1️⃣ Using try-catch (Basic)

2️⃣ Using @ExceptionHandler (Controller Level)

Handle exceptions in a specific controller:

3️⃣ Using @ControllerAdvice (Global Exception Handler ✅ Best Way)

Centralized exception handling for all controllers:

✅ Best practice for real projects.
✅ Handles exceptions across the whole application.


🔥 Interview-Ready Answer

"In my Spring Boot projects, I handle exceptions using @ControllerAdvice and @ExceptionHandler for centralized handling. This allows me to map specific exceptions to proper HTTP status codes (400, 404, 500, etc.) and return user-friendly error responses.
I also use ResponseStatusException for quick errors and create custom exceptions for business logic. This ensures my APIs are consistent, clean, and easy to debug."


 Ways to Exclude Classes from Component Scan



🟢 Problem:

Spring Boot automatically scans and creates beans for all @Component, @Service, @Repository, etc.

👉 But sometimes, you don’t want a class to become a bean. Example:

  • You have a TestService class used only in tests.

  • But in real project, you don’t want it to load.

🟢 Solution → Exclude class from scanning

✅ Way 1: Exclude by Class
@SpringBootApplication(
    excludeFilters = {
        @ComponentScan.Filter(
            type = FilterType.ASSIGNABLE_TYPE,
            value = TestService.class
        )
    }
)
👉 Here TestService will NOT be loaded as a bean.

✅ Way 2: Exclude by Annotation
@ComponentScan(
    excludeFilters = {
        @ComponentScan.Filter(
            type = FilterType.ANNOTATION,
            value = Deprecated.class
        )
    }
)

👉 Any class marked @Deprecated will be ignored.


✅ Way 3: Exclude using Condition
@Component
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
👉 If feature.enabled=false in application.properties, this bean won’t load.

🟢 Super Easy Interview Answer:

"By default, Spring scans all components. But if I don’t want a class to load, I can exclude it using @ComponentScan.excludeFilters. I can exclude by class, annotation, or using conditions like @ConditionalOnProperty."


🟢 What is Component Scan?

👉 @ComponentScan tells Spring:
“Hey, go look inside this package and find all classes with annotations like @Component, @Service, @Repository, @Controller, etc., then create beans for them.”


🟢 How it Works (Step by Step)

  1. Spring Boot starts → looks at @SpringBootApplication.

    • This annotation already has @ComponentScan inside it.

    • By default, it scans the package where the main class is present and all its sub-packages.

  2. Spring looks for stereotype annotations:

    • @Component

    • @Service

    • @Repository

    • @Controller / @RestController

  3. Spring creates beans for those classes and stores them in the Spring IoC Container.

  4. Later, when you @Autowired something → Spring knows where to get the bean from.



🟢 Top 3 Performance Bottlenecks in Microservices

1. Network Latency & Communication Overhead

  • Microservices talk to each other over HTTP/gRPC/Kafka.

  • Too many synchronous REST calls (service A → service B → service C) can make the system slow & fragile.
    ⚡ Fix: Use asynchronous messaging (Kafka), caching, and API Gateway.

2. Database Bottleneck

  • If all services hit the same database (monolithic DB), it becomes the choke point.

  • Common issues: slow queries, too many connections, locking.
    ⚡ Fix: Use Database per Service, caching (Redis), indexing, and read replicas.

3. Service Scalability & Resource Limits

  • If one service can’t handle load (e.g., limited CPU/memory or no autoscaling), the whole system slows.

  • Example: Payment Service handling 10k TPS but Notification Service handles only 1k TPS → system breaks.
    ⚡ Fix: Horizontal scaling, load balancing, circuit breakers (Resilience4j).

🏦 Real-World Example: UPI Transaction Flow

When you send money via PhonePe/Google Pay/Paytm, these steps happen:

  1. App → PSP Bank → NPCI Switch → Beneficiary Bank → NPCI → PSP → App
    (Multiple microservices & APIs in between).

🔥 Where Bottlenecks Appear?

1. Network Latency (Service-to-Service calls)

  • If PSP Bank service → NPCI Switch → Beneficiary Bank involves many synchronous REST calls, the transaction takes longer.

  • Example: Payment takes 5-10 seconds instead of <2 seconds.

  • ❌ Bottleneck: Too many hops, slow network calls.

  • ✅ Fix: Use asynchronous communication (Kafka) where possible, or optimize service chaining.

2. Database Bottleneck (High Volume Transactions)

  • Suppose NPCI Switch has a central DB storing transaction logs.

  • On festivals like Diwali, transactions spike 🔥 (millions/sec).

  • If DB queries are slow or DB locks occur → entire UPI system slows down.

  • ❌ Bottleneck: Single DB can’t handle load.

  • ✅ Fix: Use sharding, replicas, caching (Redis), DB per service.

3. Service Scalability Issue

  • Example: Notification Service sends SMS/Push notifications after payment.

  • Payment Service can handle 10k TPS but Notification Service can only handle 1k TPS → transactions succeed but notifications fail/delay.

  • ❌ Bottleneck: One weak service drags system down.

  • ✅ Fix: Autoscaling (Kubernetes), load balancing, circuit breakers (Resilience4j/Hystrix).

🟢 Interview-Ready Example Answer:

"In my work at NPCI, I saw bottlenecks during UPI high-load events.

  1. Network latency – too many synchronous calls between PSPs, NPCI switch, and banks slowed response times.

  2. Database bottleneck – central DB handling transaction logs became overloaded during festivals.

  3. Service scalability – supporting services like notifications couldn’t handle the same load as the payment core service.
    We solved this using Kafka for async communication, DB sharding + Redis caching, and Kubernetes autoscaling with circuit breakers."


🔎 How do we monitor Microservices?

Think of monitoring in 3 layers:


1. Logs (What happened?)

  • Each service writes logs (errors, transactions, events).

  • Use Centralized Logging (instead of checking logs in each server).

  • Tools:

    • ELK Stack (Elasticsearch + Logstash + Kibana)

    • Splunk

    • Graylog

👉 Example:

When UPI payment fails, logs help trace which microservice failed (PSP, NPCI switch, or Bank).


2. Metrics (What is the health?)

  • Collect numbers like:

    • Request per second (RPS)

    • Average response time (latency)

    • Error rate

    • Memory/CPU usage

  • Tools:

👉 Example:

If transaction latency suddenly jumps from 200ms → 2s, alert gets triggered.


3. Tracing (Where is the delay?)

  • In microservices, a request flows through many services.

  • Distributed tracing shows the path + time taken at each step.

  • Tools:

    • Zipkin

    • Jaeger

    • OpenTelemetry

👉 Example:

In UPI, if delay is inside Beneficiary Bank API, tracing shows this hop took 1.5s.



🔎 What is Resilience?

👉 Resilience means the system can handle failures or high load and still keep working without crashing.
It’s like a shock absorber in a car 🚗 — even if the road is rough (failures, high traffic), the car (system) keeps running smoothly.


🛡 How to Ensure Resilience under High Load?

1. Load Balancing

  • Distribute requests across multiple service instances.

  • Prevents one server from being overloaded.

  • Tools: Nginx, HAProxy, Spring Cloud LoadBalancer, Kubernetes Service.

 


2. Auto Scaling

  • Add/remove service instances based on traffic.

  • Example: During peak UPI transactions (festival sale), scale from 5 → 50 instances.

  • Done via Kubernetes HPA or AWS AutoScaling.

3. Circuit Breaker Pattern

  • If one service is slow/failing, stop calling it temporarily.

  • Prevents cascading failures.

  • Tool: Resilience4j, Hystrix.

👉 Example: If Beneficiary Bank API is down, Payment Service won’t keep retrying and crashing. Instead, it will fail fast.


 

4. Caching

  • Reduce load on DB/services by storing frequent responses in Redis or in-memory cache.

👉 Example: Store UPI bank details mapping in cache instead of DB calls.


5. Rate Limiting & Backpressure

  • Protects system from traffic spikes.

  • Example: If max TPS is 10k, reject extra requests with "try later".

  • Tools: API Gateway, Bucket4j.



🟢 Interview-Ready Answer

"Resilience means the system can handle failures and high load without going down.
In my project, we ensured resilience using:


🔹 First: What does Statelessness mean?

In REST, stateless means:
👉 The server does not store any client session between requests.
👉 Each request from the client must contain all the info needed (auth, data, context) to process it.

So, every request is independent — like a new conversation.


🔹 How RESTful APIs achieve Statelessness?

  1. No Server-Side Session

    • REST avoids keeping user state (like login session) in server memory.

    • This makes servers lightweight and scalable.

  2. Use of Tokens (JWT, OAuth2)

    • Instead of server storing user login, client sends token with each request.

    • Server checks token → identifies user → processes request.

    • No need to "remember" previous request.

    • 🔹 Easy Analogy 📞

      • Stateful: You call customer care. They say “Please hold, I remember your last details”. Only that agent can continue.

      • Stateless (REST): Every time you call, you provide all details again (ID, phone, issue). Any agent can help because all info is in the request.

    • Interview Answer (Short):
      "REST APIs achieve statelessness by not storing client session on the server. Instead, each request contains all necessary data (like authentication tokens, parameters, and context). This makes services scalable, since any server instance can handle any request independently."

 

🔹 What is Service Discovery?

👉 In a microservices architecture, you have many services running (User Service, Payment Service, Notification Service, etc.).

  • Each service may run on different servers/ports.

  • Services need to find and talk to each other dynamically.

Service Discovery solves this problem: it tells a service “where is the other service right now?”


🔹 How It Works

1️⃣ Service Registry

  • A central database of all available service instances.

  • Example: Eureka Server, Consul, Zookeeper.

  • Each service registers itself on startup.

2️⃣ Service Registration

  • When a service starts, it tells the registry:

  • I am PaymentService at 10.0.0.5:8081

  • Registry keeps track of it.

3️⃣ Service Lookup / Discovery

  • When a client or another service wants to call PaymentService:

    • It asks the registry: “Where is PaymentService?”

    • Registry replies with the current instance IP & port.


🔹 Why it is Important

  1. Dynamic Scaling → services can scale up/down; discovery updates automatically.

  2. No Hardcoding → don’t need fixed IP/port in code.

  3. High Availability → if one instance fails, client can use another.


         what are the maven command you use daily ?


Command Purpose
mvn clean  Deletes target folder (old compiled files).
mvn compile                      Compiles project source code.
mvn clean install -U
Forces update of snapshots and dependencies.



----------------------------


 





Comments

Popular posts from this blog

Two Sum II - Input Array Is Sorted

Comparable Vs. Comparator in Java

Increasing Triplet Subsequence