Building REST Controllers
Expose your beans over HTTP with @RestController , map endpoints with @GetMapping / @PostMapping , return automatic JSON , and control status codes with ResponseEntity .
Learn Building REST Controllers 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.
You should understand beans and constructor injection , and have the spring-boot-starter-web dependency from project setup . Records make tidy JSON payloads.
💡 Analogy: A @RestController is the waiter : it takes the customer's order (the HTTP request), passes it to the kitchen (the @Service ), and brings back the plated dish (the JSON response ). The waiter doesn't cook — it just translates between the dining room (HTTP) and the kitchen (business logic). ResponseEntity is the waiter choosing exactly how to present the plate (status code, headers).
Thin controllers, like good waiters, stay out of the cooking and focus on clean hand-offs.
@RestController = @Controller + @ResponseBody , so a method's return value becomes the response body. @GetMapping("/hello") wires a GET endpoint.
Return any object (a record is ideal) and Spring serialises it to JSON using Jackson — no manual string-building. A class-level @RequestMapping adds a shared base path.
When you need more than a 200 OK body — a 201 Created, custom headers, or an empty body — wrap the result in ResponseEntity to set the status explicitly.
A controller should only handle web concerns and delegate business logic to an injected @Service . This separation keeps logic reusable and testable without the web layer.
Answer: @Controller and @ResponseBody — so return values become the response body.
Answer: an HttpMessageConverter (Jackson by default, auto-configured by Boot) serialises it.
Answer: ResponseEntity.status(HttpStatus.CREATED).body(obj) .
You can now build REST endpoints with @RestController, map them with @GetMapping/@PostMapping, return objects that Spring serialises to JSON, and shape responses with ResponseEntity — all while keeping controllers thin.
Next up: Request Mapping & Parameters — binding path variables, query params and request bodies.
Practice quiz
What does @RestController combine?
- @Controller and @ResponseBody
- @Service and @Bean
- @Component and @Scope
- @Configuration and @Bean
Answer: @Controller and @ResponseBody. @RestController is @Controller + @ResponseBody, so every handler's return value is serialised directly into the response body.
Which annotation maps HTTP GET requests to a method?
- @PostMapping
- @DeleteMapping
- @GetMapping
- @PutMapping
Answer: @GetMapping. @GetMapping is a shortcut for @RequestMapping(method = GET), handling HTTP GET requests.
How does a @RestController turn a returned object into JSON?
- Manually with string concatenation
- Via an HttpMessageConverter (Jackson) configured by Boot
- It cannot return JSON
- Only via a template engine
Answer: Via an HttpMessageConverter (Jackson) configured by Boot. Spring uses HttpMessageConverters — Jackson by default — to serialise returned objects to JSON automatically.
What is ResponseEntity used for?
- Defining a database table
- Returning a body together with an explicit status code and headers
- Injecting a bean
- Reading properties
Answer: Returning a body together with an explicit status code and headers. ResponseEntity lets a handler control the HTTP status, headers and body, not just the body.
Which annotation maps HTTP POST requests?
- @GetMapping
- @PatchMapping
- @PostMapping
- @HeadMapping
Answer: @PostMapping. @PostMapping is the shortcut for handling HTTP POST requests, typically used to create resources.
Where should a controller delegate its business logic?
- Into the controller method itself
- To a @Service bean injected into the controller
- Into the database directly
- To application.properties
Answer: To a @Service bean injected into the controller. Controllers should stay thin and delegate to an injected @Service, keeping web concerns separate from business logic.
By default, a @RestController method returning a String sends...
- a view name to render
- the String itself as the response body
- nothing
- an error
Answer: the String itself as the response body. Because of @ResponseBody, the returned String becomes the response body rather than a view name to resolve.
What does @RequestMapping("/api") at class level do?
- Disables the controller
- Prefixes every handler path in the class with /api
- Sets the port
- Creates a bean
Answer: Prefixes every handler path in the class with /api. A class-level @RequestMapping defines a base path that is prepended to each method's mapping.
What status code does ResponseEntity.ok(body) produce?
- 404 Not Found
- 500 Internal Server Error
- 201 Created
- 200 OK
Answer: 200 OK. ResponseEntity.ok(...) is a convenience for an HTTP 200 OK response carrying the given body.
To return 201 Created with a body, you can use...
- ResponseEntity.status(HttpStatus.CREATED).body(obj)
- return null;
- @GetMapping
- System.exit(1)
Answer: ResponseEntity.status(HttpStatus.CREATED).body(obj). ResponseEntity.status(HttpStatus.CREATED).body(obj) sets a 201 status alongside the response body.