Career & Industry

Top 50 Spring Boot Interview Questions & Answers (2026)

The most comprehensive Spring Boot interview preparation guide for 2026. Covers core concepts, REST API, Spring Data JPA, Spring Security, testing, and microservices — with real answers and code examples.

Arunprakash Ramalingam··20 min read
Spring BootJavaInterviewREST APISpring SecurityJPA

Top 50 Spring Boot Interview Questions & Answers (2026)

Spring Boot interviews have a well-known pattern. The same 50 questions appear — in different forms — across companies ranging from Infosys and TCS to Razorpay and PhonePe. The difference between passing and failing is not intelligence. It is preparation.

This guide covers every question category interviewers use, with production-quality answers. Not textbook definitions — the kind of answers that make an interviewer nod and move on.


Category 1: Core Spring Boot Concepts (Q1–Q10)

Q1. What is Spring Boot and how is it different from the Spring Framework?

Spring Framework is a comprehensive framework for building Java applications. It is powerful, but requires a lot of configuration — XML files, Java config classes, dependency wiring.

Spring Boot is an opinionated layer on top of Spring Framework that:

  • Auto-configures components based on the JARs present in the classpath
  • Provides embedded servers (Tomcat, Jetty, Undertow) — no need to deploy a WAR file
  • Offers starter dependencies that bundle compatible library versions
  • Includes Spring Boot Actuator for production monitoring out of the box

The one-line answer: Spring Boot makes Spring-based applications production-ready with minimal configuration.


Q2. What is the role of @SpringBootApplication?

It is a convenience annotation that combines three annotations:

java
@SpringBootApplication
// is equivalent to:
@SpringBootConfiguration  // marks this as a configuration class
@EnableAutoConfiguration  // triggers Spring Boot's auto-configuration mechanism
@ComponentScan            // scans for @Component, @Service, @Repository, @Controller beans
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Follow-up: If you only want to scan specific packages:

java
@SpringBootApplication(scanBasePackages = {"com.bigxstar.api", "com.bigxstar.service"})

Q3. What is Auto-Configuration in Spring Boot? How does it work?

Auto-configuration automatically configures Spring beans based on what is on the classpath and what properties are set.

How it works:

  1. When your app starts, Spring Boot reads META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  2. Each entry is a configuration class annotated with @ConditionalOn* annotations
  3. The configuration only applies if the condition is met
java
// Spring Boot's internal DataSource auto-configuration looks roughly like this:
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(DataSource.class)  // only if you haven't defined your own
@AutoConfiguration
public class DataSourceAutoConfiguration {
    // Configures a DataSource for you automatically
}

So if you add spring-boot-starter-data-jpa to your pom.xml, Spring Boot detects it and auto-configures a DataSource, EntityManagerFactory, and TransactionManager.


Q4. What are Spring Boot Starters? Name five commonly used ones.

Starters are pre-packaged sets of dependencies designed to work together. Instead of adding 10 separate library versions (and risking incompatibility), you add one starter.

StarterWhat It Includes
spring-boot-starter-webSpring MVC, Tomcat, Jackson (JSON)
spring-boot-starter-data-jpaHibernate, Spring Data JPA, JDBC
spring-boot-starter-securitySpring Security
spring-boot-starter-testJUnit 5, Mockito, AssertJ, Spring Test
spring-boot-starter-actuatorProduction monitoring endpoints
spring-boot-starter-mailJavaMail, Spring Email support
spring-boot-starter-validationBean Validation (Hibernate Validator)

Q5. What is the difference between @Component, @Service, @Repository, and @Controller?

All four are stereotypes — they tell Spring to manage the class as a bean. The difference is semantic and functional:

java
@Component      // generic Spring-managed bean
@Service        // business logic layer — same as @Component but signals intent
@Repository     // data access layer — adds exception translation (JPA exceptions → Spring DataAccessException)
@Controller     // web layer — handles HTTP requests, returns views
@RestController // web layer — @Controller + @ResponseBody (returns JSON/XML)

The key functional difference is @Repository: it wraps JPA exceptions into Spring's DataAccessException hierarchy, which makes exception handling consistent.


Q6. What is Dependency Injection (DI)? What are the three types in Spring?

DI is a design pattern where an object receives its dependencies from an external source instead of creating them itself. Spring's IoC container manages this.

java
// 1. Constructor Injection — PREFERRED (makes dependencies explicit and final)
@Service
public class OrderService {
    private final PaymentGateway paymentGateway;
    private final InventoryService inventoryService;

    public OrderService(PaymentGateway paymentGateway, InventoryService inventoryService) {
        this.paymentGateway = paymentGateway;
        this.inventoryService = inventoryService;
    }
}

// 2. Setter Injection — for optional dependencies
@Service
public class ReportService {
    private EmailService emailService;

    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
}

