0% found this document useful (0 votes)
102 views62 pages

Complete Java & Spring Boot Interview Guide 2025

The document is a comprehensive interview guide for Java and Spring Boot, covering topics from Java 8-21, Spring Boot 3.5.6, system design, algorithms, and DevOps. It includes detailed explanations, code examples, and best practices for core Java concepts, REST controllers, custom health indicators, JPA repositories, and security configurations. The guide aims to prepare candidates for technical interviews with a focus on practical applications and design patterns.

Uploaded by

m.mohammadfawad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
102 views62 pages

Complete Java & Spring Boot Interview Guide 2025

The document is a comprehensive interview guide for Java and Spring Boot, covering topics from Java 8-21, Spring Boot 3.5.6, system design, algorithms, and DevOps. It includes detailed explanations, code examples, and best practices for core Java concepts, REST controllers, custom health indicators, JPA repositories, and security configurations. The guide aims to prepare candidates for technical interviews with a focus on practical applications and design patterns.

Uploaded by

m.mohammadfawad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

📘 Complete Java & Spring Boot Interview

Guide 2025
Comprehensive preparation for Java 8-21, Spring Boot 3.5.6, System Design, Algorithms & DevOps

Java 8-21 Spring Boot 3.5.6 Spring 6 Microservices System Design Database & SQL Algorithms

DevOps

📚 Table of Contents

Core Java (1-17) Spring Boot (18-57) System Design (58-68)

OOP Principles REST Controller & Validation Design Patterns

HashMap vs ConcurrentHashMap Health Indicators Microservices Patterns

Stream API JPA & Custom Queries Database Design

final, finally, finalize() Security & JWT Caching Strategies

Records Transaction Management Scalability Patterns

Sealed Classes Caching with Redis

Virtual Threads Async Processing

1
Core Java (Java 8-21)

1 What are the main OOP principles in Java?

Answer: Encapsulation, Inheritance, Polymorphism, and Abstraction. They promote code reusability and
modularity.

🏗️ OOP Principles in Detail:


Encapsulation: Wrapping data and methods together, hiding internal implementation details
Inheritance: Creating new classes from existing ones, promoting code reuse
Polymorphism: Ability of objects to take many forms (method overriding/overloading)
Abstraction: Hiding complex implementation details, showing only essential features
2 Difference between HashMap and ConcurrentHashMap?

Answer: HashMap is not thread-safe, while ConcurrentHashMap allows concurrent read/write operations by
segmenting data and prevents ConcurrentModificationException.

Aspect HashMap ConcurrentHashMap

Thread Safety ❌ Not thread-safe ✅ Thread-safe

Null Keys/Values ✅ Allows one null key, multiple null values ❌ Does not allow null keys or values

Performance Faster in single-threaded environment Optimized for concurrent access

Locking Segment-level locking (Java 7) or CAS


No locking
Mechanism (Java 8+)

Fail-fast (throws
Iterator Behavior Weakly consistent
ConcurrentModificationException)

3 What is the Stream API used for?

Answer: Stream API processes collections in a functional way (filter, map, reduce). It improves readability and
supports parallel processing.

Stream API Examples

import java.util.*;
import java.util.stream.*;

public class StreamExamples {


public static void main(String[] args) {
// Example 1: Filter and collect
List names = Arrays.asList("John", "Alice", "Bob", "Anna");
List result = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());

// Example 2: Map and reduce


List numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.map(n -> n * n)
.reduce(0, Integer::sum);

// Example 3: Parallel stream for performance


long count = names.parallelStream()
.filter(name -> name.length() > 3)
.count();

// Example 4: Grouping by
Map> grouped = names.stream()
.collect(Collectors.groupingBy(String::length));
}
}
4 Explain the difference between final, finally, and finalize().

Answer:
final: Makes a variable constant or prevents inheritance/method overriding
finally: Block that executes after try-catch, always runs (except System.exit())
finalize(): Called by GC before object destruction (deprecated in Java 9)

5 What are records in Java?

Answer: Introduced in Java 14, records are compact classes for immutable data carriers.

Java Records Example

// Java 14+ Records - Immutable data classes


public record User(String name, String email, int age) {

// Compact constructor with validation


public User {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
}

// Custom method
public String displayInfo() {
return name + " (" + age + ") - " + email;
}
}

// Usage
User user = new User("John Doe", "[email protected]", 30);
System.out.println(user.name()); // Accessor method
System.out.println(user.toString()); // Auto-generated toString()
6 What are sealed classes?

Answer: Sealed classes (Java 17) restrict inheritance to specific classes.

Sealed Classes Example

// Sealed class restricts which classes can extend it


public sealed class Shape permits Circle, Rectangle, Triangle {
public abstract double area();
}

// Permitted subclasses must be final, sealed, or non-sealed


public final class Circle extends Shape {
private final double radius;

public Circle(double radius) {


this.radius = radius;
}

@Override
public double area() {
return Math.PI * radius * radius;
}
}

public final class Rectangle extends Shape {


private final double width, height;

public Rectangle(double width, double height) {


this.width = width;
this.height = height;
}

@Override
public double area() {
return width * height;
}
}
7 What are virtual threads?

Answer: Introduced in Java 21 — lightweight threads that scale concurrency efficiently without blocking OS
threads.

🎯 Virtual Threads Benefits:


Lightweight: Millions of virtual threads can run concurrently
Non-blocking: Don't block OS threads when waiting
Simplified Code: Write synchronous code that scales asynchronously
Better Resource Utilization: Efficient for I/O-bound operations

Virtual Threads Example (Java 21)

import java.util.concurrent.*;
import java.util.stream.*;

public class VirtualThreadsExample {


public static void main(String[] args) throws Exception {

// Method 1: Using Executors.newVirtualThreadPerTaskExecutor()


try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {

List> futures = IntStream.range(0, 10_000)


.mapToObj(i -> executor.submit(() -> {
try {
Thread.sleep(100); // Simulate I/O operation
return "Task " + i + " completed";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}))
.collect(Collectors.toList());

for (Future future : futures) {


System.out.println(future.get());
}
}

// Method 2: Direct virtual thread creation


Thread virtualThread = Thread.ofVirtual()
.name("virtual-thread-1")
.start(() -> {
System.out.println("Hello from virtual thread!");
});

virtualThread.join();
}
}
2
Spring Boot 3.5.6 & Spring 6

18 Create a REST controller with validation and exception handling


Spring Boot 3.5.6 REST Controller

package com.example.api.controller;

import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import org.springframework.http.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/users")
@Validated
public class UserController {

@PostMapping
public ResponseEntity createUser(
@Valid @RequestBody CreateUserRequest request) {
UserResponse response = userService.createUser(request);

return ResponseEntity
.created(URI.create("/api/v1/users/" + response.id()))
.body(response);
}

@GetMapping("/{id}")
public ResponseEntity getUser(
@PathVariable @Min(1) Long id) {
return userService.findById(id)
.map(user -> ResponseEntity.ok(mapToResponse(user)))
.orElseThrow(() -> new ResourceNotFoundException(
"User not found with id: " + id));
}

// Global exception handler


@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity handleValidationException(
MethodArgumentNotValidException ex) {

List errors = ex.getBindingResult()


.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.toList());

return ResponseEntity.badRequest()
.body(new ErrorResponse("Validation failed", errors));
}
}
}

