Most Asked Full Stack Java Developer Interview Questions with Detailed Answers for Freshers and Experienced Professionals
Landing a Full Stack Java Developer role in 2026 is competitive. Companies are not just looking for developers who can write Java code — they want professionals who can build complete, production-grade applications across the backend, database layer, REST API layer, and frontend. That means interviewers will test you across Java core concepts, Spring Boot, Hibernate, Microservices architecture, and increasingly React or Angular for the frontend.
Whether you are a fresher stepping into your first Java interview or an experienced developer preparing for a senior role switch, this guide covers the top 30 most asked Full Stack Java interview questions and answers for 2026 — with clear, detailed answers that go beyond surface-level definitions.
If you want structured, expert-led training that prepares you end-to-end for Full Stack Java interviews and placements, check out JustAcademy's Full Stack Java Developer Bootcamp with real projects and 100% placement support.
Table of Contents
- Core Java Interview Questions
- Spring Boot Interview Questions
- Hibernate and JPA Interview Questions
- Microservices Interview Questions
- React and Frontend Integration Interview Questions
- Frequently Asked Questions
Section 1: Core Java Interview Questions for Full Stack Developers
These questions test your foundation. No matter how experienced you are, interviewers always begin with Core Java. A weak foundation here can end the interview early.
Question 1. What is the difference between JDK, JRE, and JVM?
This is one of the most common opening questions in any Java interview. Interviewers ask it to gauge whether you understand the Java execution model before they dive deeper.
JVM stands for Java Virtual Machine. It is the runtime engine that actually executes Java bytecode. It is platform-specific, meaning there is a different JVM implementation for Windows, Linux, and macOS. The JVM handles memory management, garbage collection, and bytecode interpretation or JIT compilation.
JRE stands for Java Runtime Environment. It includes the JVM plus the standard Java class libraries and runtime components needed to run a Java application. If someone only wants to run a Java program and not develop one, they install the JRE.
JDK stands for Java Development Kit. It includes the JRE plus development tools such as the Java compiler (javac), the debugger, JavaDoc, and other utilities needed to write and build Java applications. As a developer, you always work with the JDK.
In simple terms: JDK is for development. JRE is for running. JVM is the execution engine inside both.
In 2026, most developers work with Java 21 LTS. The distinction between JDK and JRE has become less prominent since Java 9, when modular JDKs made it possible to create custom minimal runtimes, but the conceptual understanding remains a standard interview topic.
Question 2. What are the four pillars of Object-Oriented Programming in Java?
Interviewers ask this to confirm you understand the design philosophy underlying Java before they ask you to apply it in design or code review questions.
The four pillars are Encapsulation, Inheritance, Polymorphism, and Abstraction.
Encapsulation means bundling data (fields) and the methods that operate on that data together inside a class, and restricting direct access to internal data by making fields private and exposing them through public getters and setters. Encapsulation protects the integrity of an object's state.
Inheritance means a child class can acquire the properties and behaviours of a parent class using the extends keyword. It promotes code reuse and establishes an IS-A relationship between classes.
Polymorphism means one interface, many implementations. In Java this takes two forms. Compile-time polymorphism is achieved through method overloading — same method name, different parameter lists. Runtime polymorphism is achieved through method overriding — a child class provides a specific implementation of a method defined in the parent.
Abstraction means hiding implementation details and exposing only the essential features of an object. In Java this is achieved through abstract classes and interfaces. The user knows what an object does, not how it does it.
Question 3. What is the difference between an abstract class and an interface in Java?
This is asked constantly because it directly impacts how you design your application architecture — something a full stack developer must get right.
An abstract class is a class that cannot be instantiated directly. It can have both abstract methods (no implementation) and concrete methods (with implementation). It can have instance variables, constructors, and any access modifier on its methods. A class can extend only one abstract class due to Java's single inheritance rule.
An interface (prior to Java 8) was a pure contract — only abstract method signatures and constants. Since Java 8, interfaces can have default methods and static methods with implementations. Since Java 9, they can also have private methods. A class can implement multiple interfaces, which is how Java achieves a form of multiple inheritance.
When to use which: use an abstract class when you want to share code among closely related classes and provide a partial implementation. Use an interface when you want to define a contract that unrelated classes can implement, or when you need multiple inheritance of type.
In 2026 with Java 21, sealed classes and interfaces add another dimension — you can now restrict which classes may implement an interface, giving you more controlled type hierarchies.
Question 4. What is the difference between HashMap and ConcurrentHashMap?
This question is asked specifically for full stack and backend roles because it tests whether you understand thread safety — critical for building REST APIs that serve concurrent requests.
HashMap is a standard key-value data structure that is not thread-safe. If multiple threads access a HashMap concurrently and at least one thread modifies it structurally, it must be synchronized externally, otherwise you risk data corruption or infinite loops during rehashing.
ConcurrentHashMap is a thread-safe variant designed for high-concurrency scenarios. In Java 8 and later, it uses a fine-grained locking strategy where locks are applied at the bucket level rather than locking the entire map. This allows multiple threads to read and write concurrently with minimal contention, providing much better throughput than a synchronized HashMap.
The key differences: HashMap allows one null key and multiple null values. ConcurrentHashMap does not allow null keys or null values, because null values create ambiguity about whether a key is absent or mapped to null during concurrent operations. HashMap is best for single-threaded contexts or when you control synchronization externally. ConcurrentHashMap is the right choice for concurrent REST API request handling, caches, and any shared mutable state in multi-threaded environments.
Question 5. What is the difference between == and .equals() in Java?
Deceptively simple, this question has caught out many experienced developers who give an incomplete answer.
The == operator compares references in Java for objects. When you use == with two object variables, you are asking whether both variables point to the exact same object in memory — the same memory address.
The .equals() method compares the content or logical equality of two objects. The default implementation in the Object class behaves the same as == (reference comparison), but most classes override it. String, Integer, List, and all well-designed custom classes override .equals() to compare meaningful content.
For example, two String objects created separately with the same content will return false with == but true with .equals(). However, String literals that are interned in the String pool may return true with == as well, which is a common source of confusion.
As a full stack developer, the practical implication is in your JPA entity comparisons, your unit test assertions, and your collection operations. Always override both equals() and hashCode() together in entity classes — this is a contract in Java, and violating it causes subtle bugs in HashSets, HashMaps, and Hibernate's dirty checking.
Question 6. What are Java Streams and how do you use them?
Streams are asked in virtually every modern Java interview because they are used everywhere in production codebases for data processing, and interviewers want to see whether you write modern Java or still rely on verbose loops.
Java Streams, introduced in Java 8, provide a declarative, functional-style API for processing sequences of elements. A stream is not a data structure — it is a pipeline of operations applied to a source such as a List, Set, array, or I/O channel.
A stream pipeline consists of three parts. The source creates the stream, for example calling .stream() on a List. Intermediate operations are lazy, meaning they do not execute until a terminal operation is called, and they return another stream. Examples include filter(), map(), flatMap(), sorted(), distinct(), and limit(). Terminal operations trigger the pipeline execution and produce a result or side effect. Examples include collect(), forEach(), count(), findFirst(), anyMatch(), and reduce().
Key characteristics of streams: they are lazy (nothing executes until a terminal operation is called), they can only be consumed once (you cannot reuse a stream after a terminal operation), and they support parallel processing through parallelStream() which uses the ForkJoinPool under the hood.
A common interview follow-up is the difference between map() and flatMap(). The map() operation transforms each element to another element, producing a Stream of the transformed elements. The flatMap() operation transforms each element to a Stream and then flattens all those streams into a single stream — useful when each element maps to a collection.
Question 7. What is the difference between String, StringBuilder, and StringBuffer?
This is a classic question that tests memory and performance awareness — both important in high-throughput Java applications.
String objects in Java are immutable. Every time you concatenate strings using the + operator, a new String object is created and the old one becomes eligible for garbage collection. This is fine for small, infrequent operations but is extremely inefficient inside loops.
StringBuilder is a mutable sequence of characters and is not thread-safe. It is the right choice for string manipulation within a single thread — inside a method, a loop, or a builder pattern. It is significantly faster than String concatenation in loops because it modifies the same internal character array rather than creating new objects.
StringBuffer is functionally identical to StringBuilder but all its methods are synchronized, making it thread-safe. It was introduced in early Java (pre-Java 5) before StringBuilder existed. In 2026, StringBuffer is rarely used in new code because the synchronization overhead is unnecessary in most scenarios — if you need thread safety around string building, you typically use better concurrency patterns at a higher level.
The practical rule: use String for constants and immutable text. Use StringBuilder for string construction within a method or single thread. Avoid StringBuffer unless you have a specific thread-safety requirement around string manipulation.
Section 2: Spring Boot Interview Questions for Full Stack Java Developers
Spring Boot powers the majority of Java backend services built today. Every full stack Java interview will include Spring Boot questions, ranging from basics to advanced REST API design and security.
Question 8. What is Spring Boot and how is it different from the Spring Framework?
The Spring Framework is a comprehensive Java application framework providing dependency injection, AOP, data access, transaction management, and much more. However, configuring a Spring application traditionally required significant XML or Java configuration, setting up application servers, managing dependencies manually, and wiring everything together — which was time-consuming and error-prone.
Spring Boot is an opinionated layer built on top of the Spring Framework that eliminates most of that configuration through auto-configuration, embedded servers, and starter dependencies. Spring Boot follows the convention-over-configuration principle — it makes intelligent default decisions so you can get a production-ready application running with minimal setup.
The three core features that differentiate Spring Boot are: auto-configuration (Spring Boot examines your classpath and automatically configures beans based on what it finds), starter dependencies (pre-bundled dependency groups like spring-boot-starter-web that bring in everything you need for a specific capability), and embedded servers (Tomcat, Jetty, or Undertow embedded directly in the JAR so you run your application with java -jar without needing a separate server installation).
In 2026, Spring Boot 3.3 and 3.4 are the standard versions, built on Spring Framework 6 and requiring Java 17 as a minimum. They introduce native compilation via GraalVM, improved observability with Micrometer, and Virtual Thread support as covered elsewhere in this guide.
Question 9. What is dependency injection and what types does Spring support?
Dependency Injection is a design pattern where an object does not create its own dependencies — instead, the dependencies are provided (injected) by an external container. In Spring Boot, the container is the Spring IoC (Inversion of Control) container.
Spring supports three types of dependency injection.
Constructor injection provides dependencies through the class constructor. It is the recommended approach in 2026 because it makes dependencies explicit, supports immutability (fields can be final), makes testing straightforward with simple constructor calls, and prevents the object from being created in an incomplete state.
Setter injection provides dependencies through setter methods. It is useful when dependencies are optional or when circular dependencies must be resolved, but it allows objects to exist in a partially initialized state.
Field injection uses the @Autowired annotation directly on a field. While it is the most concise to write, it is considered bad practice in modern Spring development because it hides dependencies, makes testing harder (you cannot inject mocks without reflection), and Spring itself recommends against it in the official documentation.
The practical guidance for interviews: state that you prefer constructor injection, explain why, and mention that you use @RequiredArgsConstructor from Lombok in combination with final fields to reduce boilerplate while maintaining constructor injection benefits.
Question 10. What is the difference between @Component, @Service, @Repository, and @Controller?
All four are Spring stereotype annotations that mark a class as a Spring-managed bean. They all trigger component scanning and cause Spring to create and manage an instance of the class. However, they carry semantic meaning and some provide additional behaviour.
@Component is the generic stereotype. It marks any class as a Spring component. The other three are specialisations of @Component.
@Service is used to mark the business logic layer. It carries no additional technical behaviour in current Spring versions, but it communicates intent to developers and tools — this class contains business rules and service logic.
@Repository is used to mark the data access layer. It provides one important additional behaviour: Spring applies persistence exception translation to @Repository classes, converting database-specific exceptions (like JPA or JDBC exceptions) into Spring's unified DataAccessException hierarchy. This keeps your business layer decoupled from the specific data access technology.
@Controller is used in Spring MVC to mark classes that handle HTTP requests. It works with @RequestMapping and its derivatives to map URLs to handler methods and typically returns view names for template rendering.
@RestController is a composed annotation combining @Controller and @ResponseBody. It marks every method in the class to return data directly serialized to the HTTP response body (typically JSON), rather than resolving a view name. This is what you use for REST API controllers in Spring Boot.
Question 11. What is the difference between @RequestParam and @PathVariable?
This comes up in every REST API interview and tests whether you understand HTTP request structure.
@PathVariable extracts values from the URI path itself. For example, if your endpoint mapping is /api/products/{id} and the request comes in as /api/products/42, then @PathVariable Long id gives you the value 42. Path variables are typically used for resource identifiers — they identify which specific resource you are acting on.
@RequestParam extracts values from the query string in the URL. For example, if the request comes in as /api/products?category=electronics&page=2, then @RequestParam String category gives you "electronics" and @RequestParam int page gives you 2. Request parameters are typically used for filtering, searching, sorting, and pagination.
The key distinction is structural: path variables are part of the URL path and are typically mandatory (the URL pattern will not match without them). Request parameters are appended after a question mark and can be optional — you can set a defaultValue in @RequestParam to handle cases where the parameter is not provided.
Question 12. What is Spring Security and how do you implement JWT authentication?
Spring Security is the standard framework for authentication and authorization in Spring Boot applications. It provides a comprehensive security model with filters, authentication providers, user details services, and method-level security.
JWT stands for JSON Web Token. It is a compact, URL-safe token format used for stateless authentication. A JWT contains three parts separated by dots: the header (algorithm and token type), the payload (claims — user ID, roles, expiry), and the signature (cryptographic verification).
The JWT authentication flow in Spring Boot works as follows. The user sends credentials (username and password) to a login endpoint. The application validates the credentials, and if valid, generates a signed JWT using a secret key and returns it to the client. The client stores the JWT (typically in memory or localStorage) and includes it in the Authorization header as "Bearer [token]" on every subsequent request. A Spring Security filter intercepts each request, extracts the JWT, validates the signature and expiry, and if valid, sets the authentication in the SecurityContext so that the request proceeds as authenticated.
Implementation involves creating a JwtUtil class for token generation and validation, a JwtAuthenticationFilter that extends OncePerRequestFilter to intercept requests, a UserDetailsService implementation that loads user details from the database, and a SecurityConfiguration class that configures which endpoints are public, which require authentication, and wires the JWT filter into the filter chain before UsernamePasswordAuthenticationFilter.
In Spring Boot 3.x with Spring Security 6, the SecurityFilterChain bean is the standard configuration approach, and the old WebSecurityConfigurerAdapter is removed entirely.
Question 13. What is the difference between @Transactional and manual transaction management?
@Transactional is Spring's declarative transaction management. When you annotate a method or class with @Transactional, Spring wraps the method execution in a transaction using AOP. The transaction begins before the method executes and commits when the method returns successfully. If a RuntimeException is thrown, the transaction rolls back automatically. This is clean, non-invasive, and keeps transaction logic out of your business code.
Manual transaction management uses PlatformTransactionManager directly in your code — you call begin, commit, and rollback explicitly. This gives you full programmatic control and is useful in complex scenarios where transaction boundaries are dynamic or conditional.
Key @Transactional properties you should know for interviews: propagation defines how transactions behave when a transactional method is called from another transactional method (REQUIRED is the default — join existing or create new), isolation defines the database isolation level for the transaction, readOnly=true is an optimisation hint for read-only operations that can improve performance with Hibernate, and rollbackFor lets you specify which exception types should trigger a rollback (by default only unchecked exceptions rollback).
A common interview gotcha: @Transactional only works on public methods when using Spring's default proxy-based AOP. If you call a @Transactional method from within the same class (self-invocation), the transaction will not be applied because the call bypasses the Spring proxy.
Question 14. What are Spring Boot Actuator endpoints and why are they important?
Spring Boot Actuator provides production-ready monitoring and management endpoints built into your Spring Boot application. It is a critical topic in senior interviews because it demonstrates that you think about operations and observability, not just feature development.
By default, Actuator exposes endpoints under the /actuator path. The most commonly used endpoints include /actuator/health which reports the application health status and can include details about database connectivity, disk space, and custom health indicators. The /actuator/metrics endpoint exposes application metrics including JVM memory, CPU usage, HTTP request counts and latencies, and custom metrics. The /actuator/info endpoint returns custom application information you define. The /actuator/env endpoint exposes environment properties and configuration values. The /actuator/threaddump endpoint provides a thread dump useful for diagnosing concurrency issues — especially relevant when using Virtual Threads. The /actuator/loggers endpoint allows you to change log levels at runtime without restarting the application.
In production, you typically expose only the health and metrics endpoints publicly and secure all others. Spring Boot Actuator integrates natively with Prometheus and Grafana for metrics visualization when you include the Micrometer Prometheus dependency, making it the foundation of observability in modern Java microservices.
Section 3: Hibernate and JPA Interview Questions
Hibernate is the most widely used ORM (Object-Relational Mapping) framework in the Java ecosystem. JPA is the specification it implements. Full stack Java developers are expected to understand both deeply.
Question 15. What is the difference between JPA and Hibernate?
JPA stands for Java Persistence API (now Jakarta Persistence API). It is a specification — a set of interfaces, annotations, and rules — that defines how Java objects should be mapped to relational database tables and how persistence operations should work. JPA itself contains no implementation code.
Hibernate is the most popular implementation of the JPA specification. It provides the actual code that executes queries, manages sessions, handles caching, and maps objects to database rows. When you use Spring Data JPA in a Spring Boot application, Hibernate is the default JPA provider underneath.
The practical implication: you write code against JPA interfaces and annotations (@Entity, @Table, @Column, EntityManager, JPQL) and Hibernate executes it. This keeps your code portable — theoretically you could swap Hibernate for another JPA provider like EclipseLink without changing your application code, though in practice most teams stay with Hibernate.
Hibernate also provides features beyond the JPA specification, such as its proprietary Criteria API (before JPA added its own), additional caching strategies, special annotations, and Hibernate-specific query capabilities. In interviews, knowing where the JPA standard ends and Hibernate extensions begin demonstrates senior-level understanding.
Question 16. What is the N+1 query problem and how do you solve it?
The N+1 problem is the most commonly asked Hibernate interview question at every experience level, because it is the most common performance issue in Hibernate applications.
The N+1 problem occurs when you load a list of N entities and then access a lazy-loaded association on each entity, triggering an additional database query for each one. For example, if you load 100 Orders and then access order.getCustomer() on each one, Hibernate fires 1 query to load all orders and then 100 additional queries to load each customer — 101 queries total instead of the 1 or 2 needed.
There are four main solutions. Join Fetch uses JPQL with JOIN FETCH to load the parent and associated entities in a single query. Entity Graphs introduced in JPA 2.1 let you define which associations to eagerly load for a specific query without changing the entity mapping. Batch fetching configures Hibernate to load associations in batches rather than one at a time by setting the @BatchSize annotation or the hibernate.default_batch_fetch_size property — this reduces 100 queries to perhaps 4 or 5 batch queries. DTO projections use a JPQL or native query that directly selects only the fields you need into a DTO, avoiding entity loading and association traversal entirely — this is often the cleanest and most performant solution for read operations.
In Spring Boot applications, setting spring.jpa.properties.hibernate.default_batch_fetch_size=25 in application.properties is a simple global mitigation that catches many N+1 situations automatically.
Question 17. What is the difference between FetchType.EAGER and FetchType.LAZY?
This is a follow-up to the N+1 question and also stands alone as a common interview topic.
FetchType.LAZY means the associated entity or collection is not loaded from the database until you explicitly access it in code. Hibernate loads a proxy object initially and fires the actual database query only when you call a method on the association. LAZY is the default for @OneToMany and @ManyToMany associations and is the recommended default for all associations because it prevents unnecessary data loading.
FetchType.EAGER means the associated entity or collection is always loaded immediately along with the owning entity, whether or not you need it. EAGER is the default for @ManyToOne and @OneToOne. While it sounds convenient, EAGER loading is a common source of performance problems because it loads data even when you do not need it, and combining multiple EAGER associations on one entity can produce Cartesian product queries.
The recommended approach in 2026: map all associations as LAZY and use JOIN FETCH, Entity Graphs, or batch fetching to eagerly load specific associations only when a particular use case requires them. This gives you full control over what data is loaded for each operation.
A common interview gotcha: LAZY loading only works within an open Hibernate session. If you access a LAZY association outside the session (for example, after the transaction has closed), you get a LazyInitializationException. This is why Spring Boot's Open Session in View pattern exists — and also why many teams recommend disabling it (spring.jpa.open-in-view=false) and instead loading everything you need within the service layer transaction.
Question 18. What is Hibernate caching and what are the different cache levels?
Hibernate provides two levels of caching to reduce database round-trips and improve application performance.
The first-level cache is the Hibernate Session cache. It is enabled by default and cannot be disabled. Within a single session (transaction), if you load the same entity twice by the same primary key, Hibernate returns the already-loaded instance from the session cache without hitting the database. This is why you often see that repeated findById calls within the same transaction return the same object reference.
The second-level cache is a shared cache that persists across sessions and transactions. It is optional and requires explicit configuration. Popular second-level cache implementations include Ehcache, Caffeine, and Hazelcast. Entities must be annotated with @Cache and @Cacheable to participate in the second-level cache. You also configure cache regions and eviction policies. The second-level cache is very effective for read-heavy, rarely-changing data like reference data, configuration tables, and lookup values.
The query cache is a third optional cache that stores the results of specific JPQL or Criteria queries. It caches the primary keys returned by a query, not the entity data itself (entity data comes from the second-level cache). It is best for queries that are executed frequently with the same parameters and whose results change infrequently.
In modern Spring Boot microservices, Redis is often used as a distributed cache at the application level (using Spring Cache with @Cacheable) rather than relying heavily on Hibernate's second-level cache, because Redis works across multiple application instances.
Question 19. What is the difference between save(), persist(), merge(), and saveOrUpdate() in Hibernate?
This question tests your understanding of Hibernate's entity lifecycle and session management.
persist() is the JPA standard method. It makes a transient entity persistent and associates it with the current session. The INSERT is not necessarily fired immediately — it may be delayed until the session is flushed. persist() throws an exception if you pass a detached entity. It does not return the entity.
save() is a Hibernate-specific method. It is similar to persist() but it always returns the generated identifier immediately and will fire an INSERT if necessary to get the ID (important for identity-based ID generation strategies). save() also accepts detached entities and will attempt to insert them as new rows.
merge() is the JPA standard method for working with detached entities. If you load an entity, close the session (or the transaction ends), modify the entity, and then want to save those changes, you use merge(). Hibernate copies the state of the detached entity onto a persistent entity (loading it from the cache or database if needed) and returns the now-managed persistent entity. The original detached object is NOT the one being managed after the merge call.
saveOrUpdate() is a Hibernate-specific method that performs either a save (INSERT) or update (UPDATE) based on whether the entity's identifier is null or whether the entity already exists in the session. It is the older Hibernate way of doing what merge() does more cleanly.
In 2026 with Spring Data JPA, you typically use the save() method on JpaRepository, which internally calls persist() for new entities and merge() for detached ones, based on whether the entity has a non-null ID.
Section 4: Microservices Interview Questions for Full Stack Java Developers
Microservices architecture is now the standard for enterprise Java applications. Full stack Java developers at mid to senior levels are expected to understand core microservices patterns, communication strategies, and Spring Cloud.
Question 20. What is the difference between monolithic and microservices architecture?
A monolithic architecture packages the entire application — all features, all layers, all business domains — into a single deployable unit. The entire application is built, tested, and deployed together. For small applications and small teams, this is simple and efficient. The problems emerge at scale: a change to any component requires rebuilding and redeploying the entire application, different components cannot be scaled independently, a bug in one module can bring down the entire application, and the codebase becomes increasingly difficult to understand and modify as it grows.
Microservices architecture decomposes the application into small, independently deployable services, each responsible for a specific business capability. Each service has its own database, can be written in any language, can be deployed independently, and can be scaled independently based on its specific demand.
The benefits of microservices: independent deployment reduces risk and enables continuous delivery, independent scaling allows cost-efficient resource allocation, technology diversity lets teams choose the right tool for each service, and fault isolation means one service failure does not cascade to the entire system.
The costs: microservices introduce distributed system complexity including network latency, service discovery, distributed transactions, and eventual consistency. Operational overhead increases significantly — you need container orchestration (Kubernetes), service meshes, distributed tracing, and centralized logging. These are why microservices are appropriate for large teams and complex domains but may be over-engineering for small applications.
Question 21. What is Spring Cloud and what problems does it solve?
Spring Cloud is a suite of tools and frameworks built on top of Spring Boot that addresses the common challenges of building distributed microservices systems. It provides solutions for the most difficult distributed systems problems so teams do not have to build them from scratch.
Service discovery is solved by Spring Cloud Netflix Eureka or Spring Cloud Consul. Services register themselves at startup and discover each other by name rather than by hard-coded IP addresses and ports, which change constantly in dynamic cloud environments.
Client-side load balancing is provided by Spring Cloud LoadBalancer, which distributes requests across multiple instances of a downstream service.
API Gateway is provided by Spring Cloud Gateway — a reactive API gateway that handles routing, authentication, rate limiting, circuit breaking, and request/response transformation at the edge of your microservices system.
Circuit breaking is provided through integration with Resilience4j, which prevents cascading failures when a downstream service is slow or unavailable. When failures reach a threshold, the circuit opens and subsequent calls fail fast, protecting the calling service from being overwhelmed.
Distributed configuration management is provided by Spring Cloud Config Server, which externalizes configuration from application code into a centralized Git repository, allowing configuration changes without redeployment.
Distributed tracing is provided through integration with Micrometer Tracing and systems like Zipkin or Jaeger, allowing you to trace a single user request as it flows through multiple services.
Question 22. What is the difference between synchronous and asynchronous communication in microservices?
This is a critical architecture question that tests whether you understand the trade-offs in distributed system design.
Synchronous communication means the calling service sends a request and waits for a response before continuing. The most common form in Java microservices is REST over HTTP using RestTemplate or the newer RestClient in Spring Boot 3.x. The caller is blocked until the response arrives or a timeout occurs. Synchronous communication is simple to implement, easy to reason about, and familiar. However, it creates tight temporal coupling — if Service B is slow or down, Service A is affected directly. Under high load, slow downstream services can cause thread pool exhaustion in the calling service through a cascading failure pattern.
Asynchronous communication means the calling service sends a message and does not wait for a response — it continues its own processing. The message is placed in a message broker such as Apache Kafka or RabbitMQ, and the receiving service processes it in its own time. The two services are temporally decoupled — Service A does not need Service B to be available at the moment it sends the message.
Asynchronous communication is the better choice when the operation is a notification or event (user registered, order placed, payment received), when the caller does not need an immediate result, when you need guaranteed message delivery across service boundaries, or when you want to handle traffic spikes through buffering.
The practical guideline: use synchronous REST for real-time queries where the caller needs a result immediately. Use asynchronous messaging (Kafka or RabbitMQ) for events, notifications, data propagation between services, and operations where the caller can proceed without an immediate response.
Question 23. What is the Circuit Breaker pattern and how do you implement it in Spring Boot?
The Circuit Breaker pattern prevents a microservice from continuously calling a failing downstream service, which would waste resources and increase latency. It works like an electrical circuit breaker — when too many failures are detected, the circuit opens, and subsequent calls fail immediately without attempting to reach the downstream service.
The circuit breaker has three states. In the Closed state, all calls pass through to the downstream service. Successes and failures are counted. When the failure rate exceeds a configured threshold, the circuit transitions to Open. In the Open state, all calls fail immediately without contacting the downstream service. A fallback method is called instead — returning a cached response, a default value, or an error message. After a configured wait duration, the circuit transitions to Half-Open. In the Half-Open state, a limited number of calls are allowed through. If they succeed, the circuit closes. If they fail, the circuit opens again.
In Spring Boot 3.x, the standard implementation uses Resilience4j via the spring-cloud-starter-circuitbreaker-resilience4j dependency. You configure thresholds in application.properties specifying the failure rate threshold percentage, the number of calls in a sliding window, the wait duration in the open state, and the number of permitted calls in the half-open state. You annotate the method that calls the downstream service with @CircuitBreaker(name = "serviceName", fallbackMethod = "fallbackMethod") and provide a fallback method that accepts the same parameters plus a Throwable.
Question 24. What is Docker and why is it important for Java microservices?
Docker is a containerization platform that packages an application and all its dependencies — code, runtime, libraries, configuration — into a standardized unit called a container. Containers run consistently across any environment that has Docker installed, solving the classic "it works on my machine" problem.
For Java microservices, Docker is essential for several reasons. Each microservice is packaged as its own Docker image and runs in its own container with an isolated environment. This makes deployment consistent across development, testing, staging, and production. Multiple microservices with different Java versions or dependencies can run on the same host without conflicts. Docker images are versioned and immutable, making rollbacks reliable. Container orchestration platforms like Kubernetes manage Docker containers at scale, handling deployment, scaling, health monitoring, and networking.
A basic Dockerfile for a Spring Boot 3.x application uses a multi-stage build: the first stage uses a JDK image to build the application, and the second stage uses a minimal JRE image to run it. Spring Boot 3.x supports layered JARs which improve Docker image caching — dependencies that change rarely are in a separate layer from your application code, so rebuilds and pushes are much faster.
In 2026, Spring Boot also supports building OCI-compatible container images directly using the spring-boot:build-image Maven goal with Cloud Native Buildpacks, eliminating the need to write a Dockerfile manually for many scenarios.
Question 25. What is Kafka and when would you use it in a Java microservices system?
Apache Kafka is a distributed event streaming platform designed for high-throughput, fault-tolerant, real-time data pipelines and event-driven architectures. It stores streams of records (messages) in topics, which are partitioned and replicated across a cluster of brokers.
Core Kafka concepts: a Producer publishes messages to a topic. A Consumer subscribes to a topic and reads messages. Topics are divided into Partitions — each partition is an ordered, immutable log. Consumer Groups allow multiple consumers to share the work of processing a topic's partitions. Kafka retains messages for a configurable period regardless of whether they have been consumed, unlike traditional message queues.
You would use Kafka in Java microservices for event-driven architectures where services emit and react to domain events (OrderPlaced, PaymentProcessed, UserRegistered). It is the right choice for high-throughput event ingestion such as clickstream data, IoT telemetry, or log aggregation. Kafka enables reliable asynchronous communication between microservices with guaranteed message delivery. It supports event sourcing patterns where the Kafka topic serves as the authoritative log of what happened in the system. It is also used for Change Data Capture, propagating database changes to downstream services.
In Spring Boot, the spring-kafka library and Spring Cloud Stream provide clean abstractions for Kafka producers and consumers. You can use @KafkaListener to annotate methods that process incoming messages and KafkaTemplate to send messages.
Section 5: React and Frontend Integration Interview Questions
Full stack Java developers are increasingly expected to work on the frontend as well. React is the dominant frontend library in Java full stack job descriptions in 2026.
Question 26. What is React and how does it integrate with a Spring Boot backend?
React is a JavaScript library developed by Meta for building user interfaces, specifically single-page applications (SPAs). It uses a component-based architecture where the UI is broken into reusable, self-contained components. React maintains a Virtual DOM — an in-memory representation of the UI — and efficiently updates only the parts of the real DOM that have changed, making UI rendering fast.
Integration with Spring Boot follows a clean separation of concerns. The Spring Boot application serves as the backend REST API, exposing JSON endpoints. The React application is a completely separate frontend application that runs in the user's browser. React components make HTTP calls to Spring Boot REST endpoints using the Fetch API or Axios, receive JSON responses, update component state, and React re-renders the affected UI components automatically.
The typical project structure in 2026: the Spring Boot project is a standard Maven or Gradle project. The React project is in a separate directory created with Vite (the modern alternative to Create React App). During development, React runs on a local dev server (typically port 3000) and Spring Boot runs on port 8080. CORS must be configured on the Spring Boot side to allow cross-origin requests from the React dev server. In production, the React app is built into static files and can be served by a CDN, Nginx, or even from within the Spring Boot application as static resources.
Question 27. What is the difference between state and props in React?
State and props are the two core mechanisms for managing data in React components, and understanding the difference is fundamental to building React applications correctly.
Props (short for properties) are data passed into a component from its parent component. Props are read-only from the component's perspective — a component should never modify its own props. Props flow downward through the component tree (parent to child). They are how you make components configurable and reusable. For example, a ProductCard component might receive product name, price, and image as props from a parent ProductList component.
State is data that is managed internally within a component and can change over time. When state changes, React automatically re-renders the component to reflect the new state. State is initialized with the useState hook in functional components. State is private to the component that owns it, though it can be passed down to child components as props. For example, a search input's current value, whether a modal is open or closed, or the list of items fetched from an API are all appropriate uses of state.
The practical mental model: use props for data that comes from outside the component and does not change inside it. Use state for data that the component owns and that changes as a result of user interaction or data fetching. When multiple components need to share state, lift it up to their closest common ancestor and pass it down as props.
Question 28. What are React Hooks and what are the most commonly used ones?
React Hooks, introduced in React 16.8, allow functional components to use React features that previously required class components — such as state, lifecycle methods, and context. In 2026, functional components with hooks are the standard way to write React components. Class components are considered legacy.
useState is the most fundamental hook. It adds local state to a functional component. It returns an array with the current state value and a setter function. Each call to the setter function triggers a re-render.
useEffect is the hook for side effects — operations that happen outside the React rendering pipeline. This includes fetching data from an API, setting up subscriptions, directly manipulating the DOM, and setting up timers. useEffect runs after every render by default, but you control it with a dependency array. An empty dependency array means the effect runs only once after the initial render, similar to componentDidMount in class components.
useContext provides access to React Context, allowing components to consume shared data (like authentication state, theme, or language) without prop drilling through every level of the component tree.
useMemo and useCallback are performance hooks. useMemo memoizes the result of an expensive calculation, recomputing only when its dependencies change. useCallback memoizes a function reference, preventing unnecessary re-renders of child components that receive the function as a prop.
useRef provides a mutable reference that persists across renders without causing re-renders when changed. It is commonly used to access DOM elements directly or to store previous values.
Question 29. What is CORS and how do you configure it in Spring Boot for a React frontend?
CORS stands for Cross-Origin Resource Sharing. It is a browser security mechanism that blocks web pages from making HTTP requests to a different origin (domain, port, or protocol) than the one that served the page. This becomes relevant in full stack development because your React app (running on localhost:3000 or your frontend domain) makes requests to your Spring Boot API (running on localhost:8080 or your API domain) — these are different origins.
When the browser detects a cross-origin request, it sends a preflight OPTIONS request to the server to ask whether the actual request is permitted. If the server responds with the appropriate CORS headers, the browser allows the request to proceed. If not, it blocks it.
In Spring Boot, you configure CORS at three levels. Method level uses @CrossOrigin on specific controller methods or classes to allow cross-origin requests for those specific endpoints — useful for fine-grained control. Global configuration creates a WebMvcConfigurer bean that adds CORS mappings, specifying allowed origins (your React app's URL), allowed HTTP methods, allowed headers, and whether credentials (cookies, authorization headers) are permitted. This is the recommended approach for production. Spring Security level — if you use Spring Security, you must also configure CORS within the security filter chain, because Spring Security's filter chain runs before the MVC CORS configuration and will block preflight requests if not properly configured.
In development, it is common to allow all origins with a wildcard for simplicity. In production, always specify the exact allowed origins rather than using wildcards, especially if your API accepts credentials.
Question 30. How do you handle API calls and async data fetching in React?
This question tests your practical React skills and whether you write production-quality frontend code.
In 2026, the recommended approaches for API calls in React are: the Fetch API (browser-native), Axios (a popular HTTP client library), or data fetching libraries like TanStack Query (formerly React Query).
The basic pattern using useEffect and useState: you declare a state variable to hold the data and a loading state variable. Inside useEffect with an empty dependency array, you make the API call asynchronously (using an async function defined and immediately called inside the effect, because useEffect callbacks cannot be async directly). When the response arrives, you call the setter to update state, which triggers a re-render displaying the data. You also handle errors with a try-catch block and update an error state accordingly. You show a loading indicator while the request is in progress.
The more robust and recommended approach in 2026 is TanStack Query. It handles caching, background refetching, stale data management, loading and error states, pagination, and optimistic updates automatically. Instead of managing multiple useState variables and useEffect hooks, you use the useQuery hook which returns the data, loading state, and error state directly. TanStack Query eliminates most of the boilerplate of manual API state management and prevents common bugs like race conditions and stale closures.
For communicating with your Spring Boot REST API, Axios is preferred over Fetch for its cleaner API, automatic JSON parsing, request and response interceptors (useful for adding JWT tokens to every request), and better error handling.
Frequently Asked Questions
What topics should I study for a Full Stack Java interview in 2026?
Focus on Core Java (OOP, Collections, Streams, Concurrency), Spring Boot (REST APIs, dependency injection, Spring Security, Spring Data JPA), Hibernate (entity lifecycle, N+1 problem, caching), Microservices (Spring Cloud, Docker, Kafka, Circuit Breaker), and React (components, hooks, state management, API integration). Also study system design concepts, SQL and database design, and Git workflows.
How many rounds are typically in a Full Stack Java interview?
Most companies conduct three to five rounds. A typical structure includes an online coding round (DSA and Java-specific problems), a technical round covering Core Java and Spring Boot, a technical round covering system design and microservices, a practical assignment or pair-programming session building a small full stack feature, and an HR round covering culture fit, compensation, and offer discussion.
Are freshers asked the same questions as experienced developers?
Freshers are asked more foundational questions covering Core Java, OOP, basic Spring Boot, and introductory database concepts. Experienced developers (3 plus years) face deeper questions on architecture decisions, performance tuning, design patterns, microservices trade-offs, and system design. The questions in this guide are relevant at all levels — freshers should master Sections 1 through 3, while experienced developers should be comfortable with all sections including Microservices and Kafka.
What salary can a Full Stack Java Developer expect in 2026?
In India, entry-level Full Stack Java developers earn between 4 and 7 LPA. Mid-level developers with 2 to 4 years of experience earn between 8 and 15 LPA. Senior developers with 5 or more years, especially with microservices and cloud experience, earn between 18 and 35 LPA or more. In the US, salaries range from 90,000 to 180,000 USD annually depending on experience and location.
How can I prepare for Full Stack Java interviews quickly?
The most effective approach is structured, project-based learning rather than reading alone. Build real applications that combine Spring Boot REST APIs with a React or Angular frontend, use JPA for database access, and implement basic security. JustAcademy's Full Stack Java Developer Bootcamp provides this structured learning path with live instructor-led sessions, real-world projects, mock interviews, and placement support.
Conclusion
These 30 Full Stack Java interview questions cover the core topics that interviewers test in 2026 — from Java fundamentals and Spring Boot internals to Hibernate performance, microservices architecture, and React integration. Knowing the answers is only part of preparation. The other part is being able to explain your reasoning clearly, relate answers to real project experience, and demonstrate that you think about performance, security, and maintainability — not just making things work.
The most effective way to build that depth quickly is through structured, project-based training with expert mentorship. JustAcademy's Full Stack Java Developer Bootcamp is designed specifically for this — covering every topic in this guide with hands-on coding, real projects, mock interviews, and 100% placement support.
Enroll here.
Related Bootcamps
Full Stack Mobile App Development Bootcamp (Flutter, Node.js, MongoDB, Express)
MEAN Stack Developer Bootcamp
Full Stack QA Automation Bootcamp
JustAcademy | 1201, 12th Floor, Star Plaza, Borivali East, Mumbai 400066 | +91 99871 84296 | www.justacademy.co