11 · REST APIs / LESSON 48 OF 102
Controllers and DTOs
Define the HTTP boundary without exposing database internals.
Before this lesson: Configuration and profiles
Understand the topic
@RestController serializes returned objects to the response body. @RequestMapping defines a shared path. @RequestBody converts JSON to a Java object. Records make small DTOs; entities remain separate.
This first endpoint normalizes input without storing it, so it returns 200 rather than falsely claiming durable creation. The persistence section adds a create endpoint with 201 and Location.
EXAMPLE · JAVA
src/main/java/com/example/tasks/TaskController.java
package com.example.tasks;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/tasks")
public class TaskController {
private final TitleService titles;
public TaskController(TitleService titles) { this.titles = titles; }
public record CreateTask(String title) {}
public record Preview(String title, boolean done) {}
@PostMapping("/preview")
public Preview preview(@RequestBody CreateTask input) {
return new Preview(titles.normalize(input.title()), false);
}
}What to expect
POST /api/tasks/preview with {"title":" Java "} returns {"title":"Java","done":false}.
YOUR TURN
Put it into practice
- 01Call with curl or an API client.
- 02Add a GET ping endpoint.
- 03Explain DTO versus entity.
Pass a quiz or complete a lab to check today’s streak. Each lesson counts once per day, including when you review it later.
UNDER THE HOOD
Build the mental model
A controller translates HTTP into an application operation and translates its result back into a public representation.
- 01DTOs constrain what clients can send and receive. Binding a request directly into an entity can allow unintended field changes.
- 02Constructor injection keeps the controller thin. Put business operations in a service so non-HTTP callers can reuse them.
- 03A create operation should return the saved ID. Build Location from that ID rather than guessing the next sequence value.
A mistake worth avoiding
Do not put mutable lists of tasks on a singleton controller for production storage.
DEBUGGING ROOM
Something broke. Where do you look?
The response accidentally exposes a passwordHash field.
Before revealing the diagnosis, write down your first investigation step.
CHECK YOUR UNDERSTANDING
Why use a response DTO?
BUILD IT YOURSELF
Implement create and read contracts
- 1.Add POST /api/tasks backed by TaskService when persistence is available.
- 2.Return a record with id, title, and done.
- 3.Return 201 with a Location header pointing at GET-one.
Acceptance checklist
Lab completion is your self-report. Knowledge checks do not certify project quality.
RETRIEVE IT FROM MEMORY
What should remain outside an HTTP controller?
Revisit this lesson in three days after a successful check or lab.
Ready for the next step?
Trace JSON → DTO → service → response.
Reading is separate from passing a knowledge check or completing a lab.