✅ Why is @Qualifier needed?
Suppose you have two implementations of an interface, and both are marked with @Component.
Spring won’t know which one to inject into a dependent class.
🔹 Syntax
@Autowired
@Qualifier("beanName")
private MyService myService;
✅ Example
1. Define an Interface
public interface PaymentService {
void pay();
}
2. Two Implementations
@Component("paypalService")
public class PaypalService implements PaymentService {
public void pay() {
System.out.println("Paid via PayPal");
}
}
@Component("creditCardService")
public class CreditCardService implements PaymentService {
public void pay() {
System.out.println("Paid via Credit Card");
}
}
3. Injecting with @Qualifier
@Component
public class PaymentProcessor {
@Autowired
@Qualifier("paypalService") // specify which implementation to use
private PaymentService paymentService;
public void processPayment() {
paymentService.pay(); // Output: Paid via PayPal
}
}
🔹 Without @Qualifier, you'll get an error like:
No qualifying bean of type 'PaymentService' available: expected single matching bean but found 2:
paypalService,creditCardService
✅ What is @ControllerAdvice?
@ControllerAdvice is a specialized @Component used to define global exception handling,
binding, and model attribute logic.
You can define multiple @ExceptionHandler methods within it to handle different
exceptions.
🔹 Key Annotations Used
Annotation Purpose
@ControllerAdvice Marks class as global exception handler
@ExceptionHandler Handles specific exception types
@ResponseStatus Sets the HTTP response status
@ResponseBody Returns object as JSON/XML directly in response body
✅ Example: Centralized Exception Handling using @ControllerAdvice
1. Create a Custom Exception
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
2. Create a Global Exception Handler Class
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorResponse handleGenericException(Exception ex) {
return new ErrorResponse("INTERNAL_ERROR", "An unexpected error occurred.");
}
}
3. Create a Response Wrapper (Optional)
public class ErrorResponse {
private String code;
private String message;
public ErrorResponse(String code, String message) {
this.code = code;
this.message = message;
}
// Getters and Setters
}
4. Throw Exception in Controller
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public String getUser(@PathVariable int id) {
if (id != 1) {
throw new UserNotFoundException("User with ID " + id + " not found");
}
return "User Found!";
}
}
🟨 Output Example
Response:
json
CopyEdit
{
"code": "USER_NOT_FOUND",
"message": "User with ID 2 not found"
}
Status Code: 404 Not Found
✅ What is AOP in Spring Boot?
AOP (Aspect-Oriented Programming) is a programming paradigm in Spring that allows you to
separate cross-cutting concerns (e.g., logging, security, transactions) from the main business logic.
In Spring Boot, AOP is implemented using Spring AOP, which uses proxies under the hood.
🔹 Key Terminology in AOP
Term Description
Aspect A module that encapsulates cross-cutting logic (e.g., LoggingAspect)
Join Point A point in the application where an aspect can be applied (e.g., method call)
Advice The actual action taken at a join point (e.g., @Before, @After, etc.)
Pointcut A predicate expression that matches join points
🔹 Common AOP Annotations
Annotation Purpose
@Aspect Marks a class as an aspect
@Before Runs before a method
@After Runs after a method
@AfterReturning Runs after a method returns successfully
@AfterThrowing Runs if a method throws an exception
✅ AOP Example in Spring Boot
1. Add Dependency (in pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. Create a Service
@Service
public class UserService {
public String getUser(int id) {
return "User with ID: " + id;
}
}
3. Create an Aspect
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.demo.service.UserService.*(..))")
public void logBeforeMethod(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
@AfterReturning(
pointcut = "execution(* com.example.demo.service.UserService.*(..))",
returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("Method " + joinPoint.getSignature().getName() + " returned: " + result);
}
}
4. Use the Service in a Controller
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/{id}")
public String getUser(@PathVariable int id) {
return userService.getUser(id);
}
}
🔍 Output Example (Logs)
Before method: getUser
Method getUser returned: User with ID: 10
✅ 1. Spring Boot Core Annotations
Annotation Description
Combines @Configuration, @EnableAutoConfiguration, and
@SpringBootApplication
@ComponentScan. Entry point of Spring Boot app.
Tells Spring Boot to configure the application automatically based on
@EnableAutoConfiguration
dependencies.
Tells Spring to scan the package for components (like @Component,
@ComponentScan
@Service, etc.).
Marks a class as a source of bean definitions. Replaces XML
@Configuration
configuration.
✅ 2. Dependency Injection & Bean Management
Annotation Description
@Autowired Injects beans automatically by type.
@Qualifier Specifies which bean to inject when multiple beans of the same type exist.
@Bean Declares a bean in Java config (@Configuration class).
@Component Generic stereotype for a Spring-managed component.
@Service Marks a service layer component. Treated same as @Component.
@Repository Marks DAO (Data Access Object). Enables exception translation.
@Primary Indicates that a bean should be given preference when multiple candidates exist.
@Scope Defines the scope of a bean (singleton, prototype, etc.).
✅ 3. Spring MVC / Web Annotations
Annotation Description
Combines @Controller + @ResponseBody. Used to
@RestController
build RESTful APIs.
@Controller Marks a web controller for MVC pattern.
Maps HTTP requests to handler methods (can be
@RequestMapping
used at class or method level).
@GetMapping, @PostMapping,
Shortcut annotations for common HTTP methods.
@PutMapping, @DeleteMapping
@RequestParam Binds a query parameter to a method argument.
@PathVariable Binds URI template variable to method argument.
@RequestBody Binds request JSON body to a method parameter.
@ResponseBody Returns Java object as response (usually JSON).
@ResponseStatus Customizes HTTP response status code.
✅ 4. Validation Annotations
Annotation Description
@Valid / @Validated Triggers validation on a method parameter or field.
@NotNull, @Size, @Min, @Max, Bean Validation annotations for field-level validation (from
@Email etc. javax.validation).
✅ 5. Exception Handling Annotations
Annotation Description
@ControllerAdvice Global exception handler across all controllers.
@ExceptionHandler Handles a specific exception in a controller or @ControllerAdvice.
✅ 6. JPA & Database Annotations
Annotation Description
@Entity Marks a class as a JPA entity.
@Table(name = "table_name") Specifies table name for the entity.
@Id Marks the primary key.
@GeneratedValue Specifies generation strategy for primary key.
@Column Maps a field to a specific DB column.
@OneToOne, @OneToMany, @ManyToOne,
Defines relationships between entities.
@ManyToMany
Specifies the foreign key column for a
@JoinColumn
relationship.
✅ 7. AOP (Aspect-Oriented Programming)
Annotation Description
@Aspect Marks a class as an Aspect.
@Before, @After, @Around, @AfterReturning, Define pointcut methods for aspect
@AfterThrowing logic.
✅ 8. Scheduling & Asynchronous Processing
Annotation Description
@Scheduled Runs a method on a schedule (cron, fixedRate, etc.).
@EnableScheduling Enables scheduling support.
@Async Executes a method asynchronously in a separate thread.
@EnableAsync Enables async processing support.
✅ 9. Spring Security
Annotation Description
@EnableWebSecurity Enables Spring Security configuration.
@PreAuthorize, @PostAuthorize Method-level authorization using SpEL.
@Secured Specifies security roles for methods.
@WithMockUser Used in unit testing to mock a user.
✅ 10. Testing Annotations
Annotation Description
@SpringBootTest Bootstraps entire Spring context for testing.
@WebMvcTest Tests only MVC layer (e.g., controllers).
@DataJpaTest Tests only JPA components (e.g., repositories).
@MockBean Creates a mock and injects it into the Spring context.
✅ JAVA STREAM
✅ 1. Convert List to Stream and Print
▶ Converts a list to a stream and prints each element.
list.stream().forEach(System.out::println);
✅ 2. Filtering Elements
▶ Filters elements starting with 'A'.
list.stream().filter(s -> s.startsWith("A")).collect(Collectors.toList());
✅ 3. Mapping Elements
▶ Transforms each element to uppercase.
list.stream().map(String::toUpperCase).collect(Collectors.toList());
✅ 4. Sorting Elements
▶ Returns a sorted list in natural order.
list.stream().sorted().collect(Collectors.toList());
✅ 5. Custom Sorting
▶ Sorts strings by length.
list.stream().sorted(Comparator.comparing(String::length)).collect(Collectors.toList());
✅ 6. Limit and Skip
▶ Skips first 2 elements and takes next 3.
list.stream().skip(2).limit(3).collect(Collectors.toList());
✅ 7. Distinct Elements
▶ Removes duplicates from the stream.
list.stream().distinct().collect(Collectors.toList());
✅ 8. Count Matching Elements
▶ Counts elements whose length > 3.
list.stream().filter(e -> e.length() > 3).count();
✅ 9. Check if Any Match
▶ Returns true if any element contains "z".
list.stream().anyMatch(e -> e.contains("z"));
✅ 10. All Match / None Match
list.stream().allMatch(e -> e.length() > 1);
▶ Checks if all/none match the condition.
list.stream().noneMatch(e -> e.isEmpty());
✅ 11. Find First / Find Any
▶ Returns first element or default if empty.
list.stream().findFirst().orElse("default");
✅ 12. Reduce to a Single Value
▶ Reduces stream to single value by concatenation.
list.stream().reduce("", (a, b) -> a + b);
✅ 13. Collect to List, Set, or Map
list.stream().collect(Collectors.toSet());
▶ Collects stream into different collections.
map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
✅ 14. Group By
▶ Groups strings by their length into a map.
list.stream().collect(Collectors.groupingBy(String::length));
✅ 15. Partition By
▶ Partitions stream into two groups based on predicate.
list.stream().collect(Collectors.partitioningBy(s -> s.length() > 3));
✅ 16. FlatMap
▶ Flattens nested lists into a single list.
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
✅ 17. Peek (for Debugging)
▶ Performs an action (like print) on each element during stream flow.
list.stream().peek(System.out::println).collect(Collectors.toList());
✅ 18. Stream from Arrays
▶ Creates a stream from a primitive array.
Arrays.stream(new int[]{1, 2, 3});
✅ 19. IntStream for Ranges
▶ Creates a stream of integers in a range.
IntStream.range(1, 5).forEach(System.out::print); // 1 to 4
✅ 20. Stream of Objects
▶ Creates a stream directly from values.
Stream.of("a", "b", "c").collect(Collectors.toList());
✅CACHE IN SPRINGBOOT
1. Add Required Dependency
If using Spring Boot Starter, include in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
If you're using a specific cache provider like Ehcache, Redis, etc., include that too.
2. Enable Caching in Application
In your main application class:
@SpringBootApplication
@EnableCaching
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
3. Use Cache Annotations
You can use several caching annotations:
Annotation Purpose
@Cacheable Caches the result of a method.
@CachePut Updates the cache with a new value.
@CacheEvict Removes entries from the cache.
🔹 @Cacheable Example
@Service
public class ProductService {
@Cacheable("products")
public Product getProductById(String id) {
simulateSlowService(); // Simulate DB call
return new Product(id, "Product " + id);
}
}
📌 Explanation:
First call with a new id will fetch and cache result.
Subsequent calls with the same id will return cached result.
🔹 @CachePut Example
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
return productRepository.save(product);
}
📌 Updates both the database and cache entry.
🔹 @CacheEvict Example
@CacheEvict(value = "products", key = "#id")
public void deleteProduct(String id) {
productRepository.deleteById(id);
}
📌 Removes cache entry after deletion.
4. Configure Cache Provider
Spring Boot uses ConcurrentHashMap (in-memory) by default. You can switch to more powerful
options like:
Ehcache
Caffeine
Redis
Hazelcast
Example: Enable Caffeine in application.yml:
yaml
CopyEdit
spring:
cache:
type: caffeine
And add the dependency:
xml
CopyEdit
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
5. Advanced Configuration (Optional)
Time to Live
Max size
Custom key generator
Example with Caffeine TTL:
yaml
CopyEdit
spring:
cache:
caffeine:
spec: maximumSize=500,expireAfterWrite=10m
✅ JWT Security:
🧠 Interview-Focused Summary
Concept Notes
Stateless No session on server, only JWT
Filter Intercepts request before it hits controller
AuthenticationManager Authenticates user credentials
SecurityContextHolder Stores user details for current request
Encryption Uses HS256 with secret key
Storage JWT is stored on client-side (typically localStorage or cookies)
✅ JWT Authentication & Authorization Flow (SSO-style)
🔐 1. User Requests Login
The client (e.g., browser) redirects the user to an external authentication server (SSO server).
User provides credentials (e.g., username/password).
🔑 2. Token Generation by External Auth Server
The SSO server:
o Authenticates credentials.
o Generates a JWT token signed with a secret/private key.
o Embeds user details and roles/permissions into the JWT payload.
o Sends this token back to the client.
📥 3. Client Receives and Stores Token
Client stores the JWT token (in memory, local storage, or secure cookie).
All subsequent requests to your Spring Boot app include:
Authorization: Bearer <jwt_token>
🔍 4. Request Received by Spring Boot App
Spring Security intercepts the request.
Extracts the JWT token from the Authorization header.
🧾 5. Token Validation
The application validates the token:
o Signature check (to ensure it's unaltered).
o Expiration check (token expiry date/time).
o Issuer/audience (optional, to verify it came from trusted SSO server).
👤 6. User Details & Roles Extraction
If token is valid:
o Extracts the username and roles/authorities from JWT claims.
o Spring Security sets this in the SecurityContext.
o The request is now authenticated and authorized based on roles.
🔐 7. Access Control
Spring Security uses extracted roles to:
o Allow access to the requested resource.
o Deny access (403 Forbidden) if roles are insufficient.
✅ Design Pattern in Microservices
Pattern Purpose
API Gateway Central entry point, routing, auth
Service Discovery Dynamic service registration and lookup
Circuit Breaker Resilience and fault tolerance
Config Server Centralized configuration management
Database per Service Data isolation and independence
Event-Driven Asynchronous, loosely coupled communication
Saga Distributed transaction management