Controller
With the domain, persistence, and service layers done, let's implement the create task feature in the presentation layer.
Create Task Controller
In a Spring Boot app, we build REST APIs using REST API controller classes.
Let's create a dedicated package to store these controller classes,
com.devtiro.task.controller.
Now to create the TaskController class in this package:
/** REST API controller for tasks. */
@RestController
@RequestMapping(path = "/api/v1/tasks")
public class TaskController {
/** The task service from the service layer. */
private final TaskService taskService;
/** The task mapper. */
private final TaskMapper taskMapper;
/**
* Constructs a new TaskController.
*
* @param taskService The TaskService dependency.
* @param taskMapper The TaskMapper dependency.
*/
public TaskController(TaskService taskService, TaskMapper taskMapper) {
this.taskService = taskService;
this.taskMapper = taskMapper;
}
// TODO: Create task endpoint method.
}The @RestController annotation works in a similar way to @Component,
marking the class as a bean. Therefore, the framework injects dependencies
declared in the TaskController class constructor.
Note
Despite being a bean, we almost never declare a controller class as a dependency. Instead, the framework searches out REST API controller classes on startup, exposing the corresponding REST API to clients.
Create Task Endpoint
Now to implement the create task endpoint, which is a special kind of method
on the TaskController class.
/**
* Creates a new task.
*
* @param createTaskRequestDto The request DTO used to create a task.
* @return A representation of the created task and an HTTP 201 CREATED.
*/
@PostMapping
public ResponseEntity<TaskDto> createTask(
@Valid @RequestBody CreateTaskRequestDto createTaskRequestDto) {
// Map the CreateTaskRequestDto to a CreateTaskRequest.
CreateTaskRequest taskToCreate = taskMapper.fromDto(
createTaskRequestDto
);
// Call createTask on the TaskService,
// passing the CreateTaskRequest as an argument.
Task createdTask = taskService.createTask(taskToCreate);
// Map the newly created Task object into a TaskDto.
TaskDto createdTaskDto = taskMapper.toDto(createdTask);
// Return the TaskDto object to the caller with an HTTP 201 CREATED.
return new ResponseEntity<>(createdTaskDto, HttpStatus.CREATED);
}The @PostMapping annotation specifies the endpoint uses the HTTP
POST verb.
The ResponseEntity response type is interesting! Through this object we
can control aspects of the response, like the response code and response body.
In this case we declare the response body as the type TaskDto.
The @RequestBody annotation tells the framework to expect a request body of
the type CreateTaskRequestDto. The @Valid annotation activates the
validation annotation we added to this DTO.
What happens when the request body is invalid? The framework throws an exception. Let's handle this exception.
Summary
- Created the
TaskControllerclass. - Implemented the
createTaskmethod.