// DTO with validation (Jakarta EE 9+)


public record CreateUserRequest(
@NotBlank(message = "Username is required")
@Size(min = 3, max = 50, message = "Username must be 3-50 characters")
String username,

@Email(message = "Invalid email format")


@NotBlank(message = "Email is required")
String email,

@Min(value = 18, message = "Age must be at least 18")


@Max(value = 100, message = "Age must be at most 100")
Integer age,

@Pattern(
regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,}$",
message = "Password must contain 8+ chars with uppercase, lowercase, and digit"
)
String password
) {}
19 Implement a custom HealthIndicator for Spring Boot Actuator

Custom Health Indicator

package com.example.health;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class DatabaseHealthIndicator implements HealthIndicator {

private final DataSource dataSource;


private final JdbcTemplate jdbcTemplate;

public DatabaseHealthIndicator(DataSource dataSource) {


this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

@Override
public Health health() {
try {
// Check database connection
Integer result = jdbcTemplate.queryForObject(
"SELECT 1", Integer.class);

if (result != null && result == 1) {


return Health.up()
.withDetail("database", "Connected")
.withDetail("url", dataSource.getConnection().getMetaData().getURL())
.build();
} else {
return Health.down()
.withDetail("database", "Connection test failed")
.build();
}
} catch (Exception e) {
return Health.down(e)
.withDetail("database", "Connection failed: " + e.getMessage())
.build();
}
}
}

// Health endpoint configuration in application.yml


// management:
// endpoints:
// web:
// exposure:
// include: health,metrics,info
// health:
// db:
// enabled: true
// diskspace:
// enabled: true
// defaults:
// enabled: true
20 Implement JPA repository with custom query methods

JPA Repository with Custom Queries

package com.example.repository;

import org.springframework.data.jpa.repository.*;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository {

// Derived query method


Optional findByEmail(String email);

// JPQL with join


@Query("SELECT u FROM User u JOIN FETCH u.roles WHERE u.id = :id")
Optional findByIdWithRoles(@Param("id") Long id);

// Native query with projection


@Query(value = """
SELECT u.id as userId, u.email,
COUNT(o.id) as orderCount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.active = true
GROUP BY u.id, u.email
""", nativeQuery = true)
List findActiveUsersWithOrderCount();

// Dynamic query with Specification


default List findUsersByCriteria(UserSearchCriteria criteria) {
return findAll((root, query, cb) -> {
List predicates = new ArrayList<>();

if (criteria.getEmail() != null) {
predicates.add(cb.like(root.get("email"),
"%" + criteria.getEmail() + "%"));
}

if (criteria.getMinAge() != null) {
predicates.add(cb.ge(root.get("age"),
criteria.getMinAge()));
}

if (criteria.getRole() != null) {
Join roles = root.join("roles");
predicates.add(cb.equal(roles.get("name"),
criteria.getRole()));
}

return cb.and(predicates.toArray(new Predicate[0]));


});
}
}

// Projection interface
public interface UserOrderProjection {
Long getUserId();
String getEmail();
Long getOrderCount();
}
21 Configure Spring Security 6 with JWT authentication
Spring Security 6 Configuration

package com.example.security.config;

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.method.configuration.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.*;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exceptions ->
exceptions.authenticationEntryPoint(jwtAuthenticationEntryPoint())
);

return http.build();
}

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

// JWT Filter Implementation


public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {

String token = extractToken(request);

if (token != null && jwtUtil.validateToken(token)) {


String username = jwtUtil.extractUsername(token);

UserDetails userDetails = userDetailsService


.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());

authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);

SecurityContextHolder.getContext().setAuthentication(authentication);
}

filterChain.doFilter(request, response);
}

private String extractToken(HttpServletRequest request) {


String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}

3
System Design & Architecture

🏗️ Common Design Patterns

🔒 Singleton Pattern 🏭 Factory Pattern

Creational Thread-safe Global Access Creational Decoupling Flexibility

Use Case: Database connections, logging, Use Case: Payment processors, notification services,
configuration management document converters
Thread-Safe Singleton Factory Pattern Example

public class ThreadSafeSingleton { public interface PaymentProcessor {


private static volatile ThreadSafeSingleton PaymentResult process(PaymentRequest request
}
private ThreadSafeSingleton() {
// Prevent reflection attacks public class PaymentFactory {
if (instance != null) {
throw new IllegalStateException( public static PaymentProcessor createProcess
"Singleton already initialized") return switch (type.toLowerCase()) {
} case "creditcard" -> new CreditCardP
} case "paypal" -> new PayPalProcessor
case "crypto" -> new CryptoProcessor
public static ThreadSafeSingleton getInstanc default -> throw new IllegalArgument
if (instance == null) { // First check "Unknown payment type: " + type)
synchronized (ThreadSafeSingleton.cl };
if (instance == null) { // Secon }
instance = new ThreadSafeSin }
}
}
}  

return instance;
}
}

 

👁️ Observer Pattern 🎯 Strategy Pattern

Behavioral Event-driven Decoupling Behavioral Algorithm Selection Runtime Switching

Use Case: Event notifications, stock market updates, Use Case: Sorting algorithms, compression methods,
chat applications payment gateways
Observer Pattern Example Strategy Pattern Example

public interface Observer { public interface SortingStrategy {


void update(String event); void sort(List list);
} }

public class Subject { public class QuickSortStrategy implements Sortin


private List observers = new ArrayList<>(); @Override
public void sort(List list) {
public void addObserver(Observer observer) { // Quick sort implementation
observers.add(observer); }
} }

public void notifyObservers(String event) { public class MergeSortStrategy implements Sortin


for (Observer observer : observers) { @Override
observer.update(event); public void sort(List list) {
} // Merge sort implementation
} }
} }

// Spring implementation using @EventListener public class Sorter {