// 3. Field Injection — @Autowired on field (NOT recommended — makes testing harder)
@Service
public class UserService {
    @Autowired  // avoid this in production code
    private UserRepository userRepository;
}

In interviews: Always say you prefer Constructor Injection and explain why — it makes dependencies immutable and explicit, and works without reflection (making testing straightforward).


Q7. What is the difference between @Bean and @Component?

Aspect@Component@Bean
Applied toClassMethod in a @Configuration class
When to useClasses you ownThird-party classes or complex initialization logic
DetectionAuto-detected via component scanExplicitly declared
java
// @Component — you own the class
@Component
public class EmailValidator {
    public boolean isValid(String email) { ... }
}

// @Bean — third-party class you don't own (e.g., a library's client)
@Configuration
public class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate rt = new RestTemplate();
        rt.setErrorHandler(new CustomErrorHandler());
        return rt;
    }
}

Q8. What is application.properties vs application.yml? Which is better?

Both configure Spring Boot application properties. application.yml is hierarchical and more readable for nested config; application.properties is flat key-value pairs.

properties
# application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.jpa.hibernate.ddl-auto=update
server.port=8080
yaml
# application.yml — equivalent, but more readable for nested configs
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: postgres
  jpa:
    hibernate:
      ddl-auto: update
server:
  port: 8080

For production apps: always externalize sensitive values:

yaml
spring:
  datasource:
    password: ${DB_PASSWORD}  # reads from environment variable

Q9. What are Spring Profiles? How do you use them?

Profiles let you define different configurations for different environments (dev, staging, production).

yaml
# application-dev.yml
spring:
  datasource:
    url: jdbc:h2:mem:testdb  # in-memory for local dev

# application-prod.yml
spring:
  datasource:
    url: jdbc:postgresql://prod-server:5432/mydb

Activate a profile:

bash
# On startup
java -jar myapp.jar --spring.profiles.active=prod

# Or as environment variable
SPRING_PROFILES_ACTIVE=prod

In code:

java
@Configuration
@Profile("prod")
public class ProdSecurityConfig {
    // Only active in production profile
}

Q10. What is the difference between @Value and @ConfigurationProperties?

java
// @Value — for a single property
@Service
public class PaymentService {
    @Value("${payment.gateway.api-key}")
    private String apiKey;
}

// @ConfigurationProperties — for a group of related properties (PREFERRED for complex config)
@ConfigurationProperties(prefix = "payment.gateway")
@Component
public class PaymentGatewayConfig {
    private String apiKey;
    private String baseUrl;
    private int timeoutSeconds;
    private boolean sandboxMode;
    // getters + setters
}
yaml
# application.yml
payment:
  gateway:
    api-key: sk_live_xxxx
    base-url: https://api.payment.com
    timeout-seconds: 30
    sandbox-mode: false

@ConfigurationProperties is preferred because it is type-safe, supports validation with @Validated, and is easier to test.


Category 2: Spring Data JPA & Database (Q11–Q22)

Q11. What is JPA? What is the difference between JPA, Hibernate, and Spring Data JPA?

  • JPA (Java Persistence API) — a specification (a set of interfaces and rules) for ORM in Java
  • Hibernate — the most popular implementation of the JPA specification
  • Spring Data JPA — a layer on top of JPA/Hibernate that reduces boilerplate. It generates implementations of repositories automatically.
Your Code → Spring Data JPA (findByEmail) → JPA (EntityManager) → Hibernate → JDBC → Database

Q12. Explain @Entity, @Table, @Id, @GeneratedValue.

java
@Entity                          // marks this class as a JPA entity (maps to a table)
@Table(name = "users")           // optional: specify table name (default = class name)
public class User {

    @Id                          // marks as primary key
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // auto-increment
    private Long id;

    @Column(name = "email_address", nullable = false, unique = true, length = 255)
    private String email;

    @Column(name = "created_at")
    private LocalDateTime createdAt;
}

GenerationType strategies:

  • IDENTITY — database auto-increment (MySQL, PostgreSQL)
  • SEQUENCE — uses a DB sequence (best for PostgreSQL batch inserts)
  • UUID — generates a UUID (good for distributed systems)
  • AUTO — Spring picks the strategy based on the database

Q13. What are the JPA relationship mappings? Explain with examples.

java
// @OneToMany / @ManyToOne — most common relationship
@Entity
public class Order {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)        // many orders → one customer
    @JoinColumn(name = "customer_id")
    private Customer customer;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items = new ArrayList<>();
}

