Home > Java > Automated beans conversion

Automated beans conversion

It’s been more than a month since my last post: summer was hot and sunny but I’m back to work now. This week’s post will be about beans conversion.

In the past, I’ve ranted about DTO and their indiscriminate use in applications. I do concede, however, that DTO are sometimes necessary: this article points out some contexts where they might be. Moreover, DTO even may not be enough, bringing the need for View Objects. Such is the case for layered architectures in big projects.

In all cases, conversion between each type of object quickly become not only a chore for the developer but also a nest of potential bugs. The stupidest the code to write, the more likely the developer will not think about it and it will be very hard to find the bug if there’s one. I’ve experienced it before: I remember not so fondly a time when I had to debug a code I did not develop only to discover 2 hours later the bug was caused because a setter had no effect. Using a tool in such a case (such as Eclipse or NetBeans getter/setter generation) is a good protection against those nasty potential bugs.

For bean to bean conversion, there are some tools available:

Personally, I use Dozer, a “Java Bean to Java Bean mapper” that is more powerful than a simple copy properties and highly configurable.

Setup

Note: I will use Dozer in the simplest way possible (no Spring). Using other configurations will of course require different steps.

Setting up Dozer only requires a few actions:

  • add the Maven dependency to Dozer
    
      net.sf.dozer
      dozer
      5.2.2
    
  • add the XML Beans runtime dependency. I think this is a mistake of the project since it’s a needed dependency for Dozer
    
      org.apache.xmlbeans
      xmlbeans
      2.4.0
      runtime
    
  • create a XML file called dozerBeanMapping.xml at the root of the classpath
    
    
    

Done!

Simplest mapping

In the simplest of cases, you’ll probably don’t have much to do since your different types of object will have the same attributes, both name and type.

The first thing to do is to get an instance of the mapper itself. It is a best practice to make it a singleton: in fact, Dozer offers a singleton factory.

Thereafter, Dozer offers two simple alternatives: either it creates a bean for you (line 3 below) or it fills up an already created bean (line 7).

Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();

PersonTransferObject personTo = mapper.map(personDo, PersonTransferObject.class);

/* PersonTransferObject personTo = new PersonTransferObject();

mapper.map(personDo, personTo) */;

The latter is very interesting when you are using frameworks (such as Struts) that will create beans and pass it in methods you’ll have to override.

Mapping configuration

Until now, Dozer hasn’t proved more useful than Commons Beanutils or Spring BeanUtils. Its power lies in its configuration abilities. Let’s take a simple example: imagine you need to pass a Transfer Object to a Struts form (I know Struts is outdated but I have to use it in my day-to-day work so please bear with me – the example is usable in other contexts anyway). Most of the time, Struts forms will have strict String attributes so they can be shown to the HTML page and parsed from the HTML page. In substance, a Struts form is a View Object.

Essentially, the problem at hand is how to map a bean with typed attributes to a bean with String attributes. Mapping numeric values is automated in Dozer, the real pain lies in the Date attributes. Since Dozer is configurable, just add the following in the mapping file:


  dd/MM/yyyy

You can argue that, in some cases, you’ll want other formats: no problem, since it’s only the default. Date format can be overriden at class mapping level or even at field mapping level!

Advanced configuration

In internationalized applications, the previous configuration wouldn’t be enough, since each user should have the date displayed in its own locale. Still, Dozer anticipated this use case and provide you with the mean to choose a mapping.

Until yet, we relied on default mapping: provide two objects and since they have the same attributes, Dozer does its job. In order to choose between mappings, you’ll have to explicitly declare them in your mapping file:


  ch.frankel.blog.dozer.domain.PersonTransferObject
  ch.frankel.blog.dozer.form.PersonForm

This configuration won’t change the previous example, it just declares the mapping explicitly. Now, in order to have contextual mapping, just add the map-id attribute of the mapping. And since I explained before you can change date parsing/formatting at mapping level, let’s do it too:


  ch.frankel.blog.dozer.domain.PersonTransferObject
  ch.frankel.blog.dozer.form.PersonForm


  ch.frankel.blog.dozer.domain.PersonTransferObject
  ch.frankel.blog.dozer.form.PersonForm

