Implement Create Task

Now that we can list tasks, let's implement the ability to create new ones within a task list. We'll need to add methods to both our service and controller layers to handle this functionality.

Updating the Service Interface

First, let's add the create method to our TaskService interface:

public interface TaskService { List<Task> listTasks(UUID taskListId); Task createTask(UUID taskListId, Task task); // Add this method }

Implementing the Service Method

Now let's implement the create functionality in TaskServiceImpl:

@Service public class TaskServiceImpl implements TaskService { private final TaskListRepository taskListRepository; private final TaskRepository taskRepository; public TaskServiceImpl(TaskListRepository taskListRepository, TaskRepository taskRepository) { this.taskListRepository = taskListRepository; this.taskRepository = taskRepository; } @Override public Task createTask(UUID taskListId, Task task) { if (null != task.getId()) { throw new IllegalArgumentException("Task already has ID!"); } if (null == task.getTitle() || task.getTitle().isBlank()) { throw new IllegalArgumentException("Task must have a title"); } TaskPriority priority = Optional.ofNullable(task.getPriority()) .orElse(TaskPriority.MEDIUM); TaskList taskList = taskListRepository .findById(taskListId) .orElseThrow(() -> new IllegalArgumentException("Invalid Task List ID provided") ); LocalDateTime now = LocalDateTime.now(); return taskRepository.save(new Task( null, task.getTitle(), task.getDescription(), task.getDueDate(), priority, TaskStatus.OPEN, now, now, taskList )); } }

Let's examine the key aspects of this implementation:

  1. Dependencies:

    • We need both TaskRepository and TaskListRepository
    • TaskListRepository to verify the parent task list exists
    • TaskRepository to save the new task
  2. Input Validation:

    • Checks that the task doesn't already have an ID
    • Ensures the title is not null or blank
    • Verifies the parent task list exists
  3. Default Values:

    • Sets a default MEDIUM priority if none provided
    • Sets status to OPEN for new tasks
    • Sets created and updated timestamps to current time
  4. Task List Association:

    • Fetches the parent task list
    • Associates the new task with its parent list

Updating the Controller

Now let's add the create endpoint to our TasksController:

@RestController @RequestMapping(path = "/task-lists/{task_list_id}/tasks") public class TasksController { private final TaskService taskService; private final TaskMapper taskMapper; public TasksController(TaskService taskService, TaskMapper taskMapper) { this.taskService = taskService; this.taskMapper = taskMapper; } @GetMapping public List<TaskDto> listTasks(@PathVariable("task_list_id") UUID taskListId) { return taskService.listTasks(taskListId) .stream() .map(taskMapper::toDto) .toList(); } @PostMapping public TaskDto createTask( @PathVariable("task_list_id") UUID taskListId, @RequestBody TaskDto taskDto) { Task createdTask = taskService.createTask( taskListId, taskMapper.fromDto(taskDto) ); return taskMapper.toDto(createdTask); } }

Let's break down the key components:

  1. URL Mapping:

    • @PostMapping maps this to HTTP POST requests
    • Path includes the parent task list ID
  2. Parameters:

    • @PathVariable extracts the task list ID from the URL
    • @RequestBody deserializes the request body into a TaskDto
  3. Implementation:

    • Converts the incoming DTO to a Task entity
    • Calls the service to create the task
    • Converts the result back to a DTO for the response

How It Works Together

When a POST request arrives at /task-lists/{task_list_id}/tasks:

  1. Spring extracts the task list ID from the URL path
  2. The request body is deserialized into a TaskDto
  3. The controller converts the DTO to a Task entity
  4. The service:
    • Validates the input
    • Verifies the task list exists
    • Sets default values and timestamps
    • Saves the task
  5. The controller converts the saved entity back to a DTO
  6. Spring serializes the DTO to JSON for the response

For example, a POST request to /task-lists/123e4567-e89b-12d3-a456-426614174000/tasks might look like:

{ "title": "New Task", "description": "This is a new task", "dueDate": "2024-11-01T09:00:00", "priority": "HIGH" }

And receive a response like:

{ "id": "789e4567-e89b-12d3-a456-426614174001", "title": "New Task", "description": "This is a new task", "dueDate": "2024-11-01T09:00:00", "priority": "HIGH", "status": "OPEN" }

Summary

  • Added create functionality to the TaskService
  • Implemented input validation in the service layer
  • Added the POST endpoint to create tasks
© 2026 Devtiro Ltd. All rights reserved