Capstone: A Complete REST API
Everything comes together: a CRUD REST API with a controller → service → repository → JPA flow, validation , error handling , security , and tests — the anatomy of a production Spring Boot service.
Learn Capstone: A Complete REST API in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
This capstone draws on the whole track: dependency injection , security , testing , and containerization . Skim any you're unsure of first.
💡 Analogy: A REST API runs like a restaurant. The waiter (controller) takes your order, checks it makes sense ( validation ), and never cooks anything themselves. They pass it to the chef (service), who knows the recipes and the rules ( business logic ). The chef fetches ingredients from the pantry (repository / JPA / database). The doorman (security) checks who may enter and which tables they can use. If something's wrong — no such dish — the manager ( @RestControllerAdvice ) sends a polite, consistent message back (a 404), not chaos. And the health inspectors ( tests ) visit regularly to make sure every station does its job.
Clear roles, clean hand-offs, and consistent responses — that's a well-built API.
Each layer has one job: the controller handles HTTP, the service holds logic, the repository handles data. The plain-Java model below shows the flow — including a missing resource becoming a 404.
Reject bad input with a 400 before it reaches your logic, and turn missing resources into a 404 . Spring uses @Valid + Bean Validation and @RestControllerAdvice ; the demo hand-rolls the same idea.
Now the real thing: a @RestController delegating to a @Service backed by a Spring Data JpaRepository , with @Valid for validation and @RestControllerAdvice for centralized error handling.
A stateless SecurityFilterChain guards the API, and @WebMvcTest + MockMvc verify the controller — including the 404 path — with the service mocked.
Answer: the service layer — controllers stay thin (HTTP) and repositories stay focused on data access.
Answer: 400 Bad Request — triggered by @Valid failing Bean Validation constraints.
Answer: throw a not-found exception and map it with @ExceptionHandler in a @RestControllerAdvice .
🎯 YOUR TURN — A Service Lookup with 404
Complete get(id) so a missing id throws (the controller would map it to 404).
🧩 MINI-CHALLENGE — A Full Create Flow
Validate the request, then persist and return 201 with an id, or return 400 with the errors.
You've assembled a complete REST API: a controller → service → repository → JPA flow with validation, centralized error handling, stateless security, and a layered test strategy — and you know how to monitor, cache, and containerize it. That's the full anatomy of a production Spring Boot service.
Congratulations on finishing the Spring Boot & Enterprise Java track. Keep building — the best way to cement these ideas is to ship a small API of your own.
Practice quiz
In the classic layered architecture, which layer talks to the database?
- Controller
- Service
- Repository
- DTO
Answer: Repository. The repository (data access) layer is responsible for persistence; the service orchestrates and the controller handles HTTP.
What is the controller layer responsible for?
- Persisting entities
- Handling HTTP requests/responses and delegating to the service
- Defining the database schema
- Hashing passwords
Answer: Handling HTTP requests/responses and delegating to the service. Controllers map HTTP to method calls, validate input, and delegate business logic to the service layer.
Where does business logic belong in this design?
- The controller
- The repository
- The service layer
- The entity getters
Answer: The service layer. The service layer holds business rules and coordinates repositories, keeping controllers thin and repositories focused on data.
Which annotation triggers Bean Validation on a request body?
- @Valid
- @Cacheable
- @Transactional
- @Bean
Answer: @Valid. Annotating a @RequestBody parameter with @Valid runs Bean Validation constraints like @NotBlank and @Size.
What is a good way to return a 404 when a resource is missing?
- Return null
- Log and continue
- Return an empty 200
- Throw an exception handled by @ExceptionHandler/@ControllerAdvice mapping to 404
Answer: Throw an exception handled by @ExceptionHandler/@ControllerAdvice mapping to 404. Throw a not-found exception and map it to HTTP 404 via @ExceptionHandler or @ControllerAdvice for consistent error handling.
Which HTTP status best fits a successful resource creation?
- 200 OK
- 201 Created
- 204 No Content
- 400 Bad Request
Answer: 201 Created. 201 Created signals a new resource was created, typically with a Location header pointing to it.
@ControllerAdvice is used to...
- create beans
- configure caching
- centralize cross-cutting exception handling for controllers
- define entities
Answer: centralize cross-cutting exception handling for controllers. @ControllerAdvice (or @RestControllerAdvice) centralizes exception handling and other advice across controllers.
To slice-test only the web layer of this API you would use...
- @DataJpaTest
- @WebMvcTest with MockMvc and @MockBean
- @SpringBootTest only
- no annotation
Answer: @WebMvcTest with MockMvc and @MockBean. @WebMvcTest loads just the controller; MockMvc drives requests and @MockBean stubs the service.
In a secured REST API, a stateless token is typically sent as...
- a query string password
- a hidden form field
- an X-Powered-By header
- Authorization: Bearer <jwt>
Answer: Authorization: Bearer <jwt>. Stateless APIs carry a JWT in the Authorization header as a Bearer token, validated by a security filter.
Why map JPA entities to DTOs at the API boundary?
- To slow responses
- To decouple the API contract from the persistence model and avoid leaking internals
- Because entities can't be serialized
- To skip validation
Answer: To decouple the API contract from the persistence model and avoid leaking internals. DTOs keep the external contract stable and prevent exposing or over-binding internal entity fields.