// @ManyToMany
@Entity
public class Student {
    @ManyToMany
    @JoinTable(
        name = "student_courses",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private Set<Course> courses = new HashSet<>();
}

Q14. What is the N+1 Problem in JPA? How do you solve it?

java
// THE PROBLEM:
// Fetching 100 orders fires 1 query for orders + 100 queries for each customer = 101 queries
List<Order> orders = orderRepository.findAll();
for (Order order : orders) {
    System.out.println(order.getCustomer().getName()); // triggers a new query each time
}

// SOLUTION 1: JPQL with JOIN FETCH
@Query("SELECT o FROM Order o JOIN FETCH o.customer")
List<Order> findAllWithCustomer();

// SOLUTION 2: Entity Graph
@EntityGraph(attributePaths = {"customer", "items"})
List<Order> findAll();

// SOLUTION 3: Use @BatchSize for lazy collections
@OneToMany(mappedBy = "order")
@BatchSize(size = 20)  // loads 20 at a time instead of 1 at a time
private List<OrderItem> items;

Always mention the N+1 problem in interviews — it is one of the most common real-world performance issues with JPA, and knowing the solutions signals real production experience.


Q15. What is the difference between FetchType.LAZY and FetchType.EAGER?

  • LAZY — related data is loaded only when you access it (the default for @OneToMany, @ManyToMany)
  • EAGER — related data is loaded immediately with the parent entity (the default for @ManyToOne, @OneToOne)
java
// LAZY — good default, avoids loading unnecessary data
@ManyToOne(fetch = FetchType.LAZY)
private Department department;

// EAGER — use only when you always need the related entity
@ManyToOne(fetch = FetchType.EAGER)
private UserProfile profile;

Common mistake: Using FetchType.EAGER everywhere for convenience. This causes massive over-fetching in production. Use LAZY by default and fetch eagerly only when needed with JOIN FETCH.


Q16. What is the difference between save(), saveAndFlush(), and flush() in Spring Data JPA?

java
// save() — persists or merges, adds to the persistence context, writes to DB at transaction commit
User user = userRepository.save(newUser);

// saveAndFlush() — same as save() but immediately flushes to the DB (within the transaction)
// Use when you need the DB to reflect changes immediately (e.g., before calling a stored procedure)
User user = userRepository.saveAndFlush(newUser);

// flush() — writes all pending changes in the persistence context to the DB
// (does NOT commit the transaction)
userRepository.flush();

Q17. What does @Transactional do? What is its propagation behavior?

@Transactional wraps a method in a database transaction — if the method throws an exception, the transaction is rolled back.

java
@Service
public class OrderService {

    @Transactional  // starts a transaction, commits on success, rolls back on RuntimeException
    public Order placeOrder(OrderRequest request) {
        Order order = createOrder(request);
        inventoryService.deductStock(request.getItems());  // runs in same transaction
        paymentService.charge(request.getPayment());       // runs in same transaction
        return order;
        // transaction commits here if no exception
    }
}

Common propagation types:

java
@Transactional(propagation = Propagation.REQUIRED)      // default: join existing or create new
@Transactional(propagation = Propagation.REQUIRES_NEW)  // always create a new transaction
@Transactional(propagation = Propagation.SUPPORTS)      // join if exists, run without if not
@Transactional(readOnly = true)                         // optimization for read-only operations

Gotcha: @Transactional only works on public methods called from outside the class. Calling a @Transactional method from within the same class bypasses the proxy.


Q18. What is the difference between findById(), getById(), and getReferenceById()?

java
// findById() — hits the DB immediately, returns Optional<T>
Optional<User> user = userRepository.findById(1L);

// getReferenceById() (formerly getById) — returns a PROXY, no DB hit until you access a field
// Use when you only need the reference (e.g., for a @ManyToOne foreign key)
User userRef = userRepository.getReferenceById(1L);  // no DB query yet
order.setUser(userRef);  // just sets the foreign key — efficient!
orderRepository.save(order);  // DB query happens here for the save

Q19. What are the different ddl-auto strategies in Spring JPA?

yaml
spring:
  jpa:
    hibernate:
      ddl-auto: validate  # safest for production
ValueBehavior
noneDo nothing. You manage the schema.
validateValidates schema matches entities. Fails fast if mismatch.
updateUpdates schema to match entities. Never use in production.
createCreates schema on startup, drops on shutdown. Good for tests.
create-dropCreates on startup, drops on shutdown.

Production rule: Always use none or validate in production. Manage schema changes with Flyway or Liquibase.


Q20. What is Spring Data's custom query support? Explain derived query methods and @Query.

java
public interface UserRepository extends JpaRepository<User, Long> {

    // Derived query methods — Spring generates SQL from method name
    List<User> findByLastName(String lastName);
    Optional<User> findByEmailIgnoreCase(String email);
    List<User> findByAgeGreaterThanOrderByCreatedAtDesc(int age);
    boolean existsByEmail(String email);
    long countByStatus(UserStatus status);

