29.11.20163 min

XSolve (Boldare now)

Converter pattern in Java 8

Converter pattern in Java 8

Our Java team has recently prepared a hands-on workshop on functional programming in Java 8. The participants solved our coding tasks, trying out the Java 8’s features in separation, and now it’s time we show off how we employ the full power of Java 8 in our real-life projects.

 

This is a common problem of converting pairs of similar objects one to another (in our case – domain classes to DTOs, which are then sent to frontend as JSON objects) and the other way round. In this case, what we need is a one-shot conversion, just once in the object’s lifetime. What we do not want is coupling between the two kinds of objects: DTO classes shouldn’t “know” about domain classes and the other way round.

As changes in the source object do not have to affect the destination object, the classic solution would be to create a single “Mapper” (or “Converter”) class for each pair. There are also tools which are able to map fields of similar classes, based on field names. But how about “producing” whole collections of our source object? How to produce collections of destination objects, without too much boilerplate code?

What addresses our needs, is Java 8 and its three core features:

  • default method implementation in interfaces
  • streams
  • lambdas (here in the form of a method reference)

Default method implementation is what saves us from boilerplate code, creating collections of objects. Streams and lambdas build a beautiful code transforming our collections. Let’s have a look at the final class hierarchy and the code itself:

 

public interface GenericConverter {

   E createFrom(D dto);

   D createFrom(E entity);

   E updateEntity(E entity, D dto);

   default List createFromEntities(final Collection entities) {
       return entities.stream()
               .map(this::createFrom)
               .collect(Collectors.toList());
   }

   default List createFromDtos(final Collection dtos) {
       return dtos.stream()
               .map(this::createFrom)
               .collect(Collectors.toList());
   }
}

Having implemented the default method that converts a collection of data transfer objects (D) into entities (E), as well as another one that does the opposite, we don’t need to implement this in concrete implementations of the converter any more. Creating a converter for a single DTO/domain class is as simple as that:

@Component
public class AccountConverterImpl implements AccountConverter {

   @Override
   public Account createFrom(final AccountDto dto) {
       return updateEntity(new Account(), dto);
   }

   @Override
   public AccountDto createFrom(final Account entity) {
       AccountDto accountDto = new AccountDto();
       accountDto.setAccountType(entity.getAccountType());
       accountDto.setActive(entity.getActive());
       accountDto.setEmail(entity.getUserId());
       ClassUtils.setIfNotNull(       
              entity::getPassword, accountDto::setPassword);
       return accountDto;
   }

   @Override
   public Account updateEntity(final Account entity, 
        final AccountDto dto) {
       entity.setUserId(dto.getEmail());
       entity.setActive(dto.getActive());
       ClassUtils.setIfNotNull(
              dto::getAccountType, entity::setAccountType);       
       return entity;
   }
}

Another feature you can see there is our ClassUtils.setIfNotNull method, which only calls the setter if the getter yields a non-null value:

public class ClassUtils {

   protected ClassUtils() { }

   public static  void setIfNotNull(final Supplier getter, final Consumer setter) {

       T t = getter.get();

       if (null != t) {
           setter.accept(t);
       }
   }
}

So there we have a complete Converter structure using all the Java 8 goodness. Adding a new Converter for another entity-DTO pair (like User, Address, etc.) needs just creating a new UserConverterImpl class, implementing its own UserConverter, which in turn should  implement GenericConverter. This way the new class will be capable of converting collections of objects out-of-the box. This is possible thanks to the default method implementations in GenericConverter interface, which is a very handy Java 8’s feature.

Let us know your thoughts on this solution!

Anna-Software Developer at xSolve

<p>Loading...</p>

Powiązane artykuły

Dziel się wiedzą ze 160 tysiącami naszych czytelników

Zostań autorem Readme

Hitachi Energy

Product Development Manager

senior

15 000 - 20 000 PLN

Umowa o pracę

Krakow

Praca zdalna 100%

Ważna do 26.02.2022

Bardzo dobrze
AgileSoftware Development Life Cycle Leadership skills

Simple SA

Java Developer (Mid/Senior)

medium

7 000 - 15 000 PLN

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 26.02.2022

Dobrze
JavaSpringSpring Boot

Asseco Poland S.A.

Administrator / Starszy Administrator Systemów IT

medium

Brak widełek

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 26.02.2022

Dobrze
PostgreSQLBash

Nokia

5G Automation Engineer, IODT

medium

Brak widełek

Umowa o pracę

Wrocław

Praca zdalna 100%

Ważna do 13.03.2022

Divante

Senior Vue.js Developer

senior

15 300 - 23 500 PLN

Kontrakt B2BUmowa o pracę

Wrocław

Praca zdalna 100%

Ważna do 13.03.2022

Dobrze
JavaScriptTypeScriptVue.js

T-Mobile Polska S. A.

Frontend Developer

medium

Brak widełek

Kontrakt B2B

Warsaw

Ważna do 26.02.2022

Bardzo dobrze
ReactReduxNode.js

Commerzbank - Centrum Technologii Cyfrowych w Polsce

Business Expert for Risk Applications

medium

Znamy widełki

Umowa o pracę

Łódź

Ważna do 26.02.2022

Dobrze
SQLMS Office
Początkująco
SAS / R / Python

Commerzbank - Centrum Technologii Cyfrowych w Polsce

Business Expert with German for Risk Analytics

medium

Znamy widełki

Umowa o pracę

Łódź

Ważna do 26.02.2022

Dobrze
MS Office
Początkująco
SQL / VBA / PythonQlik Sense / Qlik View / Arcadia

Hitachi Energy

Quality Assurance Engineer

medium

8 000 - 14 000 PLN

Umowa o pracę

Krakow

Ważna do 26.02.2022

Dobrze
automation testing .NET CoreSelenium
Początkująco
MS SQL

Więcej od XSolve (Boldare now)

Zobacz wszystkie artykuły od XSolve (Boldare now)