Skip to content

Practical Java Full Stack with React Interview Questions

47 questions with answers. Hands-on questions where you write code, a query, a formula or concrete steps.

How to approach these questions

Talk while you work: say your approach first, write the simplest correct version, then improve it and mention edge cases.

Solved — practicalStart 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.
3 questions free Unlock the rest in seconds
01

Show how to read a file safely using try-with-resources.

Save to ▾
Show answer
Path path = Path.of("data.txt"); try (BufferedReader reader = Files.newBufferedReader(path)) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { log.error("Could not read file", e); } // The reader is closed automatically, even if an exception occurs, // because BufferedReader implements AutoCloseable.
02

Write code that runs tasks in parallel using ExecutorService and collects results.

Core JavaMedium
Save to ▾
Show answer
ExecutorService pool = Executors.newFixedThreadPool(4); try { List<Callable<Integer>> tasks = List.of( () -> fetchCount("orders"), () -> fetchCount("users")); List<Future<Integer>> results = pool.invokeAll(tasks); for (Future<Integer> f : results) { System.out.println(f.get()); } } finally { pool.shutdown(); } // On Java 21 you can use Executors.newVirtualThreadPerTaskExecutor() // for I/O-bound tasks.
03

Use CompletableFuture to call two services in parallel and combine the results.

Save to ▾
Show answer
CompletableFuture<User> userF = CompletableFuture.supplyAsync(() -> userClient.get(id), executor); CompletableFuture<List<Order>> ordersF = CompletableFuture.supplyAsync(() -> orderClient.byUser(id), executor); Profile profile = userF .thenCombine(ordersF, Profile::new) .orTimeout(2, TimeUnit.SECONDS) .exceptionally(ex -> Profile.empty()) .join(); // Pass a dedicated executor instead of the common pool for blocking I/O.
04

Create a custom unchecked exception and throw it from a service method.

Save to ▾
Show answer
public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } } public Product getProduct(Long id) { return repository.findById(id) .orElseThrow(() -> new ResourceNotFoundException("Product not found: " + id)); } // A @RestControllerAdvice can map this exception to HTTP 404.
05

Write a record and use pattern matching in a switch expression.

Core JavaMedium
Save to ▾
Show answer
sealed interface Payment permits Card, Upi {} record Card(String number, double amount) implements Payment {} record Upi(String vpa, double amount) implements Payment {} static String describe(Payment p) { return switch (p) { case Card c when c.amount() > 50000 -> "High value card"; case Card c -> "Card ending " + c.number().substring(12); case Upi u -> "UPI to " + u.vpa(); }; } // Sealed types make the switch exhaustive without a default branch (Java 21).
06

Write a Java method to check whether a string is a palindrome, ignoring case and spaces.

Save to ▾
Show answer
static boolean isPalindrome(String s) { String clean = s.replaceAll("\\s+", "").toLowerCase(); int i = 0, j = clean.length() - 1; while (i < j) { if (clean.charAt(i++) != clean.charAt(j--)) { return false; } } return true; } // Two pointers give O(n) time and O(n) space for the cleaned copy. // isPalindrome("Nurses Run") returns true.
07

Using streams, group employees by department and count them.

Save to ▾
Show answer
Map<String, Long> countByDept = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.counting())); // Average salary per department: Map<String, Double> avgSalary = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.averagingDouble(Employee::getSalary))); // Use TreeMap::new as the second argument to get sorted keys.
08

Find the second highest salary from a list of employees using streams.

Save to ▾
Show answer
Optional<Double> second = employees.stream() .map(Employee::getSalary) .distinct() .sorted(Comparator.reverseOrder()) .skip(1) .findFirst(); second.ifPresentOrElse( s -> System.out.println("Second highest: " + s), () -> System.out.println("Not enough distinct salaries")); // distinct() handles ties at the top salary.
09

Sort a list of products by category, then by price descending, then by name.

Save to ▾
Show answer
products.sort( Comparator.comparing(Product::getCategory) .thenComparing(Product::getPrice, Comparator.reverseOrder()) .thenComparing(Product::getName)); // Null-safe variant for an optional field: Comparator<Product> byBrand = Comparator.comparing( Product::getBrand, Comparator.nullsLast(Comparator.naturalOrder()));
10

Find duplicate elements in a list of integers.

