Boost DTO pattern with Java mapping frameworks
Introduction
When working with layered applications or at least 3 tier applications, the need of not exposing all your information/properties between layers and tiers became necessary, maybe for not bothering the client with unnecessary data or for security reasons, so you can start building objects that contains just properties you want to expose and this is known by Data Transfer Object (DTO) pattern.
Data Transfer Object Pattern
By definition: The Data Transfer Object Design Pattern is one of the enterprise application architecture patterns that calls for the use of objects that aggregate and encapsulate data for transfer.
It tells you if you have like an Entity called Book with below properties
And you don't want to expose auditing properties outside your services/back-end application, so you create the DTO object of Book entity like below.
And your service methods will be as below to complete the pattern
This is will work fine, but you don't have one entity you have multiple and may you have multiple DTOs for same entity based on your requirements, imagine how boilerplate code you will write to just convert from entities to DTOs object.
Avoid boilerplate code
A lot of frameworks now exist to ease your work with DTO pattern as in Java you will find ModelMapper and MapStruct frameworks to achieve this mission for you and there is more also but these are popular ones
ModelMapper
ModelMapper is mapping between objects using Java reflection and properties name to done its' job, all you need to add maven dependency and inject an instance of ModelMapper object and use if, as below.
Recommended by LinkedIn
<dependency
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.4</version>
</dependency>>
MapStruct
MapStruct framework is taking another approach to achieve DTO pattern, it depends of pre-defined interfaces then define conversion signature and while compile time it generates the boilerplate code in target folder as below.
<dependency
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.3.1.Final</version>
</dependency>>
And in compile time MapStruct will scan your packages and find interfaces annotated with @Mapper then generate its' implementation classes as below
When working with Spring Boot framework MapStruct will annotate implantation with @Component annotation so it can be injected into your services in runtime
ModelMapper V.S MapStruct
While ModelMapper using Java reflection it has a lot of flexibility, and by using generics and few methods you can have a mapping methods for all your system, but also it have a performance impact as it uses Reflection.
In another hand MapStruct is more faster in mapping because it uses a more natural way of mapping as it uses normal java code to map between objects, but it increases jar file size because of implementation classes that it generated, also if made any change in properties name you have to re-compile project to get latest version of Mapper implementation classes.
References