Blog4Java

A personal and Java blog, likely only for me

Orika time!

| 1 Comment

I love good software, and Orika is a really interesting project. In this post I’m going to talk about this Java bean mapping framework that I’ve used recently and I highly recommend.

Orika (formerly hosted at google code) claims to be a simpler, lighter and faster Java bean mapping. And it really is.

It allows you to convert objects by copying its attributes from one to another. It performs this by using Java introspection, instead of XML configuration or something like that. It uses code generation to create the mappers, and it has an interesting strategy for its core classes that allows you to optimize the performance.

It is completely configurable, for instance, the java code generator by default is Javassist, but you can use EclipseJdt or even use another provider by implementing the appropriate interface.

Finally, it’s a very well documented project, with clear explanations and useful code.

I really like it.

If you want to try it, just add the next dependency to your maven project:

Or download the library along with three required libraries:

  • javassist (v 3.12.0+)
  • slf4j (v 1.5.6+)
  • paranamer (v 2.0+)

Main concepts

There are two core classes, the first one is MapperFactory, the class to configure the mappings and to obtain the second core class: MapperFacade, that actually provides the service of a Java bean mapping.

MapperFactory

By using a fluent API, you can construct a MapperFactory via its main implementation, DefaultMapperFactory and its static class helpers intended for building the MapperFactory.

Then you can obtain a ClassMapBuilder from the MapperFactory in order to declare the mapping configuration in a fluent-style, that is: mapping fields (bi-directional by default, or in one direction if you’d rather), excluding fields, specifying constructors and customizing mappings of Lists, Sets, nested fields and so on.

There is a default mapping that maps fields with matching names between two classes, and you can also register the mapping in the MapperFactory (the ClassMapBuilder is built with the very MapperFactory as atribute). Both operations have the appropriate methods to be called.

Let’s see an example:

We have two classes: PersonDTO and Person, and we want to convert one object for the former class to an object of the latter one, so let’s configure the MapperFactory:

The ClassMapBuilder provides interesting mappings for excluding fields, mapping fields in one direction only (as I mentioned above, mapping is by default bi-directional) and so on. See the Declarative Mapping Configuration and Advanced Mapping Configurations for more options.

MapperFacade and BoundMapperFacade

The MapperFacade performs the actual mapping work, for doing so, you have to obtain the MapperFacade from the MapperFactory and then use its map methods. There are two general options, map(objectA, B.class), which will create a new instance of B.class and map the property values of objectA onto it, or map(objectA, objectB), which copies properties from objectA onto objectB, being both of them not null.

Let’s see an example:

The BoundMapperFacade is intended to be used with a pair of types to map and no further customization needed. It provides improved performance over use of the standard MapperFacade and it has the same usage plus a mapReverse method for mapping in the reverse direction.

See below an example:

If you’re primarily concerned with the mapping of a particular type to another, and your object graph has no cycles, use BoundMapperFacade because it has better performance, since you avoid the overhead of looking up an appropriate mapping strategy for the fields of the objects to be mapped, that happens when you call the map method.

Performance

The most expensive operations are instantiation and initialization of the MapperFactory, and the MapperFacade which is obtained from it.

Both of them are thread-safe objects, thus singletons or static access for them are a very recommended approach.

For instance, you can consider an static acces to the MapperFactory:

And then use this class for registering class maps and access to the MapperFacade in a customize way:

In this case I’m using two new classes: Customer and CustomerDTO.

Finally, just use this helper classes:

How it works and Customization

The best way to understand how Orika works is to read the FAQ, but the source code is very clear and easy to follow, just in case you want to take a deeper look to the details.

“Orika uses reflection to investigate the metadata of the objects to be mapped and then generates byte-code at runtime which is used to map those classes […]”

“Orika mapping is configured via Java code at runtime, via a fluent-style ClassMapBuilder API. An instance is obtained from a MapperFactory which is then used to describe the mapping from one type to another. Finally, the specified ClassMap is registered with the MapperFactory for later use in generating a byte-code mapper.”

To configure Orika, the author recommends to extend the ConfigurableMapper class, and I will use this approach for using Orika with Spring (see below)

If you want to configure the code generation, compilation and so on, see how to do this using the MapperFactory in the next topic.

MapperFactory Configuration

The core class MapperFactory is instantiated as you’ve seen above, by building the provided implementation: DefaultMapperFactory. It uses a set of Strategy and factory objects for resolving constructors, for compiling code (actually, they belong to its inner static class MapperFactoryBuilder that is extended by its other inner static class that you use to instantiate the MapperFactory: the Builder), for resolving properties, and specially for building class maps.

So you can customize all of them after calling Builder() and before the build() method:

Custom Mappers

A Mapper<A, B> copies the properties from one object onto another and it’s used internally by Orika (MapperFacade, MapperGenerator and MapperFactory use it, but it isn’t really interesting for this post, actually)

If you want to take control of how properties of one object instance are copied to another object instance (not null), just extends the abstract class CustomMapper<A,B>.