    // @Query — custom JPQL (object-oriented query language)
    @Query("SELECT u FROM User u WHERE u.email = :email AND u.active = true")
    Optional<User> findActiveUserByEmail(@Param("email") String email);

    // @Query with native SQL
    @Query(value = "SELECT * FROM users WHERE last_login < NOW() - INTERVAL '30 days'",
           nativeQuery = true)
    List<User> findInactiveUsers();

    // Modifying query
    @Modifying
    @Transactional
    @Query("UPDATE User u SET u.status = :status WHERE u.id = :id")
    int updateUserStatus(@Param("id") Long id, @Param("status") UserStatus status);
}

Q21. What is the difference between CrudRepository, JpaRepository, and PagingAndSortingRepository?

CrudRepository
    └── PagingAndSortingRepository (adds paging/sorting)
            └── JpaRepository (adds JPA-specific methods: flush, saveAndFlush, deleteInBatch)

Use JpaRepository by default — it gives you everything.


Q22. How do you implement pagination in Spring Boot?

java
// Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Page<Product> findByCategory(String category, Pageable pageable);
}

// Service
@Service
public class ProductService {
    public Page<Product> getProductsByCategory(String category, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("price").ascending());
        return productRepository.findByCategory(category, pageable);
    }
}

// Controller
@GetMapping("/products")
public ResponseEntity<Page<Product>> getProducts(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size,
        @RequestParam(defaultValue = "electronics") String category) {
    return ResponseEntity.ok(productService.getProductsByCategory(category, page, size));
}

Response includes: content (list of items), totalElements, totalPages, number, size.


Category 3: REST API & Web Layer (Q23–Q33)

Q23. What is the difference between @Controller and @RestController?

java
@Controller  // returns a view name (for server-side rendering with Thymeleaf etc.)
public class PageController {
    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("user", currentUser);
        return "home";  // resolves to home.html template
    }
}

@RestController  // = @Controller + @ResponseBody — returns JSON/XML directly
public class ApiController {
    @GetMapping("/api/users")
    public List<User> getUsers() {
        return userService.findAll();  // serialized to JSON automatically
    }
}

Q24. What is ResponseEntity? Why use it over returning the object directly?

ResponseEntity gives you full control over the HTTP response: status code, headers, and body.

java
// Without ResponseEntity — always returns 200 OK, even for created resources
@PostMapping("/users")
public User createUser(@RequestBody UserDTO dto) {
    return userService.create(dto);  // should be 201, but returns 200
}

// With ResponseEntity — correct HTTP semantics
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody UserDTO dto) {
    User created = userService.create(dto);
    URI location = ServletUriComponentsBuilder
        .fromCurrentRequest().path("/{id}")
        .buildAndExpand(created.getId()).toUri();
    return ResponseEntity.created(location).body(created);  // 201 Created + Location header
}

// Other common patterns
return ResponseEntity.ok(data);                    // 200
return ResponseEntity.noContent().build();         // 204 (after DELETE)
return ResponseEntity.notFound().build();          // 404
return ResponseEntity.badRequest().body(errors);   // 400

Q25. How do you handle exceptions globally in Spring Boot?

java
@RestControllerAdvice  // global exception handler for all @RestController classes
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse("NOT_FOUND", ex.getMessage());
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationErrors(MethodArgumentNotValidException ex) {
        List<String> errors = ex.getBindingResult().getFieldErrors()
            .stream()
            .map(fe -> fe.getField() + ": " + fe.getDefaultMessage())
            .collect(Collectors.toList());
        return ResponseEntity.badRequest().body(new ErrorResponse("VALIDATION_FAILED", errors));
    }

    @ExceptionHandler(Exception.class)  // catch-all
    public ResponseEntity<ErrorResponse> handleGeneric(Exception ex) {
        log.error("Unexpected error", ex);
        return ResponseEntity.internalServerError()
            .body(new ErrorResponse("INTERNAL_ERROR", "An unexpected error occurred"));
    }
}

Q26. How does Bean Validation work in Spring Boot?

java
// 1. Add @Valid to the controller parameter
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) {
    return ResponseEntity.ok(userService.create(request));
}

// 2. Add constraints to your DTO
public class CreateUserRequest {
    @NotBlank(message = "Name cannot be empty")
    @Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
    private String name;

    @NotBlank
    @Email(message = "Invalid email format")
    private String email;

    @NotBlank
    @Pattern(regexp = "^(?=.*[A-Z])(?=.*\\d).{8,}$",
             message = "Password must be at least 8 chars with one uppercase and one digit")
    private String password;

    @NotNull
    @Min(value = 18, message = "Must be at least 18 years old")
    private Integer age;
}