Save to ▾
Show answer
List<Integer> nums = List.of(4, 2, 7, 2, 4, 9); Set<Integer> seen = new HashSet<>(); Set<Integer> duplicates = nums.stream() .filter(n -> !seen.add(n)) .collect(Collectors.toSet()); System.out.println(duplicates); // [2, 4] // Stateless alternative using counts: // nums.stream().collect(groupingBy(identity(), counting())) // .entrySet().stream().filter(e -> e.getValue() > 1)
11

Count the frequency of each word in a sentence.

Save to ▾
Show answer
String text = "java is fun and java is fast"; Map<String, Long> freq = Arrays.stream(text.toLowerCase().split("\\s+")) .collect(Collectors.groupingBy( Function.identity(), LinkedHashMap::new, Collectors.counting())); System.out.println(freq); // {java=2, is=2, fun=1, and=1, fast=1}
12

Implement a simple LRU cache in Java.

Save to ▾
Show answer
class LruCache<K, V> extends LinkedHashMap<K, V> { private final int capacity; LruCache(int capacity) { super(16, 0.75f, true); // true = access order this.capacity = capacity; } @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > capacity; } } // Not thread-safe: wrap with Collections.synchronizedMap // or use Caffeine in production.
13

Write global exception handling for a REST API in Spring Boot.

Save to ▾
Show answer
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ProblemDetail handleNotFound(ResourceNotFoundException ex) { return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) public ProblemDetail handleValidation(MethodArgumentNotValidException ex) { ProblemDetail pd = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST); pd.setProperty("errors", ex.getBindingResult().getFieldErrors() .stream().map(e -> e.getField() + ": " + e.getDefaultMessage()).toList()); return pd; } }
14

Bind custom properties from application.yml into a type-safe class.

Save to ▾
Show answer
# application.yml app: payment: timeout-ms: 3000 retry-count: 2 @ConfigurationProperties(prefix = "app.payment") @Validated public record PaymentProperties( @Min(500) int timeoutMs, @Max(5) int retryCount) {} @SpringBootApplication @EnableConfigurationProperties(PaymentProperties.class) public class App { } // Relaxed binding maps timeout-ms to timeoutMs automatically.
15

Write a unit test for a service method using JUnit 5 and Mockito.

Save to ▾
Show answer
@ExtendWith(MockitoExtension.class) class ProductServiceTest { @Mock ProductRepository repo; @InjectMocks ProductService service; @Test void throwsWhenProductMissing() { when(repo.findById(1L)).thenReturn(Optional.empty()); assertThrows(ResourceNotFoundException.class, () -> service.getProduct(1L)); verify(repo).findById(1L); } }
16

Write a controller slice test with @WebMvcTest and MockMvc.

Save to ▾
Show answer
@WebMvcTest(ProductController.class) class ProductControllerTest { @Autowired MockMvc mvc; @MockitoBean ProductService service; // @MockBean before Boot 3.4 @Test void returnsProduct() throws Exception { when(service.getProduct(1L)).thenReturn(new ProductDto(1L, "Pen", 20.0)); mvc.perform(get("/api/products/1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("Pen")); } }
17

Write a production-friendly Dockerfile for a Spring Boot application.

Save to ▾
Show answer
FROM eclipse-temurin:21-jdk AS build WORKDIR /app COPY . . RUN ./mvnw -q -DskipTests package FROM eclipse-temurin:21-jre WORKDIR /app RUN useradd -r appuser USER appuser COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75", "-jar", "app.jar"] # Multi-stage build keeps the image small; runs as non-root.
18

Create a scheduled job that runs every night at 2 AM in Spring Boot.

Save to ▾
Show answer
@SpringBootApplication @EnableScheduling public class App { } @Component public class CleanupJob { private final SessionRepository repo; public CleanupJob(SessionRepository repo) { this.repo = repo; } @Scheduled(cron = "0 0 2 * * *", zone = "Asia/Kolkata") public void removeExpiredSessions() { repo.deleteByExpiresAtBefore(Instant.now()); } } // With several instances, use ShedLock so only one runs the job.
19

Write a JPA entity for a Product with an auto-generated ID and basic constraints.

Save to ▾
Show answer
@Entity @Table(name = "products") public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 120) private String name; @Column(nullable = false, precision = 10, scale = 2) private BigDecimal price; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "category_id") private Category category; protected Product() {} // required by JPA }
20

Write a repository query that loads orders with their items in one query.

Save to ▾
Show answer
public interface OrderRepository extends JpaRepository<Order, Long> { @Query(""" select distinct o from Order o join fetch o.items i where o.customer.id = :customerId """) List<Order> findWithItems(@Param("customerId") Long customerId); @EntityGraph(attributePaths = {"items", "customer"}) Optional<Order> findWithGraphById(Long id); }
21

