We have developed a solution that uses a BeanMapper
that allows to abstract from the underlying implementation. As mentioned in the general bean mapping guide, we started with Dozer a Java Bean to Java Bean mapper that recursively copies data from one object to another. Now we recommend using Orika. This guide will show an introduction to Orika and Dozer bean-mapper.
To get access to the BeanMapper
we have to use either of the below dependency in our POM:
<dependency>
<groupId>com.devonfw.java.modules</groupId>
<artifactId>devon4j-beanmapping-orika</artifactId>
<version>2020.12.002</version>
</dependency>
<dependency>
<groupId>com.devonfw.java.modules</groupId>
<artifactId>devon4j-beanmapping-dozer</artifactId>
<version>2020.12.002</version>
</dependency>
The BeanMapper
implementation is based on an existing open-source bean-mapping framework.
In case of Dozer the mapping is configured src/main/resources/config/app/common/dozer-mapping.xml
.
See the my-thai-star dozer-mapping.xml as an example.
Important is that you configure all your custom datatypes as <copy-by-reference>
tags and have the mapping from PersistenceEntity
(ApplicationPersistenceEntity
) to AbstractEto
configured properly:
<mapping type="one-way">
<class-a>com.devonfw.module.basic.common.api.entity.PersistenceEntity</class-a>
<class-b>com.devonfw.module.basic.common.api.to.AbstractEto</class-b>
<field custom-converter="com.devonfw.module.beanmapping.common.impl.dozer.IdentityConverter">
<a>this</a>
<b is-accessible="true">persistentEntity</b>
</field>
</mapping>
Orika with devonfw is configured by default and sets some custom mappings for GenericEntity.java to GenericEntityDto.java. To specify and customize the mappings you can create the class BeansOrikaConfig.java that extends the class BaseOrikaConfig.java from the devon4j.orika package. To register a basic mapping, register a ClassMap for the mapperFactory with your custom mapping, by extending the method configureCustomMapping
in the class BaseOrikaConfig
. See the example below and follow the basic Orika mapping configuration guide and the Orika advanced mapping guide.
Register Mappings:
@Override
protected MapperFactory configureCustomMapping(MapperFactory mapperFactory) {
super.configureCustomMapping(mapperFactory);
mapperFactory.classMap(UserEntity.class, UserEto.class)
.field("email", "email")
.field("username", "name")
.byDefault()
.register();
return mapperFactory;
}
The call to super.configureCustomMapping
allows to keep and extend the existing mapping (to support proper JPA @Version
attribute when converting from ApplicationPersistenceEntity
to AbstractEto
like with Dozer above).
Then we can get the BeanMapper
via dependency-injection what we typically already provide by an abstract base class (e.g. AbstractUc
). Now we can solve our problem very easy:
...
UserEntity resultEntity = ...;
...
return getBeanMapper().map(resultEntity, UserEto.class);