If validation fails, Spring throws MethodArgumentNotValidException — caught by your @RestControllerAdvice.


Q27. What is the difference between @PathVariable, @RequestParam, and @RequestBody?

java
// @PathVariable — extracts a value from the URL path
// GET /products/42
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable Long id) { ... }

// @RequestParam — extracts query parameters from the URL
// GET /products?category=electronics&page=0&size=10
@GetMapping("/products")
public Page<Product> getProducts(
    @RequestParam String category,
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(required = false) String sort) { ... }

// @RequestBody — deserializes the HTTP request body (JSON → Java object)
// POST /products — body: {"name": "Laptop", "price": 50000}
@PostMapping("/products")
public Product createProduct(@RequestBody @Valid ProductDTO dto) { ... }

Q28. How do you implement CORS in Spring Boot?

java
// Method 1: @CrossOrigin on controller (for specific endpoints)
@CrossOrigin(origins = "https://bigxstar.com")
@RestController
public class ProductController { ... }

// Method 2: Global CORS configuration (recommended)
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("https://bigxstar.com", "https://www.bigxstar.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
    }
}

Q29. What is the difference between PUT and PATCH?

java
// PUT — replaces the entire resource
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody @Valid UserUpdateRequest request) {
    // ALL fields of the user are replaced with the request body
    return userService.replace(id, request);
}

// PATCH — partially updates a resource (only the provided fields change)
@PatchMapping("/users/{id}")
public User partialUpdate(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
    return userService.partialUpdate(id, updates);
}

Q30. How do you log requests and responses in Spring Boot?

java
@Component
public class RequestLoggingFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        long startTime = System.currentTimeMillis();
        try {
            filterChain.doFilter(request, response);
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            log.info("{} {} {} {}ms",
                request.getMethod(),
                request.getRequestURI(),
                response.getStatus(),
                duration);
        }
    }
}

Or use Spring Boot's built-in CommonsRequestLoggingFilter:

java
@Bean
public CommonsRequestLoggingFilter logFilter() {
    CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
    filter.setIncludeQueryString(true);
    filter.setIncludePayload(true);
    filter.setMaxPayloadLength(10000);
    return filter;
}

Q31. What is Spring Boot Actuator?

Actuator adds production-ready features via HTTP endpoints:

yaml
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health, info, metrics, env  # expose only what you need
  endpoint:
    health:
      show-details: always

Key endpoints:

  • /actuator/health — application health (DB connectivity, disk space, etc.)
  • /actuator/info — app info (version, git commit)
  • /actuator/metrics — JVM metrics, HTTP request counts, latency
  • /actuator/env — active configuration properties
  • /actuator/loggers — view and change log levels at runtime (no restart needed)
  • /actuator/threaddump — JVM thread dump

Security note: Always secure Actuator endpoints in production. Expose only /health and /info publicly. Secure the rest behind authentication.


Q32. How do you implement caching in Spring Boot?

java
// 1. Enable caching
@SpringBootApplication
@EnableCaching
public class MyApplication { ... }

// 2. Configure cache provider (Redis, Caffeine, etc.)
// In application.yml:
// spring.cache.type=redis OR spring.cache.type=caffeine

// 3. Use cache annotations
@Service
public class ProductService {

    @Cacheable(value = "products", key = "#id")  // cache the result
    public Product findById(Long id) {
        return productRepository.findById(id).orElseThrow();
    }

    @CacheEvict(value = "products", key = "#product.id")  // remove from cache on update
    public Product update(Product product) {
        return productRepository.save(product);
    }

    @CachePut(value = "products", key = "#result.id")  // update cache with new value
    public Product create(Product product) {
        return productRepository.save(product);
    }

    @CacheEvict(value = "products", allEntries = true)  // clear entire cache
    public void clearProductCache() { }
}

Q33. How do you schedule tasks in Spring Boot?

java
@SpringBootApplication
@EnableScheduling
public class MyApplication { ... }

@Component
public class ScheduledTasks {

    // Fixed rate — every 5 minutes, regardless of execution time
    @Scheduled(fixedRate = 300000)
    public void syncInventory() { ... }

    // Fixed delay — 5 minutes AFTER the previous execution finishes
    @Scheduled(fixedDelay = 300000)
    public void cleanTempFiles() { ... }

    // Cron expression — every day at 2:30 AM
    @Scheduled(cron = "0 30 2 * * ?")
    public void generateDailyReport() { ... }

    // Cron — every weekday at 9 AM IST
    @Scheduled(cron = "0 0 9 * * MON-FRI", zone = "Asia/Kolkata")
    public void sendMorningDigest() { ... }
}

Category 4: Spring Security (Q34–Q40)

Q34. What is Spring Security? How does it work at a high level?

Spring Security is a highly customizable authentication and access control framework.