Implement pagination and sorting for a product list API.

Save to ▾
Show answer
@GetMapping("/api/products") public Page<ProductDto> list( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size, @RequestParam(defaultValue = "price") String sort) { Pageable pageable = PageRequest.of(page, Math.min(size, 100), Sort.by(sort).ascending()); return repository.findByActiveTrue(pageable).map(ProductDto::from); } // Repository: Page<Product> findByActiveTrue(Pageable pageable);
22

Build a dynamic search with optional filters using JPA Specifications.

Save to ▾
Show answer
public class ProductSpecs { public static Specification<Product> hasCategory(String c) { return (root, q, cb) -> c == null ? null : cb.equal(root.get("category").get("name"), c); } public static Specification<Product> priceBetween(BigDecimal min, BigDecimal max) { return (root, q, cb) -> (min == null || max == null) ? null : cb.between(root.get("price"), min, max); } } // Repository extends JpaSpecificationExecutor<Product> repo.findAll(Specification.where(hasCategory(cat)) .and(priceBetween(min, max)), pageable);
23

Return only a few columns using an interface-based projection.

Save to ▾
Show answer
public interface ProductSummary { Long getId(); String getName(); BigDecimal getPrice(); } public interface ProductRepository extends JpaRepository<Product, Long> { List<ProductSummary> findByCategoryName(String category); @Query("select new com.shop.dto.PriceDto(p.name, p.price) from Product p where p.price < :max") List<PriceDto> cheaperThan(@Param("max") BigDecimal max); } // Projections select fewer columns and avoid loading full entities.
24

Write a Flyway migration to add a column and index to an existing table.

Save to ▾
Show answer
-- src/main/resources/db/migration/V3__add_sku_to_products.sql ALTER TABLE products ADD COLUMN sku VARCHAR(40); UPDATE products SET sku = CONCAT('SKU-', id) WHERE sku IS NULL; ALTER TABLE products ALTER COLUMN sku SET NOT NULL; CREATE UNIQUE INDEX ux_products_sku ON products (sku); # application.yml # spring.jpa.hibernate.ddl-auto: validate # Flyway runs pending V-scripts in order at startup.
25

Write a basic CRUD REST controller in Spring Boot.