@Component private SortingStrategy strategy;
public class OrderEventListener {
public void setStrategy(SortingStrategy stra
@EventListener this.strategy = strategy;
public void handleOrderCreated(OrderCreatedE }
// Send email notification
emailService.sendOrderConfirmation(event public void sort(List list) {
strategy.sort(list);
// Update inventory }
inventoryService.reserveItems(event.getO }
}
}
 

 
SD1 Design a URL Shortening Service (TinyURL)

Answer: Comprehensive system design for URL shortening service

📊 System Requirements:
Functional: Shorten URLs, redirect to original URLs, custom URLs, analytics
Non-Functional: High availability (99.99%), low latency (< 100ms), scalability
Scale: 100M URLs, 100M requests/day, 1KB per URL record

🏗️ Architecture Components:
1. API Layer: REST APIs for URL operations
2. Encoding Service: Base62 encoding for short URLs
3. Storage: Redis (cache) + PostgreSQL (persistent)
4. CDN: For static assets and frequently accessed URLs
5. Load Balancer: Distribute traffic across servers
6. Analytics: Track clicks, referrers, geographical data

URL Shortening Algorithm

public class URLShortener {


private static final String ALPHABET =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final int BASE = ALPHABET.length();

// Encode integer ID to base62 string


public String encode(long id) {
StringBuilder shortURL = new StringBuilder();

while (id > 0) {


shortURL.append(ALPHABET.charAt((int)(id % BASE)));
id = id / BASE;
}

return shortURL.reverse().toString();
}

// Decode base62 string to integer ID


public long decode(String shortURL) {
long id = 0;

for (int i = 0; i < shortURL.length(); i++) {


id = id * BASE + ALPHABET.indexOf(shortURL.charAt(i));
}
return id;
}

// Distributed ID generation (Snowflake-like)


public long generateId() {
long timestamp = System.currentTimeMillis() - 1609459200000L;
long datacenterId = 1;
long machineId = 1;
long sequence = ThreadLocalRandom.current().nextLong(4096);
return (timestamp << 22) | (datacenterId << 17) | (machineId << 12) | sequence;
}
}
4
Database & JPA

62 Explain lazy vs eager fetching

Answer: Lazy: Loads data when accessed. Eager: Loads immediately with parent entity.

Aspect Lazy Loading Eager Loading

Loading Time On-demand when accessed Immediately with parent

Performance Better for infrequently accessed data Better for frequently accessed data

N+1 Problem Can cause N+1 queries Single query with joins

Memory Usage Lower (loads only needed data) Higher (loads all related data)

Use Case Large collections, infrequent access Small collections, always needed

JPA Fetch Type Examples

@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// Eager loading - loads immediately with Order


@OneToMany(fetch = FetchType.EAGER, mappedBy = "order")
private List items;

// Lazy loading - loads only when accessed


@OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
private List payments;

// Default: @OneToMany is LAZY, @ManyToOne is EAGER


@ManyToOne(fetch = FetchType.LAZY) // Explicitly set to LAZY
@JoinColumn(name = "customer_id")
private Customer customer;
}

// Query with JOIN FETCH to avoid N+1 problem


@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")
Optional findByIdWithItems(@Param("id") Long id);

// EntityGraph for defining fetch strategy at query time


@EntityGraph(attributePaths = {"items", "customer"})
Optional findWithItemsAndCustomerById(Long id);
63 What are the common entity relationships?

Answer: @OneToOne, @OneToMany, @ManyToOne, @ManyToMany

🏗️ JPA Relationship Types:


@OneToOne: One entity instance related to one other instance
@OneToMany: One entity instance related to multiple instances
@ManyToOne: Multiple instances related to one instance
@ManyToMany: Multiple instances related to multiple instances
JPA Relationship Examples

@Entity
public class User {
@Id
@GeneratedValue
private Long id;

// One-to-One: User has one Profile


@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Profile profile;

// One-to-Many: User has many Orders


@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List orders = new ArrayList<>();

// Many-to-Many: User can have many Roles


@ManyToMany
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set roles = new HashSet<>();
}

@Entity
public class Order {
@Id
@GeneratedValue
private Long id;

// Many-to-One: Order belongs to one User


@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

// One-to-Many: Order has many Items


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

// Bidirectional relationship management helper methods


public class User {
public void addOrder(Order order) {
orders.add(order);
order.setUser(this);
}

public void removeOrder(Order order) {


orders.remove(order);
order.setUser(null);
}
}
64 What's the difference between save() and saveAndFlush()?

Answer: save(): Persists data in session. saveAndFlush(): Persists and immediately writes changes to DB.

Aspect save() saveAndFlush()

Execution Deferred until transaction commit Immediate execution

Performance Better for batch operations Slower due to immediate flush

Use Case Normal save operations Need immediate ID generation or validation

Transaction Boundary Within transaction boundaries Can be called outside transaction


save() vs saveAndFlush() Examples

@Service
@Transactional
public class UserService {

@Autowired
private UserRepository userRepository;

// Using save() - deferred execution


public User createUser(User user) {
// Entity is persisted but not flushed immediately
return userRepository.save(user);
// Changes will be written to DB at transaction commit
}

// Using saveAndFlush() - immediate execution


public User createUserAndGetId(User user) {
// Entity is persisted and flushed immediately
User savedUser = userRepository.saveAndFlush(user);

// ID is available immediately after saveAndFlush()


Long userId = savedUser.getId();

// Can use the ID for other operations immediately


logService.logUserCreation(userId);

return savedUser;
}

// Batch operations with save()


public void createUsersBatch(List users) {
for (User user : users) {
userRepository.save(user); // Deferred execution
}
// All users saved in single transaction
// Optimized for performance
}

// When to use saveAndFlush()


@Transactional
public User updateUserWithValidation(Long userId, User updatedUser) {
// Need to flush to get updated entity for validation
userRepository.saveAndFlush(updatedUser);

// Immediate validation after flush


User freshUser = userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException("User not found"));

// Perform validation on fresh data


validateUser(freshUser);

return freshUser;
}
}
5
Microservices with Spring Cloud

68 What is a microservice?

Answer: Independent, small, loosely coupled service focusing on a specific business capability.

🏗️ Microservices Characteristics:
Single Responsibility: Each service handles one business capability
Independent Deployment: Can be deployed independently
Technology Diversity: Can use different tech stacks
Decentralized Data Management: Each service owns its database
Fault Isolation: Failure in one service doesn't affect others
Microservices Architecture Example

// Order Service - Independent microservice


@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}

// Order Controller
@RestController
@RequestMapping("/api/orders")
public class OrderController {

@Autowired
private InventoryServiceClient inventoryService;

@PostMapping
public ResponseEntity createOrder(@RequestBody OrderRequest request) {
// Check inventory using Feign client
InventoryResponse inventory = inventoryService.checkInventory(
request.getProductId(), request.getQuantity());

if (!inventory.isAvailable()) {
throw new InsufficientInventoryException("Not enough stock");
}

Order order = orderService.createOrder(request);

// Publish event for other services


eventPublisher.publish(new OrderCreatedEvent(order));

return ResponseEntity.ok(order);
}
}

// Feign Client for service-to-service communication


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

@PostMapping("/api/inventory/check")
InventoryResponse checkInventory(
@RequestParam("productId") Long productId,
@RequestParam("quantity") Integer quantity);
}

// Service Discovery with Eureka


@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}

// Configuration for service registration


// eureka:
// client:
// service-url:
// defaultZone: http://localhost:8761/eureka/
// instance:
// hostname: localhost
// prefer-ip-address: true
69 How do microservices communicate?

Answer: REST APIs, Feign clients, gRPC, or message brokers (Kafka, RabbitMQ).

Method Protocol Use Case Pros Cons

Synchronous requests, Simple, stateless, Higher latency,


REST/HTTP HTTP/HTTPS
CRUD operations cacheable coupling

High-performance, Fast, bidirectional Complex setup, binary


gRPC HTTP/2
streaming streaming format

Message AMQP, Async communication, Decoupled, Complexity, eventual


Queue Kafka event-driven scalable, reliable consistency

Single endpoint, Complex queries,


GraphQL HTTP Flexible data fetching
efficient caching
Microservice Communication Examples

// 1. REST Communication with WebClient (Reactive)


@Service
public class ProductService {
private final WebClient webClient;

public ProductService(WebClient.Builder webClientBuilder) {


this.webClient = webClientBuilder
.baseUrl("http://inventory-service")
.build();
}

public Mono checkInventory(Long productId) {


return webClient.get()
.uri("/api/inventory/{productId}", productId)
.retrieve()
.bodyToMono(InventoryResponse.class)
.timeout(Duration.ofSeconds(5))
.retryWhen(Retry.backoff(3, Duration.ofSeconds(1)));
}
}