The request flow:

HTTP Request
    → Security Filter Chain (multiple filters in order)
        → Authentication Filter (checks credentials)
        → Authorization Filter (checks permissions)
    → DispatcherServlet
    → Controller

Every request passes through the SecurityFilterChain. Key filters:

  • UsernamePasswordAuthenticationFilter — handles form-based login
  • JwtAuthenticationFilter (custom) — validates JWT tokens
  • ExceptionTranslationFilter — converts security exceptions to HTTP responses

Q35. How do you implement JWT authentication in Spring Boot?

java
// 1. Create JWT utility
@Component
public class JwtUtils {
    @Value("${app.jwt.secret}")
    private String jwtSecret;

    @Value("${app.jwt.expiration-ms}")
    private int jwtExpirationMs;

    public String generateToken(String username) {
        return Jwts.builder()
            .subject(username)
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + jwtExpirationMs))
            .signWith(getSigningKey())
            .compact();
    }

    public String extractUsername(String token) {
        return Jwts.parser().verifyWith(getSigningKey()).build()
            .parseSignedClaims(token).getPayload().getSubject();
    }

    public boolean isTokenValid(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }
}

// 2. JWT filter
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        final String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }
        String jwt = authHeader.substring(7);
        String username = jwtUtils.extractUsername(jwt);
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (jwtUtils.isTokenValid(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken authToken =
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}

Q36. What is the difference between @Secured, @PreAuthorize, and @RolesAllowed?

java
@EnableMethodSecurity  // enables method-level security annotations

// @Secured — simple role check
@Secured("ROLE_ADMIN")
public void deleteUser(Long id) { ... }

// @PreAuthorize — SpEL expressions, more powerful
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
public User getUser(Long userId) { ... }

// Check if the user owns the resource before updating
@PreAuthorize("@securityService.isResourceOwner(#id, authentication.name)")
public Product updateProduct(Long id, ProductDTO dto) { ... }

// @PostAuthorize — check after method execution (rare)
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long id) { ... }

Use @PreAuthorize — it is the most flexible and is the current Spring Security recommendation.


Q37. How do you store passwords securely in Spring Boot?

java
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(12);  // cost factor 12 — balances security and speed
}

// In your registration flow:
@Service
public class AuthService {
    @Autowired private PasswordEncoder passwordEncoder;

    public User register(RegisterRequest request) {
        User user = new User();
        user.setEmail(request.getEmail());
        user.setPassword(passwordEncoder.encode(request.getPassword()));  // NEVER store plaintext
        return userRepository.save(user);
    }

    public boolean verifyPassword(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }
}

Never store plaintext passwords. Always use BCryptPasswordEncoder or Argon2PasswordEncoder.


Q38. What is CSRF? Does Spring Boot disable it by default for REST APIs?

CSRF (Cross-Site Request Forgery) is an attack where a malicious site tricks a logged-in user's browser into making unauthorized requests.

For stateful web apps (session-based auth), CSRF protection is essential.

For stateless REST APIs (JWT-based), CSRF is not needed because:

  • There are no cookies containing session IDs
  • JWT tokens are sent in the Authorization header, which browser-initiated cross-site requests cannot set
java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .csrf(csrf -> csrf.disable())  // safe to disable for stateless JWT APIs
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .build();
}

Category 5: Testing (Q39–Q44)

Q39. What is the difference between @SpringBootTest, @WebMvcTest, and @DataJpaTest?

java
// @SpringBootTest — loads FULL application context. Use for integration tests.
// Slow — use sparingly.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderIntegrationTest { ... }

// @WebMvcTest — loads ONLY the web layer (controllers, filters, security).
// Fast — for unit testing controllers.
@WebMvcTest(ProductController.class)
class ProductControllerTest {
    @Autowired MockMvc mockMvc;
    @MockBean ProductService productService;  // mock service layer
}

// @DataJpaTest — loads ONLY JPA layer (repositories, entities).
// Uses in-memory H2 database by default. Fast.
@DataJpaTest
class UserRepositoryTest {
    @Autowired UserRepository userRepository;
    @Autowired TestEntityManager entityManager;
}

Q40. How do you write a controller test with MockMvc?

java
@WebMvcTest(ProductController.class)
@AutoConfigureMockMvc(addFilters = false)  // disable security filters for unit tests
class ProductControllerTest {

    @Autowired private MockMvc mockMvc;
    @Autowired private ObjectMapper objectMapper;
    @MockBean private ProductService productService;

    @Test
    void getProduct_whenExists_returns200() throws Exception {
        Product product = new Product(1L, "Laptop", new BigDecimal("50000"));
        when(productService.findById(1L)).thenReturn(Optional.of(product));

        mockMvc.perform(get("/api/products/1")
                .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(1))
            .andExpect(jsonPath("$.name").value("Laptop"))
            .andExpect(jsonPath("$.price").value(50000));
    }

