Java Full Stack with React Interview Questions for 7 Years Experience
40 questions with answers for candidates with 7 years of experience — 20 medium, 20 hard.
What interviewers expect: 7 years experience
With seven years of experience, roles are often lead or staff-level. Interviews test architecture decisions across the full stack, such as monolith versus microservices, frontend architecture for large apps, API governance, performance at scale, cloud deployment and cost. Expect deep discussions on past projects, technical debt management and how you influence teams without direct authority.
This set is weighted towards JPA and Hibernate (8), Spring Boot (6), REST APIs, Security and Microservices (6), Core Java (5).
Architecture trade-offs Scalability and performance Technical debt strategy Cross-team influence
Solved at this levelStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
Cascade propagates operations from a parent to its children: PERSIST, MERGE, REMOVE, REFRESH, DETACH or ALL. For example, saving an Order with CascadeType.ALL also saves its items. orphanRemoval = true deletes a child row when it is removed from the parent's collection. Use them for true parent-child aggregates like order and items, but never cascade REMOVE on @ManyToOne or shared references like Category, or deleting one product could delete the category.
A new or transient entity is just a Java object not known to the persistence context. A managed entity is attached to the context; changes are tracked and flushed automatically through dirty checking. A detached entity was managed but the context has closed, so changes are not tracked unless you merge it. A removed entity is scheduled for deletion on flush. Understanding these states explains why setters inside a transaction update the database without calling save.
03
What is a closure in JavaScript? Give a practical use.
A closure is a function that remembers variables from the scope where it was created, even after that outer function has returned. For example, function counter() { let n = 0; return () => ++n; } returns a function that keeps its own private n. Closures are used for data privacy, function factories, event handlers, debounce and memoization, and React hooks rely on them. Stale closures in effects are a common bug when dependencies are missing.
04
Tell me about a difficult bug you fixed in a Java project.
Situation: our order API sometimes returned another user's cart. Task: I had to find the root cause quickly. Action: I reproduced it with a load test, found a Spring singleton service storing the current user in an instance field, and moved that state into a method parameter. I added a concurrent test to prevent regressions. Result: the issue disappeared and I shared the learning about stateless beans with the team.
05
A Spring Boot service takes nearly a minute to start. How would you speed it up?
Measure first with the startup Actuator endpoint or ApplicationStartup to see which beans are slow. Common causes are heavy component scanning, eager database or remote calls in @PostConstruct, Hibernate validating a large schema and unneeded auto-configurations. Narrow scan packages, defer work with lazy initialisation or ApplicationReadyEvent, exclude unused starters and use Class Data Sharing. For serverless workloads, consider GraalVM native images or CRaC.
06
Under load, requests fail with a connection timeout from HikariCP. What do you check?
This means all pool connections are busy. Check for long-running queries, transactions held open during remote calls, and connection leaks from code that never closes resources; set leakDetectionThreshold to find them. Compare maximumPoolSize with the database's max connections across all instances, since a bigger pool is not always better. Monitor Hikari metrics through Actuator, fix slow queries and keep @Transactional boundaries short.
07
Users must upload files up to 200 MB. How do you design the upload API?
Avoid streaming large files through the application server. Generate a pre-signed URL for object storage like S3 or Azure Blob so the browser uploads directly, then the client calls the API to confirm and save the metadata. If uploads must go through Spring, raise spring.servlet.multipart.max-file-size, stream the input to storage instead of loading it into memory, validate type and size, and scan files for malware before use.
08
An object put into a HashMap cannot be found later even though it looks equal. What could be wrong?
Most likely a field used in hashCode was changed after insertion, so the object now hashes to a different bucket and get looks in the wrong place. It can also happen when equals is overridden without hashCode. Fix it by using immutable keys, such as records, Strings or IDs, and by basing equals and hashCode on fields that never change. Never mutate an object while it is a key in a hash-based collection.
09
How does column order matter in a composite index?
A composite B-tree index on (customer_id, status, created_at) is sorted by the first column, then the second, and so on. It can serve queries filtering on customer_id, on customer_id and status, or all three, following the leftmost prefix rule, but it cannot efficiently serve a filter on status alone. Put equality columns first and range or sort columns last. A covering index includes all selected columns so the table need not be read.
10
Tell me about a time you delivered a feature under a tight deadline.
Situation: a client demo was moved forward by a week and the reporting module was not ready. Task: deliver the core report screens and APIs in five days. Action: I split the work into must-have and later items with my lead, reused existing query components, and wrote tests for the critical paths only. Result: the demo went well, and the remaining features shipped in the next sprint without bugs.
11
Add the JWT to every API call and handle 401 responses using an Axios interceptor.
Create React App is deprecated and no longer recommended. For a single-page app backed by a Spring Boot API, Vite is the usual choice because of its fast dev server and optimised builds. If you need server-side rendering, SEO or file-based routing, a framework like Next.js or React Router in framework mode is recommended by the React team. Choose based on SEO needs, hosting and the team's experience.
13
How does the Spring Security filter chain process a request?
Every request passes through a DelegatingFilterProxy into a FilterChainProxy, which picks the matching SecurityFilterChain. Filters run in order: CORS, CSRF, authentication filters such as BearerTokenAuthenticationFilter, exception translation and finally the authorization filter. Authentication filters build an Authentication object, validate it through the AuthenticationManager and store it in the SecurityContextHolder. The authorization filter then checks rules such as hasRole("ADMIN") before the controller runs.
14
What is the circuit breaker pattern and how is it implemented in Spring?
A circuit breaker stops calling a failing downstream service so failures do not cascade. It is closed during normal operation, opens when the failure rate crosses a threshold, returns a fallback immediately while open, and moves to half-open after a wait to test recovery. In Spring Boot it is implemented with Resilience4j using @CircuitBreaker(name = "payment", fallbackMethod = "fallback"), usually combined with timeouts, retries with backoff and bulkheads.
15
What changed when moving from Spring Boot 2 to Spring Boot 3?
Spring Boot 3 requires Java 17 or later and is built on Spring Framework 6. The biggest migration task is the switch from javax.* to jakarta.* packages for persistence, validation and servlet APIs. Spring Security 6 removed WebSecurityConfigurerAdapter in favour of SecurityFilterChain beans. Boot 3 also supports GraalVM native images, Micrometer observation and tracing, and from 3.2 the RestClient and virtual thread support.
SELECT e.name AS employee,
e.salary,
m.name AS manager,
m.salary AS manager_salary
FROM employees e
JOIN employees m ON e.manager_id = m.id
WHERE e.salary > m.salary;
-- A self join treats the same table as two roles.
17
Why is constructor injection preferred over field injection?
Constructor injection makes dependencies explicit and lets fields be final, so the object is always fully initialised and immutable. It allows plain unit tests without Spring or reflection, because you can pass mocks to the constructor. A long constructor also signals that a class has too many responsibilities. Field injection with @Autowired hides dependencies and needs a container or reflection in tests. With a single constructor, @Autowired is not even needed.
18
Paging through a large table with OFFSET becomes very slow on later pages. What is a better approach?
With OFFSET 500000, the database still reads and discards half a million rows. Use keyset or seek pagination instead: remember the last seen sort key and query WHERE (created_at, id) < (:lastDate, :lastId) ORDER BY created_at DESC, id DESC LIMIT 20, backed by a matching index. This is fast at any depth and stable when new rows arrive. The trade-off is no direct jump to page N, which suits infinite scroll and APIs.
Measure with Lighthouse and the browser Performance tab, and check Core Web Vitals such as LCP and INP. Then reduce JavaScript with route-based code splitting and removing heavy libraries, compress and lazy-load images using modern formats like WebP or AVIF with proper sizes, enable gzip or Brotli and long-term caching through a CDN, and avoid render-blocking resources. Server-side rendering or pre-rendering, for example with Next.js, can improve first paint further.
21
How do indexes improve performance, and when can they hurt?
An index, usually a B-tree, lets the database find rows without scanning the whole table, which speeds up WHERE, JOIN and ORDER BY on indexed columns. Indexes cost disk space and slow down INSERT, UPDATE and DELETE because each index must also be updated. They help little on low-selectivity columns like a boolean flag. Functions on the column, such as WHERE LOWER(email) = ?, or a leading wildcard in LIKE also prevent normal index use.
22
When should you use parallel streams and when should you avoid them?
Parallel streams split work across the common ForkJoinPool. They help for CPU-heavy, stateless operations on large in-memory data with cheap splitting, such as ArrayList or arrays. Avoid them for small lists, I/O or database calls, operations with shared mutable state, or inside web servers where the common pool is shared by all requests. Always measure with JMH or real load before and after, because overhead often makes them slower.
23
Your Spring Boot service crashes with OutOfMemoryError: Java heap space in production. How do you investigate?
First capture evidence: enable -XX:+HeapDumpOnOutOfMemoryError and check GC logs and container memory limits. Open the heap dump in Eclipse MAT or VisualVM and look at the dominator tree for the largest retained objects. Common causes are unbounded caches, loading full tables into lists, static collections that keep growing and large file reads. Fix the leak, add pagination or streaming, set a sensible -Xmx below the container limit and add memory alerts.
24
Find the second highest salary from a list of employees using streams.
It happens when one query loads N parent rows and then each lazy association fires a separate query, giving N+1 queries. For example, listing 100 orders and calling getCustomer on each. Solve it with JOIN FETCH in JPQL, @EntityGraph on the repository method, batch fetching with hibernate.default_batch_fetch_size, or DTO projections that select only the needed columns. Enable SQL logging or a statistics tool in development to catch it early.
26
Explain the difference between map and flatMap in streams.
map transforms each element into exactly one new element, so a Stream of orders mapped to customer names gives a Stream of String. flatMap transforms each element into a stream and flattens all of them into one stream. For example, orders.stream().flatMap(o -> o.getItems().stream()) gives every item from every order. Optional also has map and flatMap with the same idea.
27
Use CompletableFuture to call two services in parallel and combine the results.
Spring wraps the bean in a proxy. When an external caller invokes a @Transactional method, the proxy starts a transaction, calls the method and commits, or rolls back on a RuntimeException or Error. If a method in the same class calls another @Transactional method through this, the call skips the proxy, so the annotation is ignored. Fix it by moving the method to another bean or restructuring the boundary. The annotation also has no effect on private methods.
29
Describe a time you improved the performance of an application.
Situation: our dashboard API took eight seconds and users complained. Task: I was asked to bring it under one second. Action: using SQL logs and a profiler, I found N+1 queries and a missing index. I rewrote the query with a DTO projection, added a composite index and cached reference data with a short expiry. Result: response time dropped to about 400 milliseconds, and I added the query-count check to our test suite.
30
Your code has frequent NullPointerExceptions from repository lookups. How would you redesign it?
Return Optional from lookup methods so callers must handle the missing case, for example findById(id).orElseThrow(). Validate inputs at the API boundary with Bean Validation, initialise collections to empty lists instead of null and use Objects.requireNonNull in constructors. Java 17 helpful NPE messages show which variable was null, which speeds debugging. Do not use Optional for fields or method parameters; it is meant for return values.
31
Explain the first-level and second-level cache in Hibernate.
The first-level cache is the persistence context itself. It is enabled by default and scoped to a session or transaction, so loading the same entity twice returns the same object without a second query. The second-level cache is optional and shared across sessions, configured with a provider like Ehcache or Infinispan through JCache. It suits read-mostly reference data. In clustered systems many teams prefer an explicit Redis cache at the service layer instead.
32
What causes LazyInitializationException and how do you fix it properly?
It occurs when a lazy association is accessed after the persistence context has closed, for example in a controller or during JSON serialisation outside the transaction. The proper fix is to fetch the data inside the service transaction using JOIN FETCH or @EntityGraph and map it to a DTO. Avoid enabling spring.jpa.open-in-view as a crutch, and avoid switching associations to eager, because both hide performance problems.
33
A downstream service is slow, and your API threads are all stuck waiting. What do you do?
Set connection and read timeouts on every client call, because the defaults can wait far too long. Add a Resilience4j circuit breaker with a fallback and a bulkhead to limit concurrent calls to that service, plus retries only with backoff and only for idempotent requests. Consider caching the downstream data or making the call asynchronous through a queue. Monitor latency percentiles and thread pool usage with Micrometer to confirm the fix.
34
Mentoring: how would you help a junior developer who keeps pushing untested Spring code?
Situation: a junior on my team often broke the build with untested changes. Task: help him improve without demotivating him. Action: I paired with him for a few sessions to write JUnit and Mockito tests for his own features, shared a short checklist and set up a CI rule that blocks merges without passing tests. Result: within a month his pull requests passed review faster, and he later helped another new joiner.
35
Return only a few columns using an interface-based projection.
This is a lost update. Add a @Version column for optimistic locking, send the version to the frontend with the entity, and include it in the update request. If the version no longer matches, Hibernate throws an optimistic lock exception, and the API returns HTTP 409 Conflict so the user can reload and retry. For short, high-contention operations like stock decrement, use a pessimistic lock or an atomic UPDATE with a condition.
37
You need a thread-safe singleton for a configuration loader. How do you implement it?
The simplest safe options are an enum singleton or the holder idiom. With the holder idiom, a private static nested class holds the instance, and the JVM's class loading guarantees lazy, thread-safe initialisation without synchronization. Double-checked locking also works but needs a volatile field. In a Spring application you usually do not write singletons at all, because beans are singleton-scoped by default and the container manages them.
38
A user's JWT is stolen and you need to invalidate it before expiry. How would you design for this?
Pure JWTs cannot be revoked, so keep access tokens short-lived, around 10 to 15 minutes, and use refresh tokens stored server-side and rotated on each use. On logout or theft, revoke the refresh token. For immediate blocking, keep a denylist of token IDs or a per-user token version in Redis and check it in the filter. Send refresh tokens in HttpOnly, Secure, SameSite cookies to reduce theft through XSS.
39
Compare monolithic and microservices architecture.
A monolith is one deployable application. It is simpler to build, test and debug, and suits small teams and early products. Microservices split the system into independently deployable services owned by separate teams, such as orders, payments and inventory, each with its own database. They allow independent scaling and releases but add network latency, distributed data, monitoring and deployment complexity. Many teams start with a modular monolith and split only when needed.
40
Create a protected route in React Router that redirects unauthenticated users to login.
function ProtectedRoute({ roles }) {
const { user } = useAuth();
const location = useLocation();
if (!user) {
return <Navigate to="/login" replace state={{ from: location }} />;
}
if (roles && !roles.includes(user.role)) {
return <Navigate to="/unauthorized" replace />;
}
return <Outlet />;
}
// Routes
<Route element={<ProtectedRoute roles={['ADMIN']} />}>
<Route path="/admin" element={<AdminDashboard />} />
</Route>
// The backend must still enforce authorization on every API.
Frequently asked questions
What is asked in Java Full Stack with React interviews for 7 years of experience?
With seven years of experience, roles are often lead or staff-level. Interviews test architecture decisions across the full stack, such as monolith versus microservices, frontend architecture for large apps, API governance, performance at scale, cloud deployment and cost. Expect deep discussions on past projects, technical debt management and how you influence teams without direct authority.
How many questions should I practise before a Java Full Stack with React interview?
Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.
Which topics matter most for 7 years of experience?
Focus first on Architecture trade-offs, Scalability and performance, Technical debt strategy, Cross-team influence.