Java & Spring Boot Interview Preparation
Comprehensive Q&A — Both Interview Sessions
Generated: Fri May 29 2026 | 32 Questions Covered
1. What annotation is used for Component Scan in Spring Boot?
The primary annotation is @ComponentScan (or @SpringBootApplication which includes it).
Key Annotations:
• @ComponentScan — Tells Spring where to scan for @Component, @Service, @Repository,
@Controller beans.
• @SpringBootApplication — Composite annotation that includes @Configuration +
@EnableAutoConfiguration + @ComponentScan.
• @Component — Generic stereotype; marks a class as a Spring-managed bean.
• @Service — Specialization of @Component for service layer.
• @Repository — Specialization for DAO/repository layer (also adds exception translation).
• @Controller / @RestController — For web layer beans.
Example: Scanning a specific package
@SpringBootApplication
@ComponentScan(basePackages = {"[Link]", "[Link]"})
public class MyApp {
public static void main(String[] args) {
[Link]([Link], args);
}
}
If no basePackages is specified, Spring scans the package of the annotated class and all its sub-
packages.
2. Java Streams — Filter Employee list where Dept = HR (with possible NULL
dept)
Employee POJO:
public class Employee {
private int id;
private String name;
private String dept;
// constructor, getters, setters
}
Filter employees where dept = HR (handling NULL safely):
List<Employee> hrEmployees = [Link]()
.filter(e -> "HR".equals([Link]())) // null-safe: "HR".equals(null) =
false
.collect([Link]());
Alternative with [Link] check:
List<Employee> hrEmployees = [Link]()
.filter(e -> [Link]() != null && [Link]().equals("HR"))
.collect([Link]());
Get ONLY employee names from Dept = IT:
List<String> itNames = [Link]()
.filter(e -> "IT".equals([Link]()))
.map(Employee::getName)
.collect([Link]());
Get UNIQUE employee names from Dept = IT:
List<String> uniqueITNames = [Link]()
.filter(e -> "IT".equals([Link]()))
.map(Employee::getName)
.distinct()
.collect([Link]());
3. RestTemplate — GET call with headers
RestTemplate is Spring's synchronous HTTP client (pre-WebClient era).
Basic GET call:
RestTemplate restTemplate = new RestTemplate();
String url = "[Link]
String response = [Link](url, [Link]);
GET call with custom headers:
HttpHeaders headers = new HttpHeaders();
[Link]("Authorization", "Bearer " + token);
[Link]("Content-Type", "application/json");
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<MyResponse> response = [Link](
"[Link]
[Link],
entity,
[Link]
);
MyResponse body = [Link]();
Note: RestTemplate is in maintenance mode since Spring 5. WebClient is the recommended
replacement for new code.
4. Spring Cloud Config Server — setup from scratch
Spring Cloud Config Server provides centralized externalized configuration for distributed systems.
Server Setup:
1. Add dependency in [Link]:
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2. Annotate main class:
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApp {
public static void main(String[] args) {
[Link]([Link], args);
}
}
3. [Link] of Config Server:
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: [Link]
default-label: main
Client Setup:
In [Link] (or [Link] with [Link]):
spring:
application:
name: payment-service
config:
import: optional:configserver:[Link]
Config files in Git repo are named: {application}-{profile}.yml e.g., [Link]
5. Singleton Bean vs Singleton Class
These are two different patterns though both result in a 'single instance'.
Aspect Singleton Bean Singleton Class (Design
Pattern)
Scope One instance per Spring One instance per
ApplicationContext JVM/ClassLoader
Control Managed by Spring IoC Managed by the class itself
container
Multiple contexts Multiple Spring contexts = Truly single in JVM
multiple instances
Testability Easy to mock/replace in tests Hard to mock (private
constructor)
Thread Safety Not guaranteed; must be Not guaranteed; must be
coded carefully coded carefully
Singleton Class example (double-checked locking):
public class SingletonClass {
private static volatile SingletonClass instance;
private SingletonClass() {}
public static SingletonClass getInstance() {
if (instance == null) {
synchronized ([Link]) {
if (instance == null) instance = new SingletonClass();
}
}
return instance;
}
}
6. @Conditional Annotation in Spring Boot
@Conditional allows bean registration based on a condition. Spring Boot auto-configuration heavily
uses it.
Common Conditional Annotations:
• @ConditionalOnProperty — Bean created only if a property exists/has a value
• @ConditionalOnClass — Bean created only if a class is on the classpath
• @ConditionalOnMissingBean — Bean created only if no bean of that type exists
• @ConditionalOnExpression — Evaluate a SpEL expression
• @ConditionalOnWebApplication — Only in a web context
Example:
// Bean only created when [Link]=true
@Bean
@ConditionalOnProperty(name = "[Link]", havingValue = "true")
public PaymentService paymentService() {
return new PaymentService();
}
// Bean created only when no existing DataSource bean
@Bean
@ConditionalOnMissingBean([Link])
public DataSource defaultDataSource() {
return new EmbeddedDatabaseBuilder().build();
}
7. WebClient — How and Where is it used?
WebClient is the reactive, non-blocking HTTP client introduced in Spring 5 (spring-webflux). It is the
recommended replacement for RestTemplate.
When to use WebClient:
• Reactive / non-blocking applications (Spring WebFlux)
• High-concurrency microservice-to-microservice calls
• Streaming responses
• Can also be used in traditional Spring MVC apps (blocking mode with .block())
Dependency:
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Creating and using WebClient:
@Bean
public WebClient webClient() {
return [Link]()
.baseUrl("[Link]
.defaultHeader(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE)
.build();
}
// GET call
Mono<Employee> employee = [Link]()
.uri("/employees/{id}", 1)
.header("Authorization", "Bearer " + token)
.retrieve()
.bodyToMono([Link]);
// Blocking call (for use in non-reactive context)
Employee emp = [Link]();
8. Disadvantages of RestTemplate
• Synchronous and blocking — thread is held for entire request duration
• Poor performance under high concurrency — one thread per request model
• In maintenance mode since Spring 5 — no new features being added
• Does not support reactive programming model
• No built-in retry or circuit breaker support (need extra libraries)
• Error propagation across services requires manual handling
• Verbose boilerplate for adding headers/auth on every call
Recommendation: Migrate to WebClient which supports both blocking and non-blocking modes.
9. JUnit Testing in Spring Boot
Spring Boot uses JUnit 5 (JUnit Jupiter) + Mockito for unit and integration testing.
Key Annotations:
• @SpringBootTest — Loads full application context for integration tests
• @WebMvcTest — Only loads web layer (Controllers)
• @MockBean — Creates a Mockito mock and adds to Spring context
• @Mock / @InjectMocks — Pure Mockito; no Spring context
• @ExtendWith([Link]) — Enables Mockito in JUnit 5
Service layer unit test:
@ExtendWith([Link])
class PaymentServiceTest {
@Mock
private PaymentRepository paymentRepository;
@InjectMocks
private PaymentService paymentService;
@Test
void testProcessPayment_Success() {
Payment payment = new Payment(1L, 500.0, "PENDING");
when([Link](any([Link]))).thenReturn(payment);
Payment result = [Link](payment);
assertEquals("PENDING", [Link]());
verify(paymentRepository, times(1)).save(payment);
}
}
Controller layer test with MockMvc:
@WebMvcTest([Link])
class PaymentControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private PaymentService paymentService;
@Test
void testGetPayment() throws Exception {
when([Link](1L)).thenReturn(new Payment(1L, 500.0,
"SUCCESS"));
[Link](get("/payments/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value("SUCCESS"));
}
}
10. Multithreading in Spring Boot — @Async
Spring Boot supports async execution via @Async and @EnableAsync.
Setup:
@SpringBootApplication
@EnableAsync
public class MyApp { ... }
Async method example:
@Service
public class NotificationService {
@Async
public CompletableFuture<String> sendEmail(String to) {
// runs in a separate thread
[Link]("Sending email on: " +
[Link]().getName());
return [Link]("Email sent to " + to);
}
}
Custom Async Executor:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
[Link](5);
[Link](20);
[Link](500);
[Link]("PaymentAsync-");
[Link]();
return executor;
}
}
// Use named executor
@Async("taskExecutor")
public CompletableFuture<Void> processAsync() { ... }
Important: @Async only works when called from OUTSIDE the same bean (Spring proxy limitation).
11. How to Implement Swagger in Spring Boot
Use SpringDoc OpenAPI (recommended for Spring Boot 3.x):
Dependency:
<dependency>
<groupId>[Link]</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
Access Swagger UI at: [Link]
Optional configuration:
@OpenAPIDefinition(
info = @Info(title = "Payment API", version = "1.0", description = "BofA
Payments Platform")
)
@Configuration
public class SwaggerConfig {}
// Annotate controller endpoints
@Operation(summary = "Get payment by ID")
@ApiResponse(responseCode = "200", description = "Payment found")
@GetMapping("/payments/{id}")
public ResponseEntity<Payment> getPayment(@PathVariable Long id) { ... }
12. Logging in Spring Boot
Spring Boot uses SLF4J as the logging facade, with Logback as the default implementation.
Basic Usage:
import [Link];
import [Link];
@Service
public class PaymentService {
private static final Logger log =
[Link]([Link]);
public void processPayment(Payment p) {
[Link]("Processing payment id={}, amount={}", [Link](),
[Link]());
[Link]("Payment details: {}", p);
[Link]("Payment failed for id={}", [Link](), exception);
}
}
[Link] configuration:
logging:
level:
root: INFO
[Link]: DEBUG
file:
name: logs/[Link]
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
For Log4j2, exclude default Logback and add Log4j2 starter dependency instead.
13. Method Overriding vs Method Overloading
Aspect Overloading Overriding
Type Compile-time (Static) Runtime (Dynamic)
polymorphism polymorphism
Location Same class Parent & Child class
Signature Different parameters (type/count) Same method signature
Return type Can differ Must be same (or covariant)
@Override Not used Should always use
Overloading example:
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; } // overloaded
Overriding example:
class Animal { public void sound() { [Link]("Some sound"); } }
class Dog extends Animal {
@Override
public void sound() { [Link]("Bark"); } // overridden
}
14. Java 8 Streams — Display ODD numbers from 1 to 100
Java 8 Streams provide a declarative way to process sequences of elements.
Solution:
import [Link];
[Link](1, 100)
.filter(n -> n % 2 != 0)
.forEach([Link]::println);
// Collect to list
List<Integer> oddNumbers = [Link](1, 100)
.filter(n -> n % 2 != 0)
.boxed()
.collect([Link]());
Key Java 8 Stream Operations:
• Intermediate (lazy): filter(), map(), flatMap(), distinct(), sorted(), limit()
• Terminal (eager): forEach(), collect(), reduce(), count(), findFirst()
15. What is a Map Collection? Time Complexity of Add/Retrieve
Map is a key-value data structure. Common implementations: HashMap, LinkedHashMap, TreeMap,
ConcurrentHashMap.
Implementation Get Put Ordered?
HashMap O(1) avg O(1) avg No
LinkedHashMap O(1) avg O(1) avg Insertion order
TreeMap O(log n) O(log n) Sorted
(natural/comparator
)
How HashMap O(1) works:
1. [Link]() is computed → determines bucket index.
2. If no collision → direct access → O(1).
3. With collisions → Java 8+ uses a balanced tree (TreeMap) within bucket when bucket size > 8 →
O(log n) worst case.
4. Effective O(1) assumes a good hash function and load factor <= 0.75.
16. Spring Boot Configuration Hierarchy (Multiple Environments)
Spring Boot loads configuration in the following order (later sources override earlier):
• 1. Default properties (hardcoded in code or @PropertySource)
• 2. [Link] or [Link] in classpath
• 3. Profile-specific: application-{profile}.yml (e.g., [Link], [Link])
• 4. Config Server (Spring Cloud Config) — if configured
• 5. Environment variables (OS-level)
• 6. Command-line arguments (--[Link]=8081)
[Link] example with profiles:
# [Link] (default)
server:
port: 8080
spring:
profiles:
active: dev
---
# [Link]
spring:
datasource:
url: jdbc:oracle:thin:@dev-db:1521:ORCL
---
# [Link]
spring:
datasource:
url: jdbc:oracle:thin:@prod-db:1521:ORCL
17. Building a REST API to Create and Add Users — High Level
Step-by-step: Entity → Repository → Service → Controller
1. Entity:
@Entity
@Table(name = "users")
public class User {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String name;
private String email;
}
2. Repository (for SQL use JpaRepository, for different DBs see below):
// SQL (Oracle, PostgreSQL, MySQL)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}
// MongoDB
@Repository
public interface UserRepository extends MongoRepository<User, String> {}
3. Service:
@Service
public class UserService {
@Autowired private UserRepository userRepository;
public User createUser(User user) { return [Link](user); }
public List<User> getAllUsers() { return [Link](); }
}
4. Controller:
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired private UserService userService;
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User saved = [Link](user);
return [Link]([Link]).body(saved);
}
@GetMapping
public List<User> getAllUsers() { return [Link](); }
}
18. Exception Handling & @ControllerAdvice in Spring Boot
@ControllerAdvice is a global exception handler — intercepts exceptions from all controllers.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse>
handleNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse("NOT_FOUND", [Link]());
return [Link](HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleGeneral(Exception ex) {
ErrorResponse error = new ErrorResponse("INTERNAL_ERROR", "Something
went wrong");
return
[Link](HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
// Custom exception
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String msg) { super(msg); }
}
Without @ControllerAdvice, each controller must handle its own exceptions — verbose and error-
prone.
19. Error Propagation Between Microservices with RestTemplate
Scenario: Service2 calls Service1. Service1 returns 4xx/5xx. How does Service2 handle/propagate
it?
RestTemplate throws HttpClientErrorException (4xx) or HttpServerErrorException (5xx):
@Service
public class Service2 {
@Autowired private RestTemplate restTemplate;
public ResponseEntity<String> callService1(Long id) {
try {
return [Link](
"[Link] + id, [Link]);
} catch (HttpClientErrorException e) {
// 4xx - Service1 client error
[Link]("Client error from Service1: {}", [Link]());
throw new ServiceCallException("Service1 returned: " +
[Link]());
} catch (HttpServerErrorException e) {
// 5xx - Service1 server error
[Link]("Server error from Service1: {}", [Link]());
throw new ServiceCallException("Service1 server error");
} catch (ResourceAccessException e) {
// Network/timeout issue
[Link]("Service1 unreachable: {}", [Link]());
throw new ServiceUnavailableException("Service1 is down");
}
}
}
20. Security Mechanisms for Microservices
Common approaches used in banking/payment microservices:
• JWT (JSON Web Token) — Stateless token-based auth; Service2 passes JWT in
Authorization header to Service1
• OAuth2 + OpenID Connect — Industry standard; Spring Security OAuth2 Resource Server
• API Gateway Authentication — All requests authenticated at gateway (e.g., Kong, AWS API
Gateway)
• mTLS (Mutual TLS) — Certificate-based auth between microservices
• Spring Security — @PreAuthorize, @Secured for method-level security
OAuth2 Resource Server config (Spring Boot 3.x):
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 ->
[Link]([Link]()));
return [Link]();
}
}
// Secured RestTemplate for calling Service1
@Bean
public RestTemplate securedRestTemplate() {
return new RestTemplateBuilder()
.interceptors((req, body, exec) -> {
[Link]().set("Authorization", "Bearer " + getToken());
return [Link](req, body);
}).build();
}
21. flatMap — Example and How to Iterate / Remove Duplicates
flatMap transforms each element into a stream and then flattens all those streams into one.
Example — flatten a list of lists:
List<List<String>> nested = [Link](
[Link]("Alice", "Bob"),
[Link]("Charlie", "Alice"),
[Link]("Dave")
);
// Flatten
List<String> flat = [Link]()
.flatMap(Collection::stream)
.collect([Link]());
// [Alice, Bob, Charlie, Alice, Dave]
// Flatten + remove duplicates
List<String> unique = [Link]()
.flatMap(Collection::stream)
.distinct()
.collect([Link]());
// [Alice, Bob, Charlie, Dave]
Object example — get all skills from all employees:
List<String> allSkills = [Link]()
.flatMap(e -> [Link]().stream()) // each emp has List<String> skills
.distinct()
.sorted()
.collect([Link]());
22. Sequential vs Parallel Streams
Aspect Sequential Stream Parallel Stream
Execution Single thread Fork/Join pool (multiple threads)
Order Maintained Not guaranteed
Performance Better for small data Better for large data & CPU-
intensive
Thread safety Safe Needs careful handling
Usage .stream() .parallelStream()
// Sequential
[Link]().filter(...).collect(...);
// Parallel — use with caution in stateful operations
[Link]().filter(...).collect(...);
23. How to Instantiate Multiple Instances of the Same Class
In Spring, beans are singleton by default. To get multiple instances, use @Prototype scope.
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PaymentProcessor {
private String processorId;
// each getBean() call returns a NEW instance
}
// Usage — inject ApplicationContext to get new instances
@Service
public class PaymentService {
@Autowired
private ApplicationContext context;
public void process() {
PaymentProcessor p1 = [Link]([Link]);
PaymentProcessor p2 = [Link]([Link]);
// p1 != p2 (different instances)
}
}
Note: @Autowired on a prototype bean in a singleton will still give one instance. Use
ApplicationContext or ObjectProvider.
24. @Qualifier Annotation
@Qualifier is used when multiple beans of the same type exist; it specifies which one to inject.
@Component("sqlPaymentRepo")
public class SqlPaymentRepository implements PaymentRepository { ... }
@Component("mongoPaymentRepo")
public class MongoPaymentRepository implements PaymentRepository { ... }
@Service
public class PaymentService {
@Autowired
@Qualifier("sqlPaymentRepo")
private PaymentRepository paymentRepository; // injects
SqlPaymentRepository
}
Without @Qualifier, Spring throws NoUniqueBeanDefinitionException when multiple matching beans
exist.
25. Enabling Auto-Configuration in Spring Boot
@EnableAutoConfiguration (part of @SpringBootApplication) tells Spring Boot to automatically
configure beans based on classpath dependencies.
How it works:
• Spring Boot scans
META-INF/spring/[Link]
• Each auto-config class is annotated with @Conditional* — only applied when conditions are
met
• Example: H2 on classpath + no DataSource bean → Spring Boot auto-configures an in-
memory H2 DataSource
// Full combo — most common
@SpringBootApplication // = @Configuration + @EnableAutoConfiguration +
@ComponentScan
public class App { }
// To exclude specific auto-config:
@SpringBootApplication(exclude = {[Link]})
public class App { }
26. Spring Boot Version Differences — v2.x vs v3.x
Area Spring Boot 2.x Spring Boot 3.x
Java version Java 8/11 Java 17+ (minimum)
Jakarta EE javax.* packages jakarta.* packages
Security config WebSecurityConfigurerAdapter SecurityFilterChain @Bean
(extends)
Native support Limited GraalVM Native Image
Observability Spring Boot Actuator Micrometer tracing built-in
Key breaking change: import [Link].* becomes import [Link].* in Spring Boot
3.x.
27. How to Enable CORS in Spring Boot — When Does CORS Exception
Occur?
CORS (Cross-Origin Resource Sharing) error occurs when a browser makes a request to a different
domain/port than the page origin (e.g., React on localhost:3000 calling API on localhost:8080).
Enable globally:
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
[Link]("/api/**")
.allowedOrigins("[Link]
"[Link]
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
Enable at controller level:
@CrossOrigin(origins = "[Link]
@RestController
@RequestMapping("/api/users")
public class UserController { ... }
28. Caching in Spring Boot (@Cacheable)
Spring Boot provides caching abstraction via @EnableCaching. Backed by ConcurrentHashMap
(default), Redis, Ehcache, Caffeine, etc.
@SpringBootApplication
@EnableCaching
public class App { }
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id")
public Product getProduct(Long id) {
// DB call — only executed on cache miss
return [Link](id).orElseThrow();
}
@CacheEvict(value = "products", key = "#id")
public void deleteProduct(Long id) { [Link](id); }
@CachePut(value = "products", key = "#[Link]")
public Product updateProduct(Product product) { return
[Link](product); }
}
For Redis caching, add spring-boot-starter-data-redis and configure [Link] in
[Link].
29. AOP — Aspect Oriented Programming in Spring Boot
AOP allows cross-cutting concerns (logging, security, transactions, auditing) to be separated from
business logic.
Key Concepts:
• Aspect — Class containing cross-cutting logic
• Advice — The action taken (@Before, @After, @Around, @AfterReturning, @AfterThrowing)
• JoinPoint — Method execution point where advice is applied
• Pointcut — Expression defining which methods to intercept
Audit logging example:
@Aspect
@Component
public class AuditAspect {
private static final Logger log =
[Link]([Link]);
@Around("execution(* [Link].*.*(..))") // all service methods
public Object logAudit(ProceedingJoinPoint joinPoint) throws Throwable {
String method = [Link]().getName();
[Link]("AUDIT: {} started", method);
Object result = [Link]();
[Link]("AUDIT: {} completed", method);
return result;
}
@AfterThrowing(pointcut = "execution(* [Link].*.*(..))",
throwing = "ex")
public void logException(JoinPoint jp, Exception ex) {
[Link]("AUDIT: {} threw exception: {}", [Link]().getName(),
[Link]());
}
}
30. int vs Integer — Primitive vs Wrapper
Aspect int (primitive) Integer (wrapper)
Type Primitive type Object ([Link])
Default value 0 null
Memory 4 bytes (stack) Object on heap (more overhead)
Null support No Yes
Generics Cannot use (List<int>) Can use (List<Integer>)
Streams IntStream Stream<Integer>
Why Integer in Java Streams? Java Generics do not support primitives — List<int> is invalid. Use
List<Integer> and .stream() returns Stream<Integer>. Use IntStream for primitives.
// Sum even numbers
List<Integer> numbers = [Link](1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sumOfEvens = [Link]()
.filter(n -> n % 2 == 0)
.mapToInt(Integer::intValue) // unbox to int for sum
.sum();
[Link]("Sum of even numbers: " + sumOfEvens); // 30
31. Storing Audit Details in Spring Boot
Audit tracking (who created/modified a record, when) is handled via Spring Data JPA Auditing or
AOP.
Using Spring Data JPA Auditing:
@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class AuditConfig {
@Bean
public AuditorAware<String> auditorProvider() {
return () -> [Link]([Link]()
.getAuthentication().getName()); // current user
}
}
@MappedSuperclass
@EntityListeners([Link])
public abstract class BaseAuditEntity {
@CreatedBy private String createdBy;
@CreatedDate private LocalDateTime createdAt;
@LastModifiedBy private String modifiedBy;
@LastModifiedDate private LocalDateTime modifiedAt;
}
@Entity
public class Payment extends BaseAuditEntity {
@Id @GeneratedValue private Long id;
private Double amount;
}
32. Spring Boot Interceptors
Interceptors allow pre/post-processing of HTTP requests — similar to filters but Spring MVC-aware.
@Component
public class RequestLoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
Object handler) {
[Link]("Request: {} {}", [Link](), [Link]());
return true; // continue processing
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception ex) {
[Link]("Response: {} for {}", [Link](), [Link]());
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired private RequestLoggingInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
[Link](interceptor).addPathPatterns("/api/**");
}
}