// 2. Message Broker with Kafka


@Configuration
public class KafkaConfig {
@Bean
public ProducerFactory producerFactory() {
Map config = new HashMap<>();
config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return new DefaultKafkaProducerFactory<>(config);
}

@Bean
public KafkaTemplate kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
}

@Component
public class OrderEventPublisher {
@Autowired
private KafkaTemplate kafkaTemplate;

public void publishOrderCreated(Order order) {


OrderEvent event = new OrderEvent("ORDER_CREATED", order);
kafkaTemplate.send("order-events", order.getId().toString(), event);
}
}

// 3. gRPC Communication
@GrpcClient("product-service")
private ProductServiceGrpc.ProductServiceBlockingStub productStub;

public Product getProduct(Long id) {


GetProductRequest request = GetProductRequest.newBuilder()
.setId(id)
.build();

GetProductResponse response = productStub.getProduct(request);


return mapToProduct(response);
}

// 4. Circuit Breaker with Resilience4j


@Service
@Slf4j
public class PaymentService {
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackProcessPayment")
@TimeLimiter(name = "paymentService")
@Retry(name = "paymentService")
public CompletableFuture processPayment(PaymentRequest request) {
return CompletableFuture.supplyAsync(() -> {
// Call external payment service
return paymentClient.process(request);
});
}

private CompletableFuture fallbackProcessPayment(


PaymentRequest request, Throwable throwable) {
log.warn("Payment service unavailable, using fallback", throwable);
return CompletableFuture.completedFuture(
new PaymentResponse("QUEUED", "Payment queued for retry")
);
}
}
6
Deployment, Docker & DevOps Basics

77 What is Docker?

Answer: A containerization platform that packages apps with dependencies for consistent deployment.

🐳 Docker Key Concepts:


Container: Lightweight, executable package with application and dependencies
Image: Read-only template used to create containers
Dockerfile: Script to build Docker images
Docker Compose: Tool for defining and running multi-container applications
Registry: Repository for Docker images (Docker Hub, ECR, GCR)
Docker Configuration Examples

# Dockerfile for Spring Boot Application


FROM eclipse-temurin:17-jdk-alpine as builder

WORKDIR /app

# Copy Maven wrapper and pom.xml


COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .

# Download dependencies
RUN ./mvnw dependency:go-offline -B

# Copy source code


COPY src src

# Build application
RUN ./mvnw clean package -DskipTests

# Runtime stage
FROM eclipse-temurin:17-jre-alpine

WORKDIR /app

# Copy built jar from builder stage