    @Test
    void createProduct_withInvalidData_returns400() throws Exception {
        ProductDTO dto = new ProductDTO("", null);  // invalid: name empty, price null

        mockMvc.perform(post("/api/products")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(dto)))
            .andExpect(status().isBadRequest());
    }
}

Q41. What is Mockito? How do you use @Mock vs @MockBean?

java
// @Mock — pure Mockito, no Spring context. Use in unit tests.
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock private OrderRepository orderRepository;
    @Mock private PaymentGateway paymentGateway;
    @InjectMocks private OrderService orderService;  // injects mocks into the service

    @Test
    void placeOrder_whenPaymentSucceeds_savesOrder() {
        when(paymentGateway.charge(any())).thenReturn(PaymentResult.success("txn_123"));
        when(orderRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));

        Order result = orderService.placeOrder(testRequest);

        assertThat(result.getStatus()).isEqualTo(OrderStatus.CONFIRMED);
        verify(orderRepository, times(1)).save(any(Order.class));
    }
}

// @MockBean — Spring Boot's Mockito, replaces the bean in Spring context.
// Use in @WebMvcTest or @SpringBootTest.
@WebMvcTest(OrderController.class)
class OrderControllerTest {
    @MockBean private OrderService orderService;  // replaces real OrderService in Spring context
}

Category 6: Microservices & Advanced (Q42–50)

Q42. What are microservices? How does Spring Boot support them?

Microservices is an architectural style where an application is split into small, independent services, each running its own process and communicating over HTTP/messaging.

Spring Boot supports microservices through:

  • Spring Cloud — service discovery, config server, circuit breakers
  • Spring Cloud Netflix Eureka — service registry
  • Spring Cloud Gateway — API gateway
  • Feign Client — declarative HTTP clients between services
  • Spring Cloud Config — centralized external configuration
  • Spring Cloud Circuit Breaker (Resilience4j) — fault tolerance

Q43. What is a Feign Client?

java
// Instead of using RestTemplate manually, Feign generates the HTTP client for you:

@FeignClient(name = "inventory-service", url = "${inventory.service.url}")
public interface InventoryClient {

    @GetMapping("/api/inventory/{productId}")
    InventoryResponse checkStock(@PathVariable Long productId);

    @PostMapping("/api/inventory/deduct")
    void deductStock(@RequestBody DeductRequest request);
}

// Use it like any other @Autowired bean
@Service
public class OrderService {
    @Autowired private InventoryClient inventoryClient;

    public Order placeOrder(OrderRequest request) {
        InventoryResponse stock = inventoryClient.checkStock(request.getProductId());
        if (stock.getQuantity() < request.getQuantity()) {
            throw new InsufficientStockException();
        }
        // ...
    }
}

Q44. What is a Circuit Breaker? How does Resilience4j implement it?

A Circuit Breaker prevents cascading failures. If a downstream service is failing repeatedly, the circuit "opens" and subsequent calls fail fast (without waiting for a timeout).

java
@Service
public class ProductService {

    @CircuitBreaker(name = "inventoryService", fallbackMethod = "fallbackInventory")
    @TimeLimiter(name = "inventoryService")
    public CompletableFuture<InventoryResponse> checkInventory(Long productId) {
        return CompletableFuture.supplyAsync(() -> inventoryClient.checkStock(productId));
    }

    // Called when circuit is open or timeout occurs
    public CompletableFuture<InventoryResponse> fallbackInventory(Long productId, Throwable t) {
        log.warn("Inventory service unavailable, using fallback", t);
        return CompletableFuture.completedFuture(InventoryResponse.unknown());
    }
}
yaml
# application.yml
resilience4j:
  circuitbreaker:
    instances:
      inventoryService:
        slidingWindowSize: 10
        failureRateThreshold: 50        # open if 50% of last 10 calls fail
        waitDurationInOpenState: 30s    # wait 30s before trying again (half-open)

Q45. How does Spring Boot handle asynchronous processing?

java
@SpringBootApplication
@EnableAsync
public class MyApplication { ... }

@Service
public class EmailService {

    @Async  // runs in a separate thread pool
    public CompletableFuture<Void> sendWelcomeEmail(String email) {
        // This runs asynchronously — the controller returns immediately
        emailSender.send(email, "Welcome to BigXStar!", buildWelcomeBody(email));
        return CompletableFuture.completedFuture(null);
    }
}

// Configure the async thread pool
@Configuration
public class AsyncConfig {
    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("Async-");
        executor.initialize();
        return executor;
    }
}

Q46. What is the difference between @Transactional rollback on checked vs unchecked exceptions?

