Create Task Mapper

Now that we have our Task entity and TaskDto classes, we need a way to convert between them. This is where mappers come in - they handle the transformation of objects between our domain (entities) and presentation (DTOs) layers.

Why Use Mappers?

While we could perform these conversions directly in our service or controller classes, using dedicated mapper classes gives us several benefits:

  1. Separation of concerns - mapping logic is isolated and reusable
  2. Consistent transformation rules across the application
  3. Easier to maintain and modify mapping logic
  4. Cleaner service and controller code

Mapping Approaches

There are two main approaches to implementing mappers:

Manual Implementation

Pros:

  • Complete control over mapping logic
  • No additional dependencies
  • Easier to debug
  • Better understanding of the transformation process

Cons:

  • More boilerplate code
  • Higher maintenance burden
  • Potential for human error

Automated Mapping (e.g., MapStruct)

Pros:

  • Less boilerplate code
  • Reduced chance of mapping errors
  • Automatic handling of null checks
  • Performance optimized

Cons:

  • Additional project dependency
  • Learning curve for the mapping library
  • Less control over the mapping process
  • Can be harder to debug generated code

For this project, we'll implement our mappers manually to keep things simple and transparent.

Creating the Mapper Interface

First, let's create a new package com.devtiro.tasks.mappers to hold our mapper classes. In this package, create a new interface called TaskMapper:

package com.devtiro.tasks.mappers; import com.devtiro.tasks.domain.dto.TaskDto; import com.devtiro.tasks.domain.entities.Task; public interface TaskMapper { Task fromDto(TaskDto dto); TaskDto toDto(Task task); }

This interface defines two methods:

  • fromDto - converts a TaskDto to a Task entity
  • toDto - converts a Task entity to a TaskDto

Implementing the Mapper

Now let's create an implementation class. Create a new package com.devtiro.tasks.mappers.impl and add a new class TaskMapperImpl:

package com.devtiro.tasks.mappers.impl; import com.devtiro.tasks.domain.dto.TaskDto; import com.devtiro.tasks.domain.entities.Task; import com.devtiro.tasks.mappers.TaskMapper; import org.springframework.stereotype.Component; @Component public class TaskMapperImpl implements TaskMapper { @Override public Task fromDto(TaskDto dto) { return new Task( dto.id(), dto.title(), dto.description(), dto.dueDate(), dto.priority(), dto.status(), null, null, null ); } @Override public TaskDto toDto(Task task) { return new TaskDto( task.getId(), task.getTitle(), task.getDescription(), task.getDueDate(), task.getPriority(), task.getStatus() ); } }

Let's break down the implementation:

  1. We annotate the class with @Component so Spring will manage it as a bean
  2. In fromDto:
    • We map all fields from the DTO to create a new Task entity
    • Created/updated timestamps and taskList are set to null as they're handled by the service layer
  3. In toDto:
    • We map only the fields needed for the DTO
    • Internal fields like timestamps and relationships are excluded

Notice how the mapper keeps the transformation logic isolated and makes it easy to modify how we convert between our domain and presentation objects?

Summary

  • Created a mapper interface to define the contract for Task/TaskDto conversion
  • Implemented a manual mapper with clear, explicit transformation logic
  • Annotated the implementation as a Spring component for dependency injection
  • Kept mapping logic separate from business logic
© 2026 Devtiro Ltd. All rights reserved