In order to use the desired mapping, just pass the appropriate identifier in the mapping call:

mapper.map(personTo, personForm, "en");

Beyond configuration

If all else fails, you always have the possibility to create your own converter. For example, imagine you want to hide the database primary key of your objects in the presentation layer, relying on a business key in it. Since the primary key is lost, and all you have is the business key, you have to retrieve the PK from the database tier when transforming your Transfer Object back to an Entity.

Custom converters can be configured for the entire application, for specific mapping or even for particular fields; meaning in the latter case you can have the cake and eat it too. For the case presented above, just use this in the configuration file:


  ch.frankel.blog.dozer.domain.PersonTransferObject
  ch.frankel.blog.dozer.entity.PersonDataObject
  
    businessId
    id
  

The custom converter is just a implementation of ch.frankel.blog.dozer.converter.PersonPrimaryKeyConverter which has a single method, public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class destinationClass, Class sourceClass).

Additional features

This small article hasn’t brushed the surface of what Dozer can do:

  • collections mapping
  • enumerations mapping
  • field exclusion
  • custom bean factories
  • custom getter/setter methods
  • reference mapping
  • event framework
  • expression language
  • etc.

Conclusion

Regarding the size and use of applications I’m designing, I tend to follow the KISS principle and in most cases, I let my entities be flow through the layers. In other contexts, I’m in favor of using automated conversion tools to reduce both bug probability and developer weariness. Dozer is the best tool I’ve used so far: it’s configurable enough to be used easily in simple use-cases and powerful enough to be used in complex ones. Moreover, its documentation is of excellent quality.

Sources for this article are available here in Eclipse/Maven format.

To go further:

email
Send to Kindle
Categories: Java Tags: ,
  1. sme
    June 3rd, 2011 at 11:37 | #1
  2. January 15th, 2013 at 15:07 | #2

    Hi Nicolas,

    Dozer is the reference point, but write the xml file take much time and it is error-prone, the performance are low, annotation are supported only for simple mapping…

    I suggest you take a look at JMapper Framework:
    http://code.google.com/p/jmapper-framework/

    With JMapper you can decide to map with annotations or in xml format, execute creation or enrichment of the target instance, explicit conversions, 1 to N and N to 1 relationships and much more.

    This framework is based on javassist library, the mapping is created at runtime, with 0 memory consuption and with performance of static code.

    try it :)

  3. January 15th, 2013 at 15:27 | #3

    Hi Alessandro,

    XML vs annotations is an ongoing debate, but just to be quick, XML is orthogonal: this means in some (most) use-cases, mapping is contextual and I want to switch from one mapper to another depending on the context. It’s very easy to do that with XML, not so much with annotations.

    The good thing is the bytecode modification, so I’ll take a look. Thanks for your advice!

  4. November 30th, 2013 at 18:38 | #4

    Hi Nicolas,

    Just came across this post and would be interested in what you think on an alternative mapping solution I’m working on called MapStruct.

    This is a compile-time code generator which creates bean mappings that are fast (using plain method invocations) and type-safe (an error will be raised at build time if attributes can’t be mapped) and don’t have any runtime dependencies.

    Mappers are defined in MapStruct by interfaces like this:

    @Mapper
    public interface PersonMapper {

    @Mappings({
    @Mapping(source=”businessId”, target=”id”),
    @Mapping(source=”birthday”, dateFormat=”dd/MM/yyyy”)
    })
    PersonTransferObject personEntityToDto(PersonDataObject entity);
    }

    MapStruct will generate an implementation of this interface which you then can use to perform the mappings in your code (also retrievable via CDI and Spring).

    There is also support for collection mappings, bi-directional mappings, mapping several sources into one target and much more. If you’re interested you can find more information in the reference documentation (http://mapstruct.org/documentation). Any feedback you might have is highly welcome :)

    –Gunnar

  5. December 2nd, 2013 at 11:23 | #5

    Hello Gunnar,

    From a quick overview, it looks very good. It has many properties I look for: decoupled from classes themselves thus allowing reuse, pretty self-explanatory and no boilerplate code. I have to play with it at some point. Thanks for the pointer!

  1. No trackbacks yet.