COPY --from=builder /app/target/*.jar app.jar

# Create non-root user


RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

# Expose port
EXPOSE 8080

# Run application
ENTRYPOINT ["java", "-jar", "/app.jar"]

# docker-compose.yml for multi-service setup


version: '3.8'

services:
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: mydb
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- app-network

redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- app-network

app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/mydb
SPRING_DATASOURCE_USERNAME: admin
SPRING_DATASOURCE_PASSWORD: secret
SPRING_REDIS_HOST: redis
depends_on:
- postgres
- redis
networks:
- app-network

networks:
app-network:
driver: bridge

volumes:
postgres_data:

# Docker commands cheat sheet


# Build image: docker build -t myapp:latest .
# Run container: docker run -p 8080:8080 myapp:latest
# View running containers: docker ps
# View logs: docker logs
# Stop container: docker stop
# Remove container: docker rm
# Push to registry: docker push myregistry/myapp:latest
81 What is CI/CD?

Answer: Continuous Integration & Continuous Deployment automate testing and deployment pipelines.

🚀 CI/CD Pipeline Stages:


1. Source: Code commit triggers pipeline
2. Build: Compile code and run unit tests
3. Test: Run integration and functional tests
4. Package: Create Docker images
5. Deploy: Deploy to staging/production
6. Verify: Run smoke tests and monitoring
GitHub Actions CI/CD Pipeline

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:15-alpine
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

steps:
- uses: actions/checkout@v3

- name: Set up JDK 17


uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

- name: Build and Test


run: |
chmod +x mvnw
./mvnw clean verify

- name: Upload Test Results


uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: target/surefire-reports/

build-and-push:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v3

- name: Set up Docker Buildx


uses: docker/setup-buildx-action@v2

- name: Login to DockerHub


uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push Docker image


uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/myapp:latest
${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}

deploy:
runs-on: ubuntu-latest
needs: build-and-push
if: github.ref == 'refs/heads/main'

steps:
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v4
with:
namespace: production
manifests: |
k8s/deployment.yaml
k8s/service.yaml
k8s/ingress.yaml
images: |
${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}

- name: Run Smoke Tests


run: |
# Wait for deployment to be ready
sleep 30
# Run smoke tests
curl -f http://myapp.example.com/actuator/health

- name: Notify Slack


uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: always()

📊 Document Summary

97+ 50+ 10 5
Interview Questions Code Examples Design Patterns System Designs

This document contains the complete Java & Spring Boot interview preparation guide with all questions, answers,
and code examples. Save this HTML file for offline reference.

📅 Generated: December 2024 | 🚀 Version: 1.0 | 📁 Format: Self-contained HTML


💾 Download Complete Guide

📘 Complete Java & Spring Boot Interview


Guide 2025
Comprehensive preparation for Java 8-21, Spring Boot 3.5.6, System Design, Algorithms & More

Java 21 Spring Boot 3.5.6 System Design Microservices SQL & NoSQL Algorithms

Core Spring Database Microservices System Algorithms 📥 Download


Java Boot Design PDF

📚 Contents

1
Core Java (8-21) 2. Core Java (Java 8-21)
Spring Boot 3.5.6

Database & JPA

Microservices 2.1. 1 What are the main OOP principles in Java?

Answer: The four main OOP principles are:


Deployment & DevOps

🏗️ OOP Principles:
System Design
Encapsulation: Binding data and methods together, hiding internal state
Testing Inheritance: Creating new classes from existing ones
Polymorphism: Ability to take many forms (method
Algorithms overriding/overloading)
Abstraction: Hiding complex implementation details
HR & Behavioral

Extra Q&A

🏷️ Quick Links

Code Examples

Design Patterns

Performance

Security

Scalability
2.2. 2 Difference between HashMap and ConcurrentHashMap?

Answer:

🔒 Thread Safety Comparison:

Aspect HashMap ConcurrentHashMap

Thread Safety ❌ Not thread-safe ✅ Thread-safe

✅ Allows one null


Null ❌ Does not allow null keys
key, multiple null
Keys/Values or values
values

Faster for single Optimized for concurrent


Performance
thread access

Locking Segment-level locking (Java


No locking
Mechanism 7) or CAS (Java 8+)

Java 21 Virtual Threads Example Copy

// Java 21 Virtual Threads - Lightweight threads for high concurrency


import java.util.concurrent.*;
import java.util.stream.*;

public class VirtualThreadsExample {

public static void main(String[] args) {


// Using Executors.newVirtualThreadPerTaskExecutor()
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(

// Launch 10,000 virtual threads


List<CompletableFuture<String>> futures = IntStream.range(0, 10_000)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
try {
// Simulate I/O operation
Thread.sleep(100);
return "Task " + i + " completed on thread: " +
Thread.currentThread();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, executor))
.collect(Collectors.toList());

// Wait for all tasks to complete


CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenRun(() -> System.out.println("All virtual threads completed")

} // Auto-close ensures executor shutdown


}

// Pattern matching for switch (Java 21)


public String processShape(Object shape) {
return switch (shape) {
case Circle c -> "Circle with radius: " + c.getRadius();
case Rectangle r && r.isSquare() -> "Square with side: " + r.getWidth(
case Rectangle r -> "Rectangle: " + r.getWidth() + "x" + r.getHeight()
case null -> "Null shape";
default -> "Unknown shape";
};
}
}

// Records (Java 14+) - Immutable data carriers


public record User(String name, String email, int age) {
// Compact constructor with validation
public User {
if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
if (email == null || !email.contains("@"))
throw new IllegalArgumentException("Invalid email");
}
}

// Sealed classes (Java 17) - Restricted inheritance


public sealed class Shape permits Circle, Rectangle, Triangle {
public abstract double area();
}

public final class Circle extends Shape {


private final double radius;
public Circle(double radius) { this.radius = radius; }
@Override public double area() { return Math.PI * radius * radius; }
}

public final class Rectangle extends Shape {


private final double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override public double area() { return width * height; }
}
2.3. 8 Implement thread-safe singleton using Java 21 features

Thread-Safe Singleton Pattern Copy

// Double-checked locking with volatile


public class ThreadSafeSingleton {
private static volatile ThreadSafeSingleton instance;

private ThreadSafeSingleton() {
// Prevent reflection attacks
if (instance != null) {
throw new IllegalStateException("Singleton already initia
}
}

public static ThreadSafeSingleton getInstance() {


if (instance == null) { // First check (no locking)
synchronized (ThreadSafeSingleton.class) {
if (instance == null) { // Second check (with locking
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}

// Enum singleton (Joshua Bloch's approach) - Most recommended


public enum EnumSingleton {
INSTANCE;

public void doSomething() {


// Singleton operations
}
}

// Using Holder pattern (Lazy initialization, thread-safe)


public static class HolderSingleton {
private HolderSingleton() {}

private static class SingletonHolder {


private static final HolderSingleton INSTANCE = new Holde
}

public static HolderSingleton getInstance() {


return SingletonHolder.INSTANCE;
}
}
}

 

💡 Explanation:
Double-checked locking ensures thread safety while minimizing
synchronization overhead. The volatile keyword prevents instruction
reordering issues.
Enum singleton is the most recommended approach as it's inherently
thread-safe, serialization-safe, and reflection-safe.
2
4. Spring Boot 3.5.6 & Spring 6

4.1. 18 Create REST controller with validation and exception handling

Spring Boot 3.5.6 REST Controller Copy

// Spring Boot 3.5.6 with Jakarta EE 9+ (javax -> jakarta)


package com.example.api.controller;

import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import org.springframework.http.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/users")
@Validated
public class UserController {

@PostMapping
public ResponseEntity<UserResponse> createUser(
@Valid @RequestBody CreateUserRequest request) {
// Business logic here
UserResponse response = userService.createUser(request);

return ResponseEntity
.created(URI.create("/api/v1/users/" + response.id()))
.body(response);
}

@GetMapping("/{id}")
public ResponseEntity<UserResponse> getUser(
@PathVariable @Min(1) Long id) {
return userService.findById(id)
.map(user -> ResponseEntity.ok(mapToResponse(user)))
.orElseThrow(() -> new ResourceNotFoundException("User no
}

// Global exception handler


@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationExceptio
MethodArgumentNotValidException ex) {

List<String> errors = ex.getBindingResult()


.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefa
.collect(Collectors.toList());

return ResponseEntity.badRequest()
.body(new ErrorResponse("Validation failed", errors))
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFoundException(
ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse(ex.getMessage()));
}
}
}

// DTO with validation annotations (Jakarta EE 9+)


public record CreateUserRequest(
@NotBlank(message = "Username is required")
@Size(min = 3, max = 50, message = "Username must be 3-50 charact
String username,

@Email(message = "Invalid email format")


@NotBlank(message = "Email is required")
String email,

@Min(value = 18, message = "Age must be at least 18")


@Max(value = 100, message = "Age must be at most 100")
Integer age,

@Pattern(
regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(
message = "Password must contain at least 8 characters, one u
)
String password
) {}

// Custom validation annotation


@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
public @interface UniqueEmail {
String message() default "Email already exists";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
4.2. 21 Configure Spring Security 6 with JWT authentication

Spring Security 6 Configuration Copy

// Spring Boot 3.5.6 Security Configuration


package com.example.security.config;

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.method.configur
import org.springframework.security.config.annotation.web.builders.Ht
import org.springframework.security.config.annotation.web.configurati
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncod
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswo

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**")
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/user/**").hasAnyRole("USER", "
.anyRequest().authenticated()
)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.S
)
.addFilterBefore(jwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exceptions ->
exceptions.authenticationEntryPoint(jwtAuthentication
);

return http.build();
}

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

// JWT Filter Implementation


public class JwtAuthenticationFilter extends OncePerRequestFilter

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {

String token = extractToken(request);

if (token != null && jwtUtil.validateToken(token)) {


String username = jwtUtil.extractUsername(token);

UserDetails userDetails = userDetailsService


.loadUserByUsername(username);

UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities

authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails
);

SecurityContextHolder.getContext().setAuthentication(
}

filterChain.doFilter(request, response);
}

private String extractToken(HttpServletRequest request) {


String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer
return bearerToken.substring(7);
}
return null;
}
}
}

3
6. System Design & Architecture

🏗️ System Design Approaches

Monolithic Microservices
🏢 🔗
Architecture Architecture

Simple Single Deploy ACID Scalable Independent Polyglot

When to use: Small to medium When to use: Large scale


applications, startup MVPs, when applications, multiple teams, need
team size is small. for independent scaling.

Advantages: Advantages:

Simple development and Independent development


deployment and deployment
Easier debugging and testing Fault isolation
Strong consistency (ACID Technology diversity
transactions) Horizontal scaling
Lower operational
complexity
Disadvantages:

Disadvantages:
Single point of failure Distributed system
Difficult to scale horizontally complexity
Long deployment cycles Eventual consistency
Technology lock-in Operational overhead
Network latency

Event-Driven Serverless
⚡ ☁️
Architecture Architecture

Async Decoupled Scalable Cost-effective Auto-scale

No Ops
When to use: Real-time processing,
IoT, financial systems, notification
When to use: Sporadic workloads,
systems.
event processing, API backends,
chatbots.
Advantages:

Loose coupling Advantages:


High scalability
No server management
Real-time processing
Pay-per-use pricing
Better fault tolerance
Automatic scaling
Quick deployment

Disadvantages:

Complex debugging Disadvantages:


Event ordering challenges
Cold start latency
Message broker dependency
Vendor lock-in
Learning curve
Limited execution time
Debugging challenges

🎯 System Design Interview Questions


6.1.SD1 Design a URL Shortening Service like TinyURL

Answer:

📊 Requirements:
Functional: Shorten URLs, redirect to original URLs, custom URLs
Non-Functional: High availability, scalability, low latency
Scale: 100M URLs, 100M requests/day, 1KB per URL

🏗️ Architecture:
1. API Layer: REST APIs for URL shortening and redirection
2. Encoding Service: Base62 encoding for short URLs
3. Storage: Redis (cache) + PostgreSQL (persistent storage)
4. Cache Strategy: LRU cache for hot URLs
5. CDN: For static assets and frequently accessed URLs

URL Encoding Algorithm Copy

public class URLShortener {


private static final String ALPHABET =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567
private static final int BASE = ALPHABET.length();

// Bijective function - encode integer to base62


public String encode(long id) {
StringBuilder shortURL = new StringBuilder();

while (id > 0) {


shortURL.append(ALPHABET.charAt((int)(id % BASE)));
id = id / BASE;
}

return shortURL.reverse().toString();
}

// Decode base62 string to integer


public long decode(String shortURL) {
long id = 0;

for (int i = 0; i < shortURL.length(); i++) {


id = id * BASE + ALPHABET.indexOf(shortURL.charAt(i));
}

return id;
}

// Distributed ID generation (Twitter Snowflake-like)


public long generateId() {
long timestamp = System.currentTimeMillis() - 1609459200000L;
long datacenterId = 1; // From configuration
long machineId = 1; // From configuration
long sequence = ThreadLocalRandom.current().nextLong(4096);

return (timestamp << 22) | (datacenterId << 17) |


(machineId << 12) | sequence;
}
}

 
6.2.SD2 Design a Distributed Cache System

Answer:

🔑 Requirements:
Capacity: 1TB total, distributed across nodes
Latency: < 5ms for cache hits
Consistency: Eventual consistency
Availability: 99.99%

🏗️ Architecture Components:
1. Consistent Hashing: For data distribution and minimal reshuffling
2. Replication: Each key stored in N nodes (typically 3)
3. LRU Eviction: When cache reaches capacity
4. Write-through/Write-behind: Cache persistence strategies
5. Health Checks: Automatic node failure detection and recovery

Consistent Hashing Implementation Copy

public class ConsistentHash<T> {


private final SortedMap<Integer, T> circle = new TreeMap<>();
private final int numberOfReplicas;
private final HashFunction hashFunction;

public ConsistentHash(int numberOfReplicas, Collection<T> nodes)


this.numberOfReplicas = numberOfReplicas;
this.hashFunction = new MD5Hash();

for (T node : nodes) {


addNode(node);
}
}

public void addNode(T node) {


for (int i = 0; i < numberOfReplicas; i++) {
int hash = hashFunction.hash(node.toString() + i);
circle.put(hash, node);
}
}

public void removeNode(T node) {


for (int i = 0; i < numberOfReplicas; i++) {
int hash = hashFunction.hash(node.toString() + i);
circle.remove(hash);
}
}

public T getNode(String key) {


if (circle.isEmpty()) return null;

int hash = hashFunction.hash(key);

// Find the first node with hash >= key's hash


SortedMap<Integer, T> tailMap = circle.tailMap(hash);

// Wrap around if not found


int nodeHash = tailMap.isEmpty() ? circle.firstKey() : tailMa

return circle.get(nodeHash);
}

// Virtual nodes for better distribution


private void addVirtualNode(T node, int replicaIndex) {
String virtualNode = node.toString() + "#" + replicaIndex;
int hash = hashFunction.hash(virtualNode);
circle.put(hash, node);
}
}

+
8. Extra Interview Questions & Answers

🚀 Advanced Spring Boot Questions


8.1. E1 How to handle database transactions in microservices?

Answer: Use Saga pattern for distributed transactions

📊 Saga Pattern Approaches:

Pattern Use Case Complexity

Choreography Simple workflows, few services Low

Orchestration Complex workflows, many services High

Saga Orchestrator Example Copy

@Component
public class OrderSagaOrchestrator {

@Transactional
public void processOrder(OrderRequest request) {
try {
// Step 1: Reserve inventory
inventoryService.reserveItems(request.getItems());

// Step 2: Process payment


paymentService.processPayment(request.getPayment());

// Step 3: Create order


Order order = orderService.createOrder(request);

// Step 4: Schedule shipping


shippingService.scheduleShipping(order);

// Step 5: Send notifications


notificationService.sendOrderConfirmation(order);

} catch (Exception e) {
// Compensating transactions
inventoryService.releaseReservation(request.getItems());
paymentService.refundPayment(request.getPayment());
throw e;
}
}
}

// Event-driven Saga (Choreography)


@Component
public class OrderSagaChoreography {

@EventListener
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT
public void handleOrderCreated(OrderCreatedEvent event) {
// Publish events for other services
eventPublisher.publish(new ReserveInventoryEvent(event.getOrd
}

@EventListener
public void handleInventoryReserved(InventoryReservedEvent event)
eventPublisher.publish(new ProcessPaymentEvent(event.getOrder
}

@EventListener
public void handlePaymentProcessed(PaymentProcessedEvent event) {
if (event.isSuccess()) {
eventPublisher.publish(new CompleteOrderEvent(event.getOr
} else {
eventPublisher.publish(new CancelOrderEvent(event.getOrde
}
}
}
8.2. E2 How to implement rate limiting in Spring Boot?

Answer: Multiple approaches based on requirements

🎯 Rate Limiting Algorithms:


1. Token Bucket: Fixed capacity bucket, tokens added at fixed rate
2. Leaky Bucket: Fixed outflow rate, burst absorption
3. Fixed Window: Simple but allows bursts at window edges
4. Sliding Window: More accurate but complex

Rate Limiter with Resilience4j Copy

@Configuration
public class RateLimitConfig {

@Bean
public RateLimiterRegistry rateLimiterRegistry() {
return RateLimiterRegistry.of(
RateLimiterConfig.custom()
.limitForPeriod(100) // 100 requests
.limitRefreshPeriod(Duration.ofSeconds(60)) // per mi
.timeoutDuration(Duration.ofMillis(500)) // wait t
.build()
);
}

@Bean
public RateLimiterProperties rateLimiterProperties() {
return new RateLimiterProperties();
}
}

@Service
public class ApiService {

private final RateLimiter rateLimiter;

public ApiService(RateLimiterRegistry registry) {


this.rateLimiter = registry.rateLimiter("apiLimiter");
}

@RateLimiter(name = "apiLimiter", fallbackMethod = "fallbackMetho


public ResponseEntity<String> processRequest(String request) {
// Process the request
return ResponseEntity.ok("Processed: " + request);
}

private ResponseEntity<String> fallbackMethod(String request, Thr


return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
.header("Retry-After", "60")
.body("Rate limit exceeded. Please try again later.");
}
}

// Custom rate limiter with Redis


@Component
public class RedisRateLimiter {

private final RedisTemplate<String, String> redisTemplate;

public boolean isAllowed(String key, int maxRequests, Duration du


String redisKey = "rate_limit:" + key;

Long current = redisTemplate.opsForValue().increment(redisKey

if (current == 1) {
// Set expiry on first request
redisTemplate.expire(redisKey, duration.getSeconds(), Tim
}

return current <= maxRequests;


}
}

🔐 Security Best Practices


What are essential security practices for Spring Boot
8.3. E3
applications?

Answer:

🛡️ Security Checklist:
1. Input Validation: Validate all inputs, use DTO validation
2. Authentication: JWT with proper expiration, refresh tokens
3. Authorization: Role-based access control (RBAC)
4. HTTPS: Enforce HTTPS, use HSTS headers
5. SQL Injection: Use prepared statements, JPA named parameters
6. XSS Protection: Content Security Policy, input sanitization
7. CSRF Protection: Enable CSRF for state-changing operations
8. Secrets Management: Use environment variables, vaults
9. Audit Logging: Log security events
10. Regular Updates: Keep dependencies updated

Security Configuration Example Copy

@Configuration
@EnableWebSecurity
public class AdvancedSecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws
http
// HTTPS enforcement
.requiresChannel(channel ->
channel.anyRequest().requiresSecure())

// Headers security
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("default-src 'self'; script-src
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.maxAgeInSeconds(31536000))
.frameOptions(frame -> frame.sameOrigin())
.xssProtection(xss -> xss.enable()))

// CORS configuration
.cors(cors -> cors.configurationSource(corsConfigurationS

// CSRF configuration (enabled for state-changing operati


.csrf(csrf -> csrf
.ignoringRequestMatchers("/api/public/**")
.csrfTokenRepository(CookieCsrfTokenRepository.withHt

// Session management
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELES
.maximumSessions(1))

// Authentication
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthent

// Authorization
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/user/**").hasAnyRole("USER", "
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated());

return http.build();
}

// Password encoder with multiple algorithms


@Bean
public PasswordEncoder passwordEncoder() {
return new DelegatingPasswordEncoder("bcrypt", Map.of(
"bcrypt", new BCryptPasswordEncoder(),
"scrypt", new SCryptPasswordEncoder(),
"pbkdf2", new Pbkdf2PasswordEncoder()
));
}
}
4
10. Algorithms & Data Structures

10.1.
A1 Implement Trie data structure for autocomplete

Trie Implementation with Autocomplete Copy

public class TrieNode {


private Map<Character, TrieNode> children;
private boolean isEndOfWord;
private int frequency;
private String word;

public TrieNode() {
this.children = new HashMap<>();
this.isEndOfWord = false;
this.frequency = 0;
}
}

public class Trie {


private final TrieNode root;

public Trie() {
this.root = new TrieNode();
}

public void insert(String word) {


TrieNode current = root;

for (char c : word.toCharArray()) {


current = current.getChildren()
.computeIfAbsent(c, k -> new TrieNode());
}

current.setEndOfWord(true);
current.setFrequency(current.getFrequency() + 1);
current.setWord(word);
}

public List<String> autocomplete(String prefix, int limit) {


TrieNode node = findNode(prefix);
if (node == null) return Collections.emptyList();

List<WordFrequency> results = new ArrayList<>();


collectWords(node, results);

// Sort by frequency (descending) then alphabetically


results.sort((a, b) -> {
int freqCompare = Integer.compare(b.frequency, a.frequenc
return freqCompare != 0 ? freqCompare : a.word.compareTo(
});

return results.stream()
.limit(limit)
.map(wf -> wf.word)
.collect(Collectors.toList());
}

private void collectWords(TrieNode node, List<WordFrequency> resu


if (node.isEndOfWord()) {
results.add(new WordFrequency(node.getWord(), node.getFre
}

for (TrieNode child : node.getChildren().values()) {


collectWords(child, results);
}
}

private TrieNode findNode(String prefix) {


TrieNode current = root;

for (char c : prefix.toCharArray()) {


current = current.getChildren().get(c);
if (current == null) return null;
}

return current;
}

// Fuzzy search with Levenshtein distance


public List<String> fuzzySearch(String word, int maxDistance) {
List<WordFrequency> results = new ArrayList<>();
fuzzySearch(root, word, "", 0, maxDistance, results);

return results.stream()
.map(wf -> wf.word)
.collect(Collectors.toList());
}

private void fuzzySearch(TrieNode node, String word, String curre


int index, int maxDistance, List<WordFrequ
if (index == word.length()) {
if (node.isEndOfWord()) {
results.add(new WordFrequency(current, node.getFreque
}
return;
}

char target = word.charAt(index);

for (Map.Entry<Character, TrieNode> entry : node.getChildren(


char c = entry.getKey();
TrieNode child = entry.getValue();

int distance = (c == target) ? 0 : 1;

if (distance <= maxDistance) {


fuzzySearch(child, word, current + c, index + 1,
maxDistance - distance, results);
}
}
}
}

class WordFrequency {
String word;
int frequency;

WordFrequency(String word, int frequency) {


this.word = word;
this.frequency = frequency;
}
}
10.2.
A2 Implement LRU Cache

LRU Cache Implementation Copy

import java.util.*;

public class LRUCache {


private class Node {
K key;
V value;
Node prev;
Node next;

Node(K key, V value) {


this.key = key;
this.value = value;
}
}

private final int capacity;


private final Map cache;
private Node head;
private Node tail;

public LRUCache(int capacity) {


this.capacity = capacity;
this.cache = new HashMap<>();
this.head = new Node(null, null);
this.tail = new Node(null, null);
head.next = tail;
tail.prev = head;
}

public V get(K key) {


Node node = cache.get(key);
if (node == null) return null;

// Move to front (most recently used)


moveToFront(node);
return node.value;
}

public void put(K key, V value) {


Node node = cache.get(key);

if (node != null) {
// Update existing node
node.value = value;
moveToFront(node);
} else {
// Create new node
node = new Node(key, value);
cache.put(key, node);
addToFront(node);

// Check capacity
if (cache.size() > capacity) {
removeLRU();
}
}
}

private void moveToFront(Node node) {


removeNode(node);
addToFront(node);
}

private void addToFront(Node node) {


node.next = head.next;
node.prev = head;
head.next.prev = node;
head.next = node;
}

private void removeNode(Node node) {


node.prev.next = node.next;
node.next.prev = node.prev;
}

private void removeLRU() {


Node lru = tail.prev;
removeNode(lru);
cache.remove(lru.key);
}

// Thread-safe version using ReadWriteLock


public class ConcurrentLRUCache {
private final LRUCache cache;
private final ReadWriteLock lock = new ReentrantReadWriteLock
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();

public ConcurrentLRUCache(int capacity) {


this.cache = new LRUCache<>(capacity);
}

public V get(K key) {


readLock.lock();
try {
return cache.get(key);
} finally {
readLock.unlock();
}
}

public void put(K key, V value) {


writeLock.lock();
try {
cache.put(key, value);
} finally {
writeLock.unlock();
}
}
}
}

12. Performance Optimization

12.1.
P1 How to optimize Spring Boot application performance?

Answer: Multi-layered optimization approach

🎯 Optimization Strategies:

Layer Optimization Impact

Indexing, Query Optimization,


Database High
Connection Pooling

Caching, Async Processing, Connection


Application High
Pooling

JVM GC Tuning, Heap Sizing, JIT Optimization Medium

Infrastructure CDN, Load Balancing, Auto-scaling High

Performance Monitoring Configuration Copy

# application.yml - Performance Configuration


spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 10
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000

jpa:
properties:
hibernate:
jdbc:
batch_size: 50
order_inserts: true
order_updates: true
generate_statistics: true

cache:
type: redis
redis:
time-to-live: 600000
cache-null-values: false

management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
distribution:
percentiles-histogram:
http.server.requests: true
# JVM Options for production
# -Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200
# -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
# -XX:NativeMemoryTracking=summary -XX:+PrintGCDetails

🔧 Key Optimizations:
1. Connection Pooling: Use HikariCP with proper pool sizing
2. Batch Processing: Enable JDBC batching for bulk operations
3. Caching Strategy: Multi-level caching (L1/L2/Redis)
4. Async Processing: Use @Async for non-blocking operations
5. Database Indexing: Create indexes on frequently queried columns
6. Garbage Collection: Use G1GC for better throughput

📊 Interview Preparation Statistics

150+ 50+ 10+ 5


Questions Code System Architecture
Covered Examples Design Styles
Patterns

This comprehensive guide covers everything from Core Java 8-21 to advanced
System Design patterns.
Continuously updated for 2025 interviews with latest Spring Boot 3.5.6 features.

📅 Last Updated: December 2024 | 🚀 Version: 3.5.6

Java & Spring Boot Job Interview Q&A (2025 Edition)


14. Core Java (Java 8–21)

14.1.
What are the main OOP principles in Java?

Encapsulation, Inheritance, Polymorphism, and Abstraction. They promote code reusability and modularity.
14.2.
Difference between HashMap and ConcurrentHashMap?

HashMap is not thread-safe, while ConcurrentHashMap allows concurrent read/write operations by segmenting data and
prevents ConcurrentModificationException.
14.3.
What is the Stream API used for?

Stream API processes collections in a functional way (filter, map, reduce). It improves readability and supports parallel
processing.

14.4.
Explain the difference between final, finally, and finalize().

final: Makes a variable constant or prevents inheritance.


finally: Block that executes after try-catch.
finalize(): Called by GC before object destruction (deprecated).

14.5.
What are records in Java?

Introduced in Java 14, records are compact classes for immutable data carriers.

Example: public record User(String name, int age) {}

14.6.
What are sealed classes?

Sealed classes (Java 17) restrict inheritance.

Example: public sealed class Shape permits Circle, Square {}

14.7.
What are virtual threads?

Introduced in Java 21 — lightweight threads that scale concurrency efficiently without blocking OS threads.
16. Spring Core & Boot Basics

16.1.
What is Dependency Injection (DI)?

A design pattern where Spring manages object creation and wiring instead of manually instantiating dependencies.
16.2.
Difference between @Component, @Service, and @Repository?

@Component: Generic stereotype.


@Service: Marks a service layer.
@Repository: Marks DAO layer and enables exception translation.

16.3.
What is the role of @SpringBootApplication?

Combines @Configuration, @EnableAutoConfiguration, and @ComponentScan.

16.4.
How does Spring Boot simplify configuration?

It uses auto-configuration and opinionated defaults via starter dependencies.

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

Using @ControllerAdvice and @ExceptionHandler.

16.6.
What is the difference between application.properties and application.yml?

Both define configurations; .yml supports hierarchical data structure and is easier to read.
18. Spring Boot Advanced

18.1.
What is @Transactional used for?

Manages transactions automatically; rolls back changes if an exception occurs.


18.2.
How does Spring Data JPA simplify database access?

Eliminates boilerplate DAO code and provides CRUD methods using repository interfaces.

18.3.
What is the purpose of @Cacheable annotation?

Caches method results to improve performance on repeated calls.

18.4.
How can you schedule tasks in Spring Boot?

Using @Scheduled annotation with cron expressions.


18.5.
What are Actuators in Spring Boot?

Provide endpoints to monitor and manage the application (e.g., /actuator/health).

18.6.
How do you secure REST APIs with JWT?

Client logs in → receives JWT → server validates token for access control.

18.7.
How do you create a Docker image for a Spring Boot app?

1. Create Dockerfile:

FROM openjdk:17
COPY target/app.jar app.jar
ENTRYPOINT ['java', '-jar', '/app.jar']

2. Run: docker build -t myapp .


20. Database & JPA

20.1.
Explain lazy vs eager fetching.

Lazy: Loads data when accessed.


Eager: Loads immediately with parent entity.

20.2.
What are the common entity relationships?

@OneToOne, @OneToMany, @ManyToOne, @ManyToMany


20.3.
What's the difference between save() and saveAndFlush()?

save(): Persists data in session.


saveAndFlush(): Persists and immediately writes changes to DB.

20.4.
How does Hibernate handle caching?

Level 1 (Session) – default.


Level 2 (SessionFactory) – optional (Ehcache, Redis, etc.).
20.5.
What is JPQL?

Java Persistence Query Language — operates on entity objects instead of tables.

22. Microservices with Spring Cloud

22.1.
What is a microservice?

Independent, small, loosely coupled service focusing on a specific business capability.

22.2.
How do microservices communicate?

REST APIs, Feign clients, gRPC, or message brokers (Kafka, RabbitMQ).

22.3.
What is a Config Server?

Centralizes external configuration for multiple services.

22.4.
What is the role of Eureka Server?

Service discovery — helps services find and communicate with each other dynamically.

22.5.
What is Circuit Breaker in microservices?

Prevents cascading failures when one service is down (Resilience4j or Hystrix).

22.6.
What is an API Gateway?

Single entry point for client requests that handles routing, security, and rate-limiting.

22.7.
What is idempotent API?

An API that can be called multiple times without changing the result (e.g., PUT or GET).
24. Deployment, Docker & DevOps Basics

24.1.
What is Docker?

A containerization platform that packages apps with dependencies for consistent deployment.
24.2.
Difference between Docker image and container?

Image: Blueprint of the app.


Container: Running instance of an image.
24.3.
How do you deploy a Spring Boot app to AWS?

Package app → push to EC2 or Elastic Beanstalk → configure environment variables.

24.4.
How do you store application secrets safely?

Use environment variables or AWS Secrets Manager / Vault, not in code.

24.5.
What is CI/CD?

Continuous Integration & Continuous Deployment automate testing and deployment pipelines.

26. System Design & Architecture

26.1.
What is a layered architecture in Spring Boot?

Controller → Service → Repository → Entity. Promotes separation of concerns.

26.2.
Which design patterns are commonly used in Spring?

Singleton, Factory, Proxy, Template.

26.3.
What are REST API best practices?

Use proper HTTP verbs, status codes, versioning, and validation.


26.4.
How do you make APIs scalable?

Use caching, load balancers, async communication, and stateless design.

26.5.
How does caching improve performance?

Reduces DB load by serving frequently accessed data from memory.


28. Testing

28.1.
What is the difference between unit and integration testing?

Unit: Tests one method or class in isolation.


Integration: Tests combined modules (REST + DB).

28.2.
How do you test a service using Mockito?

@Mock UserRepository repo; @InjectMocks UserService service;

28.3.
What is @SpringBootTest used for?

Loads full Spring context for integration testing.

28.4.
What are Testcontainers?

Library that runs real dependencies (like DBs) in Docker during tests.

30. HR & Behavioral Questions

30.1.
Tell me about your last project.

Explain business goal, tech stack (Spring Boot, Angular, MySQL, Docker), and your role.

30.2.
What challenges did you face and how did you solve them?

Discuss a real issue like slow queries or security setup and your solution.
30.3.
How do you stay updated with new tech?

Follow official Spring blogs, YouTube, GitHub, and open-source projects.

30.4.
How do you ensure code quality?

Code reviews, SonarQube checks, unit tests, and following clean code principles.

You might also like