java
// DEFAULT: only rolls back on RuntimeException (unchecked) and Error
@Transactional
public void processOrder(Order order) {
    orderRepository.save(order);
    throw new IOException("file error");  // DOES NOT rollback — checked exception!
}

// SOLUTION: configure rollbackFor
@Transactional(rollbackFor = Exception.class)  // rollback on any exception
public void processOrder(Order order) throws IOException {
    orderRepository.save(order);
    throw new IOException("file error");  // NOW rolls back
}

// Or: wrap checked exceptions in RuntimeException
@Transactional
public void processOrder(Order order) {
    try {
        orderRepository.save(order);
        riskyOperation();
    } catch (IOException e) {
        throw new RuntimeException("Processing failed", e);  // triggers rollback
    }
}

Q47. How do you handle database migrations in Spring Boot?

Use Flyway (most common in enterprise Java):

xml
<!-- pom.xml -->
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>
sql
-- src/main/resources/db/migration/V1__create_users_table.sql
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

-- src/main/resources/db/migration/V2__add_user_roles.sql
ALTER TABLE users ADD COLUMN role VARCHAR(50) DEFAULT 'USER';

Flyway runs migrations on startup, in version order. Each migration runs exactly once.

yaml
spring:
  flyway:
    enabled: true
    locations: classpath:db/migration
    baseline-on-migrate: true

Q48. What is the difference between @Autowired on a field, constructor, and setter?

Always prefer constructor injection for these reasons:

  1. Immutability — dependencies can be final
  2. Fail-fast — missing dependency fails at startup, not at runtime
  3. Testability — no Spring context needed in unit tests:
java
// With field injection — needs Spring to test
@Autowired private OrderRepository orderRepository;  // can't inject without Spring

// With constructor injection — pure Java object creation in tests
OrderService service = new OrderService(mockRepository, mockGateway);  // no Spring needed

Q49. What is @Conditional and name some @ConditionalOn* annotations?

@Conditional allows bean registration only when a condition is met.

java
@Bean
@ConditionalOnProperty(name = "feature.payments.enabled", havingValue = "true")
public PaymentGateway stripeGateway() {
    return new StripeGateway(apiKey);
}

@Bean
@ConditionalOnMissingBean(CacheManager.class)  // only if no CacheManager is defined
public CacheManager simpleCacheManager() {
    return new SimpleCacheManager();
}

@Bean
@ConditionalOnClass(name = "com.amazonaws.services.s3.AmazonS3")  // only if AWS SDK is present
public S3FileStorage s3FileStorage() { ... }

@ConditionalOnWebApplication    // only in a web application context
@ConditionalOnNotWebApplication // only in a non-web context
@ConditionalOnExpression("${app.environment} == 'production'")

Q50. What are the best practices for a production-ready Spring Boot application?

java
// 1. Use constructor injection everywhere

// 2. Externalize ALL configuration
spring.datasource.password=${DB_PASSWORD}  // never hardcode secrets

// 3. Always validate input
@Valid @RequestBody CreateOrderRequest request

// 4. Use specific exception handling
@RestControllerAdvice with specific @ExceptionHandler methods

// 5. Use @Transactional(readOnly = true) for read operations
@Transactional(readOnly = true)
public List<Product> getAll() { return productRepository.findAll(); }

// 6. Set connection pool limits
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.connection-timeout=30000

// 7. Enable and secure Actuator
management.endpoints.web.exposure.include=health,info

// 8. Use Flyway for schema migrations

// 9. Add structured logging with MDC for tracing
MDC.put("requestId", UUID.randomUUID().toString());

// 10. Profile-based configuration
@Profile("prod")
public class ProductionSecurityConfig { ... }

Final Preparation Checklist

Before your Spring Boot interview, make sure you can:

  • Explain the Spring Boot auto-configuration mechanism clearly
  • Write a complete REST API endpoint with validation and error handling
  • Explain the N+1 problem and its solutions without prompting
  • Implement JWT authentication from scratch
  • Write a unit test using @WebMvcTest and a repository test using @DataJpaTest
  • Explain constructor vs field injection and why you prefer constructor
  • Describe what @Transactional does and when it does NOT roll back
  • Explain at least one microservices pattern (Circuit Breaker, Service Discovery)

What Next?

Knowing the answers is only half the battle. You need to have built something real with these concepts before an interviewer probes deeper.

If you want structured, project-based Spring Boot training — where you build full applications under code review — explore BigXStar's Java Full Stack Course. For those preparing for senior roles at product companies, our Java Full Stack Career Program covers Spring Boot, microservices, system design, and interview preparation over 9 months.

Good luck — and remember, the goal is not to memorize these answers. It is to have built enough to mean every word you say.

Browse all Java learning resources on BigXStar →