I found myself doodling around on the internet till I found this Dynamic proxies in Java article, I always wondered how MapStruct manages to intercept method invocation, this way it can make use of your argument and turns it into a new class of the return type specified by the method signature.
By the end of that short read it makes a lot of sense why the library it's implemented through an interface and not a class, previous versions of mapstruct created a class implementation with abstract processing, newer versions do not create this class implementation instead they perform all the mapping through the mapper interface.
All you need to do is to run the following command:
$ ./gradlew build publishMavenLocal
with that done, all you need to do is add the respective artifact to your favorite build tool, in case you're using gradle an extra step to be done.
repositories {
mavenLocal() // do no forget to add this
mavenCentral()
}
implementation 'com.glaze.mapple:glaze-mapple:1.0'
<dependency>
<groupId>com.glaze.mapple</groupId>
<artifactId>glaze-mapple</artifactId>
<version>1.0</version>
</dependency>
import com.glaze.maple.annotations.Mapper;
import com.glaze.maple.annotations.Mapping;
import com.glaze.maple.core.Mappers;
@Mapper
interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
@Mapping(source = "model", target = "brand")
@Mapping(source = "seatCount", target = "numOfSeats")
CarDto carToCarDto(Car car);
}
class Car {
String model;
int sitCount;
constructors...
getters and setters...
}
class CarDto {
String brand;
int numOfSeats;
// Required no args constructor to perform instantiation and property assignment
public constructor(){}
}
To the usage of this project is pretty straight forward.
@Mapper
annotation does nothing, but it shows intention at first glance- You must define an INSTANCE field then call
Mappers.getMapper
and provide your interface type as an argument, this way a Proxy will get created the one that will intercept methods calls to convert the argument into your expected DTO. - Mapping methods must follow these simple rules:
- Must not return
void
orVoid
- Must not return an interface, prefer a concrete implementation
- Must not return primitives
- Must take only one parameter, the given object you want to map to another
- Must not return
- Classes that are meant to be created dynamically (the return type of your mapping method) must have a no args constructor.
@Mapping
annotation is repeatable you can define as many as needed, it takes 2 string parameterssource
that refers to a declared field in the object you provided as argument andtarget
that refers to a declared field in the object that will get created dynamically of the specified return type.