Spring Framework Case Studies & Practical Application 5 — Questions and Answers
Question 1: A Spring Boot REST API must rate-limit requests per API key without external infrastructure. Which Spring component provides the most straightforward insertion point?
- A @RestControllerAdvice that counts exceptions per key
- A HandlerInterceptor or OncePerRequestFilter that checks a per-key counter before the controller executes (Correct answer)
- A @Transactional service method that queries a rate-limit table on every call
- A Spring AOP @Around advice on all @RestController methods
Correct answer: A HandlerInterceptor or OncePerRequestFilter that checks a per-key counter before the controller executes
A servlet Filter or HandlerInterceptor runs before the controller and can short-circuit the request with a 429 response if the rate limit is exceeded.
Question 2: A Spring application uses RabbitMQ via Spring AMQP. Messages are occasionally lost when the broker restarts. What configuration prevents message loss?
- Increase the prefetch count on the listener container
- Declare queues and exchanges as durable and publish messages as persistent (deliveryMode=2) (Correct answer)
- Use Spring Retry on the listener method
- Set the acknowledgement mode to NONE for maximum throughput
Correct answer: Declare queues and exchanges as durable and publish messages as persistent (deliveryMode=2)
Durable queues survive broker restarts, and persistent messages (deliveryMode=2) are written to disk, together ensuring no messages are lost on broker restart.
Question 3: A company migrates from Spring Boot 2 to Spring Boot 3. Their application uses javax.* imports throughout. What is the required code change?
- Replace all javax.* imports with jakarta.* imports, as Spring Boot 3 is based on Jakarta EE 9+ (Correct answer)
- Add the javax.* compatibility library to the classpath
- No changes needed — Spring Boot 3 automatically bridges javax.* to jakarta.*
- Downgrade Hibernate to version 5 to maintain javax.* compatibility
Correct answer: Replace all javax.* imports with jakarta.* imports, as Spring Boot 3 is based on Jakarta EE 9+
Spring Boot 3 is built on Jakarta EE 9+, which replaced the javax.* namespace with jakarta.*; all imports must be updated manually or via migration tools.
Question 4: A Spring Security application must allow users to log in with Google OAuth2 and also with a username/password. Which configuration approach handles both?
- Configure two separate SecurityFilterChain beans, one for each auth method
- Use a single SecurityFilterChain with both formLogin() and oauth2Login() configured (Correct answer)
- Implement a custom AuthenticationProvider and map Google tokens to form-login sessions
- Create two separate Spring Boot applications and share the session cookie
Correct answer: Use a single SecurityFilterChain with both formLogin() and oauth2Login() configured
Spring Security's fluent DSL allows combining formLogin() and oauth2Login() in a single HttpSecurity configuration, with each flow handled by its dedicated filter chain entry.
Question 5: A Spring Boot application must expose a custom metric — the number of pending orders — to a Prometheus scrape endpoint. What is the recommended approach?
- Write a custom Servlet that returns a /metrics text file
- Register a MeterBinder bean that uses a Gauge to read the pending order count from the repository (Correct answer)
- Manually increment a static counter field in the OrderService
- Use @Scheduled to log the count every minute
Correct answer: Register a MeterBinder bean that uses a Gauge to read the pending order count from the repository
Implementing MeterBinder and registering a Gauge with Micrometer allows the metric to appear on /actuator/prometheus automatically with proper lifecycle management.
Question 6: A service decorated with @Transactional calls an external HTTP API inside the transaction. The HTTP call sometimes hangs for 30 seconds. What is the primary risk?
- The external API response will be rolled back with the transaction
- Database connections are held open for the duration of the HTTP call, exhausting the connection pool under load (Correct answer)
- Spring will automatically time out the transaction after 5 seconds
- The @Transactional proxy will retry the HTTP call on timeout
Correct answer: Database connections are held open for the duration of the HTTP call, exhausting the connection pool under load
A long-running HTTP call inside a transaction holds a database connection for its entire duration, which under concurrent load quickly exhausts the connection pool and blocks all other requests.
Question 7: A Spring Boot app must gracefully shut down — finishing in-flight requests but refusing new ones — when it receives a SIGTERM from Kubernetes. How is this enabled?
- Set server.shutdown=graceful in application.properties and configure a terminationGracePeriodSeconds in the Kubernetes pod spec (Correct answer)
- Add a @PreDestroy method in the main class that calls Thread.sleep(30000)
- Configure spring.lifecycle.timeout-per-shutdown-phase=0 to skip waiting
- Register a JVM shutdown hook that calls System.exit(0)
Correct answer: Set server.shutdown=graceful in application.properties and configure a terminationGracePeriodSeconds in the Kubernetes pod spec
Setting server.shutdown=graceful tells Spring's embedded server to drain active requests before stopping, and Kubernetes' terminationGracePeriodSeconds gives it enough time to do so.
A Spring Boot REST API must rate-limit requests per API key without external infrastructure.
Which Spring component provides the most straightforward insertion point?