There are several Java Frameworks available that does Object Mapping – automatic creation of DTO (Data Transfer Object) in Spring Boot.
Reasons we need it
Spring (Boot) Framework saves a lot of time of developers by hiding complexity and placing smart defaults with convention over configuration. This comes with the price of a “magic” happening behind the scene that may create obsticles for you.
- REST Endpoints – The very basic example is exposing the objects created by the Database layer directly to the REST. I’ll write more on how to REST in the future.
- Using Frameworks like Google Web Toolkit https://www.gwtproject.org/, that take a portion of the Java SDK and compile it to JavaScript. Whenever there is something beyond it – it will now work out of the box.
- Wrapping and Isolating out of external dependencies. It is general practice your business logic to not have dependencies on concrete implementations. This will make the code harder to change.
Object Mapping Options
Here are a few popular ones:
- ModelMapper: ModelMapper is a popular library for mapping between Java objects, including automatic DTO creation.
- Dozer: Dozer is another popular library for mapping between Java objects, including automatic DTO creation.
- Orika: Orika is a Java library that provides automatic DTO creation and mapping between Java objects.
- MapStruct: MapStruct is a Java library that provides automatic DTO creation and mapping between Java objects. It’s designed to be fast, efficient, and easy to use.
- Dozer-Mapstruct: Dozer-Mapstruct is a library that combines the features of Dozer and MapStruct to provide automatic DTO creation and mapping between Java objects.
- Spring Framework’s BeanUtils. Spring Framework provides a set of utility classes, including BeanUtils, that can be used to automatically create DTOs from Java objects.
Here’s an example of how you might use MapStruct to automatically create a DTO from a Java object:
MapStruct Example
MapStruct like Lombok – very much like many Spring Framework tools work with
- processing your code,
- finds annotated parts and
- based on it – adds things on your classpath (at compile time).
The last step above is crucial for the tool to work. It does it with annotation post processor that needs to be activated by your IDE or build tool.
First, you need to add the following dependency in your pom.xml file if you’re using Maven:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.3.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.3.Final</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>21</source>
<target>21</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<!-- This is needed when using Lombok 1.18.16 and above -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
<!-- Mapstruct should follow the lombok path(s) -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Or in your build.gradle file if you’re using Gradle:
dependencies {
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
}
Here is the most basic code.
// Entity class
public class User {
private Long id;
private String name;
// getters and setters
}
// DTO class
public class UserDTO {
private Long id;
private String name;
// getters and setters
}
// Using MapStruct to create a DTO from an entity
public class UserService {
@Autowired
private UserMapper userMapper;
public UserDTO getUserDTO(User user) {
return userMapper.map(user, UserDTO.class);
}
}
You need to configure the Mapper in your application.
// UserMapperConfig.java
@MapperConfig
public class UserMapperConfig {
}
In The example above, the UserService class uses a mapping library to automatically create a UserDTO object from a User entity. This can save a lot of boilerplate code and make your application more maintainable.