Save to ▾
Show answer
@RestController @RequestMapping("/api/products") public class ProductController { private final ProductService service; public ProductController(ProductService service) { this.service = service; } @GetMapping("/{id}") public ProductDto get(@PathVariable Long id) { return service.get(id); } @PostMapping public ResponseEntity<ProductDto> create(@Valid @RequestBody ProductRequest req) { ProductDto saved = service.create(req); return ResponseEntity.created(URI.create("/api/products/" + saved.id())).body(saved); } @DeleteMapping("/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) public void delete(@PathVariable Long id) { service.delete(id); } }
26

Add request validation to a registration API.

Save to ▾
Show answer
public record RegisterRequest( @NotBlank @Size(max = 60) String name, @NotBlank @Email String email, @Pattern(regexp = "^[6-9]\\d{9}$", message = "Invalid mobile") String mobile, @Size(min = 8, max = 64) String password) {} @PostMapping("/api/auth/register") public ResponseEntity<Void> register(@Valid @RequestBody RegisterRequest req) { authService.register(req); return ResponseEntity.status(HttpStatus.CREATED).build(); } // Needs spring-boot-starter-validation. Errors raise // MethodArgumentNotValidException, mapped to 400 by the advice.
27

Configure Spring Security 6 for a stateless JWT-secured REST API.

Save to ▾
Show answer
@Configuration @EnableMethodSecurity public class SecurityConfig { @Bean SecurityFilterChain api(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .cors(Customizer.withDefaults()) .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/**", "/actuator/health").permitAll() .requestMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN") .anyRequest().authenticated()) .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults())); return http.build(); } }
28

How do you store user passwords securely in Spring Boot? Show the code.

Save to ▾
Show answer
@Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } public void register(RegisterRequest req) { User user = new User(req.email(), encoder.encode(req.password())); userRepository.save(user); } public boolean checkLogin(String raw, User user) { return encoder.matches(raw, user.getPasswordHash()); } // BCrypt adds a random salt and is deliberately slow. // Never store plain text or use MD5/SHA-1 for passwords.
29

Call another microservice from Spring Boot using RestClient with a timeout.

Save to ▾
Show answer
@Bean RestClient inventoryClient(RestClient.Builder builder) { var factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(2000); factory.setReadTimeout(3000); return builder.baseUrl("http://inventory-service") .requestFactory(factory).build(); } public StockDto getStock(String sku) { return inventoryClient.get() .uri("/api/stock/{sku}", sku) .retrieve() .body(StockDto.class); } // RestClient (Boot 3.2+) replaces RestTemplate for new code; // use WebClient for reactive stacks.
30

Write a query to find the second highest salary from an employees table.

Save to ▾
Show answer
-- Using a subquery SELECT MAX(salary) AS second_highest FROM employees WHERE salary < (SELECT MAX(salary) FROM employees); -- Using DISTINCT with OFFSET SELECT DISTINCT salary FROM employees ORDER BY salary DESC LIMIT 1 OFFSET 1; -- The first query returns NULL when there is no second salary.
31

Find the top 3 highest-paid employees in each department.

Save to ▾
Show answer
SELECT department_id, name, salary FROM ( SELECT department_id, name, salary, DENSE_RANK() OVER ( PARTITION BY department_id ORDER BY salary DESC) AS rnk FROM employees ) ranked WHERE rnk <= 3 ORDER BY department_id, rnk; -- DENSE_RANK keeps ties; use ROW_NUMBER for exactly 3 rows.
32

Write a query to find duplicate email addresses in a users table and delete the extra rows.

Save to ▾
Show answer
-- Find duplicates SELECT email, COUNT(*) AS cnt FROM users GROUP BY email HAVING COUNT(*) > 1; -- Keep the lowest id, delete the rest (MySQL / PostgreSQL) DELETE FROM users u USING users k WHERE u.email = k.email AND u.id > k.id; -- PostgreSQL syntax -- Then add: ALTER TABLE users ADD CONSTRAINT ux_email UNIQUE (email);
33

Find employees who earn more than their managers.

Save to ▾
Show answer
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.
34

Write a query that shows daily sales with a running total for the month.

Save to ▾
Show answer
SELECT order_date, SUM(amount) AS daily_sales, SUM(SUM(amount)) OVER ( ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS running_total FROM orders WHERE order_date >= DATE '2026-10-01' AND order_date < DATE '2026-11-01' GROUP BY order_date ORDER BY order_date;
35

How do you use EXPLAIN to analyse a slow query?

Save to ▾
Show answer
EXPLAIN ANALYZE SELECT o.id, o.total FROM orders o WHERE o.customer_id = 42 AND o.status = 'PAID' ORDER BY o.created_at DESC LIMIT 20; -- Look for: Seq Scan / type=ALL (full scan), large 'rows' estimates, -- 'Using filesort' or a Sort node, and actual time per step. -- Fix with: CREATE INDEX ix_orders_cust_status_date -- ON orders (customer_id, status, created_at DESC);
36

Fetch a list of products from an API and show loading and error states.

Save to ▾
Show answer
function ProductList() { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const controller = new AbortController(); fetch('/api/products', { signal: controller.signal }) .then(res => { if (!res.ok) throw new Error('HTTP ' + res.status); return res.json(); }) .then(data => setProducts(data.content)) .catch(err => { if (err.name !== 'AbortError') setError(err.message); }) .finally(() => setLoading(false)); return () => controller.abort(); }, []); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return <ul>{products.map(p => <li key={p.id}>{p.name}</li>)}</ul>; }
37

Write a reusable useFetch custom hook.

Save to ▾
Show answer
export function useFetch(url) { const [state, setState] = useState({ data: null, loading: true, error: null }); useEffect(() => { let ignore = false; setState(s => ({ ...s, loading: true })); fetch(url) .then(r => r.ok ? r.json() : Promise.reject(new Error(r.statusText))) .then(data => { if (!ignore) setState({ data, loading: false, error: null }); }) .catch(error => { if (!ignore) setState({ data: null, loading: false, error }); }); return () => { ignore = true; }; }, [url]); return state; } // Usage: const { data, loading, error } = useFetch(`/api/orders/${id}`);
38

Build a login form with basic validation in React.

Save to ▾
Show answer
function LoginForm({ onLogin }) { const [form, setForm] = useState({ email: '', password: '' }); const [errors, setErrors] = useState({}); const handleChange = e => setForm({ ...form, [e.target.name]: e.target.value }); const handleSubmit = e => { e.preventDefault(); const errs = {}; if (!/^\S+@\S+\.\S+$/.test(form.email)) errs.email = 'Enter a valid email'; if (form.password.length < 8) errs.password = 'Minimum 8 characters'; setErrors(errs); if (Object.keys(errs).length === 0) onLogin(form); }; return ( <form onSubmit={handleSubmit}> <input name="email" value={form.email} onChange={handleChange} /> {errors.email && <span>{errors.email}</span>} <input name="password" type="password" value={form.password} onChange={handleChange} /> {errors.password && <span>{errors.password}</span>} <button type="submit">Login</button> </form> ); }
39

Create a protected route in React Router that redirects unauthenticated users to login.

Save to ▾
Show answer
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.
40

Add the JWT to every API call and handle 401 responses using an Axios interceptor.

Save to ▾
Show answer
const api = axios.create({ baseURL: import.meta.env.VITE_API_URL }); api.interceptors.request.use(config => { const token = getAccessToken(); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }); api.interceptors.response.use( res => res, async error => { const original = error.config; if (error.response?.status === 401 && !original._retry) { original._retry = true; await refreshToken(); // calls /api/auth/refresh with cookie return api(original); } return Promise.reject(error); });
41

Implement a cart counter using useReducer.

Save to ▾
Show answer
function cartReducer(state, action) { switch (action.type) { case 'add': return { count: state.count + 1 }; case 'remove': return { count: Math.max(0, state.count - 1) }; case 'reset': return { count: 0 }; default: throw new Error('Unknown action ' + action.type); } } function Cart() { const [state, dispatch] = useReducer(cartReducer, { count: 0 }); return ( <div> <span>Items: {state.count}</span> <button onClick={() => dispatch({ type: 'add' })}>+</button> <button onClick={() => dispatch({ type: 'remove' })}>-</button> </div> ); }
42

Write a debounce function in JavaScript.

Save to ▾
Show answer
function debounce(fn, delay = 300) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } const search = debounce(term => { fetch(`/api/products?q=${encodeURIComponent(term)}`); }, 400); input.addEventListener('input', e => search(e.target.value)); // Only the last call within 400 ms actually runs.
43

Call three APIs in parallel and handle failure of any one gracefully.

Save to ▾
Show answer
async function loadDashboard() { const results = await Promise.allSettled([ fetch('/api/orders').then(r => r.json()), fetch('/api/stats').then(r => r.json()), fetch('/api/alerts').then(r => r.json()), ]); const [orders, stats, alerts] = results.map(r => r.status === 'fulfilled' ? r.value : null); return { orders, stats, alerts }; } // Promise.all rejects on the first failure; // allSettled lets the page show partial data.
44

Use map, filter and reduce to get the total value of in-stock products.

Save to ▾
Show answer
const products = [ { name: 'Pen', price: 20, qty: 10, inStock: true }, { name: 'Bag', price: 900, qty: 0, inStock: false }, { name: 'Book', price: 250, qty: 4, inStock: true }, ]; const total = products .filter(p => p.inStock) .map(p => p.price * p.qty) .reduce((sum, value) => sum + value, 0); console.log(total); // 1200
45

How do you deep clone an object in JavaScript?

Save to ▾
Show answer
const original = { user: { name: 'Asha' }, tags: ['a'], joined: new Date() }; // Modern built-in (handles Date, Map, Set, cycles): const copy = structuredClone(original); // Spread is only a shallow copy: const shallow = { ...original }; shallow.user.name = 'Ravi'; // also changes original.user.name // JSON.parse(JSON.stringify(obj)) loses Dates, functions, // undefined and fails on circular references.
46

Centre a div horizontally and vertically using CSS.

Save to ▾
Show answer
.container { display: flex; justify-content: center; /* horizontal */ align-items: center; /* vertical */ min-height: 100vh; } /* Grid alternative */ .container { display: grid; place-items: center; min-height: 100vh; }
47

Write CSS for a product grid that shows 1 column on mobile, 2 on tablet and 4 on desktop.

Save to ▾
Show answer
.grid { display: grid; grid-template-columns: 1fr; gap: 16px; padding: 0 16px; } @media (min-width: 640px) { .grid { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 1024px) { .grid { grid-template-columns: repeat(4, 1fr); } } /* Mobile-first: base styles for small screens, then widen. */

Frequently asked questions

Why are practical questions important?

Most technical rounds include at least one live task. Practising the exact typing and reasoning makes you calm and fast in the real round.

How should I answer them?

Talk while you work: say your approach first, write the simplest correct version, then improve it and mention edge cases.