Then, you can register your custom mapper in the MapperFactory via its method registerMapper(Mapper<A, B> mapper).

It’s intended to be used when the mapping behavior configured via the ClassMapBuilder API doesn’t suit your purposes, but only to copy properties, that is, the destination object already exists. If you want to control instantiation, use a CustomConverter or ObjectFactory which both return an instance. See below.

If you need to map nested members of the given object, you can doing so by using the current MapperFacade that it’s accessible via a protected mapperFacade variable.

I’ve used converters in a Spring applications as components that can be scanned and used to configure the MapperFactory by extending ConfigurableMapper as I mentioned above and I’ll show below.

Object Factories

An ObjectFactory<D> instantiates objects. You can implement this interface and register your implementation in the MapperFactory via their method registerObjectFactory (there are a couple of them)

I’ve never used this option.

Custom Converters

A Converter<S, D> combines both ObjectFactory and Mapper together, returning a new instance of the destination type with all properties copied from the source instance.

When you want to take complete control over the instantiation and mapping, just extend CustomConverter<S, D> to create the new instance and to provide it the properties from the source object.

Then, you can register your custom converter in the MapperFactory by obtaining its ConverterFactory via the getConverterFactory() method and then using one of its registerConverter() methods.

I’ve found this option useful when you want to create some hard conversion between classes that has the same meaning in your code but are not really related in terms of Java. Well, it’s a conversion, let’s say, from a date represented in a String and a date that has to be a Calendar. You have to use some formatter for doing so.

It’s also very easy to configure converters as Spring components if you need so.

Using Orika with Spring

Since the Orika core classes MapperFactory and the MapperFacade obtained from it are very expensive to instantiate and initialize, but at the same time are thread-safe, they should be shared as singletons. That is, they are good candidates for being Spring beans with singleton scope.

Let’s start with using spring-framework in a maven project,just add the next dependency to the pom.xml file:

The Spring application

Let’s create a couple of beans to obtain a Person and a PersonDTO, let’s call them service and repository respectively:

And their implementations, the one for the service will use the repository interface, and the one for the repository will be a simple in-memory implementation.

Note that the service will need to convert from the DTO to the domain object, so let’s inject a mapper.

As you can see, I used setter injection (via autowiring) to provide a MapperFactory in order to obtain from it a MapperFacade. I’m using the suggestion of having the MapperFactory as singleton, that it’s easy to achieve with Spring.

Since MapperFactory has a particular way to be instantiated, the best option is to create a factory for exposing it, a FactoryBean:

This approach has been selected just in case I want to use a BoundMapperFacade, but it’s possible to use a MapperFacade directly by creating a MapperFacadeFactory.

Now, let’s configure the Spring application

This is enough for the project to run:

But pay attention, the mapper didn’t work, because there are differences between the two classes (tow attributes with different names, and the same concept, address, with different types)

Plugging in Orika Mappers and Converters with Spring

Orika provides custom converters and mappers, so the only thing we need is to configure them as spring beans in the application context. Let’s see how to do this.

First, we need a custom mapper. We annotate it as component to be discovered (via component scanning) by Spring.

Finally, we have to plug in mappers and converters that belongs to the Spring application context, into the MapperFactory. If we extend ConfigurableMapper we will have a MapperFactory created for us, and later on, the chance to access the application context itself to look up for the custom mappers and converters that are Spring components to register them in the MapperFactory.

Let’s show the code:

Some important things to note here:

  • Our class SpringConfigurableMapper is a @Component
  • When Spring instantiates it, it will call its constructor that is inherited from ConfigurableMapper and it calls an init method that creates a MapperFactory and allows you to configure via the overriden method.

    So, the first method called is configure(MapperFactory).

    Furthermore, don’t create your own MapperFactory as I did above, because it won’t be the one you’ll use to register the mappers and converters, on the contrary, this class will create a new MapperFactory.

  • Our class SpringConfigurableMapper has the ApplicationContext @Autowired
  • It’s the same as if you implement ApplicationContextAware, but I’d rather this approach.

    Besides, it implies that the method will be called after all the beans have been created. Since you already have a MapperFactory, you can then search for custom components and converters that are spring beans and register them in the MapperFactory.

  • Our class extends ConfigurableMapper that implements MapperFacade
  • So, you have to slightly change the PersonServiceImpl and it’s better to not have a MapperFacadeFactory or you will have an autowiring exception because there would be two beans of the MapperFacade class:

    Now, if you run the Orika with Spring main class, OrikaSpringTest, everything will run as expected:

    Resources

    Author: Javier (@jbbarquero)

    Java EE developer, swim addict, occasional videogames player, fan of Ben Alex and Shamus Young, and deeply in love with my wife. Sooner or later I'll dedicate a post to expand this simple introduction.

One Comment

  1. elaatifi@gmail.com'

    Thanks for this great article !

Leave a Reply

Required fields are marked *.