Why you should spend more time implementing software utilities rather than the core one?

Fabio Borriello
Apr 11 · 6 min read

In a layered architecture, where you are creating levels of abstraction by encapsulating changes to particular data objects and propagating these to other layers, the object mapping process can become mandatory and cumbersome.

The data object mapping has traditionally been addressed by hand-coding transformers that copy data between the entities (or Java Beans).

This task may require countless hours and thousands of lines of code mapping to and from their different data object depending on the number of items you need to transform.

The amount of work required is substantial, especially if the necessary amount of test cases are taken into account.

This type of code for such conversions is rather boring to write and extremely error-prone, so why not do it automatically?

The problem

Luckily, there are plenty of mapping frameworks available on the web that can do this for us, so we are safe!

But, what happens if your Java Beans are immutable as per common security best practices? The consequence of this is that there is no available mapping framework able to transform your objects in a simple way.

The solution

A library that can automatically transform all kinds of Java Beans, including Immutable, mutable and mixed would save us a lot of work and BULL does.

BULL logo

The benefits

To better show the benefits of having this library in place, let’s go through an example: imagine that you are working on a multi-tier application, built as follow:

Application architecture using classic transformers

The FooController contains a Rest API that gets a request in input and returns a response after having performed a set of operations.

To obtain the response, the FooController needs to get the request/response data (mapped by Domain objects similar to this) moving across the three layers so we do need to implement, for each one of them: a Transformer (plus its test), that copies, and modifies if needed, the data from one object to the other in the next layer.

Summarising, for each layer, we will need 20 classes divided up as follows:

  • 1 Service class
  • 1 Service class’s test
  • 6 Domain objects
  • 6 Transformers
  • 6 Transformer’s tests

Multiplied for the 3 layers gives a total of 60 classes.


Let’s now analyze the same scenario using BULL:

Application architecture using BULL

Now the situation looks quite different: the Transformer classes are not needed anymore and the total classes we need for all 3 layers are reduced to just 24, and overall we have 60% less code. That implies:

That implies:

  • Less development time (so direct cost reduction)
  • Reduced possibility of introducing errors
  • Code that is easier to maintain

What BULL can do

BULL has been built trying to make its usage as much easy as possible, indeed to transform an object it’s needed just one line of code:

ToBean toBean = new BeanUtils().transform(fromBean, ToBean.class);

Supported features

  • copy of immutable beans.
  • copy of mutable beans.
  • copy of hybrid beans (some fields private and some not).
  • copy of Java beans without getter and setters.
  • Validation through annotations
  • copy with Java primitive types
  • copy with Java Collection types
  • copy with nested map fields
  • copy with Array containing primitive and not object types
  • copy with property name mapping
  • copy with recursion copy
  • lambda function field transformation

The full list of features, always updated including examples, is available here.

Transformation in real life

We know that, in real life, it’s rare that we just need to copy information between two Java Beans almost identical, often occurs that:

  • the destination object has a totally different structure than the source object
  • we need to perform some operation on a specific field value before copying it
  • the destination object’s fields have to be validated
  • the destination object has an additional field than the source object that needs to be filled with something coming from a different source

How we can solve this? well BULL gives you the possibility to perform any kind of operation on a specific field!

Taking advantage of lambda expressions the developer can define its own method that will be applied to the a value before copying it.

Let’s explain it better with an example:

Given the following Source class:

public class FromFoo {
private final String id;
private final String val;
private final List<FromSubFoo> nestedObjectList;
// all args constructor
// getters
}

and the following Destination class:

public class MixedToFoo {
public String id;

@NotNull
private final Double val;
// constructors
// getters and setters
}

and assuming that the val field needs to be multiplied by a random value in our transformer, we have 2 problems:

  1. The val field has a different type than the Source object, indeed one is String and one is Double
  2. We need to instruct the library on how we would apply out math operation

Well, this is pretty simple, you just need to define your own Lambda Expression that does that:

FieldTransformer<String, Double> valTransformer =
new FieldTransformer<>("val",
n -> Double.valueOf(n) * Math.random());

The expression will be applied to the field with the name: “val” in the destination object.

The last step is to pass the function the BULL instance:

beanUtils.getTransformer()
.withFieldTransformer(valTransformer)
.transform(fromFoo, MixedToFoo.class);

For what concerns the “field validation” aspect, it’s even simpler as you only need to annotate your field with one of the existing javax.validation.constraints (or defining a custom one) and that’s it.

How did we get there?

As we used to implement tons of Java Bean Transformers that, too often, required more implementation time than the core feature we were working on, we decided to start implementing something that would speed-up our development process and that could be useful to all the ones who were dealing with the same issue.

Thanks to the Hotels.com company culture, we had half-a-day per week to spend on Innovation projects. Taking the opportunity for implementing this, and other products, are now showing their benefit. In this particular case, we markedly reduced the development time of several of the features we work on.

Why Open Sourcing

  1. OSS also has long-term viability. It’s created and supported by a worldwide community of organizations and individual developers, many of whom also live by open source values like collaboration and volunteerism.
  2. OSS is supported by a community of developers. These same development shops are constantly reviewing the OSS code they support, as are thousands of independent developers working on the project worldwide. The result is a vast peer-review process that ensures security and accountability.
  3. OSS has strong values — and more often than not, OSS shops and developers hold similar values — they are advocates for more community participation, collaboration, and volunteerism. They believe in working together to build free, high-quality products that are accessible to for-profit and nonprofit organizations alike.
    This belief underlines the mission of the best OSS shops and developers. It pushes them to build new features and contribute these features back to the community. As a direct result, popular OSS projects are often on the cutting-edge of technology.

Key Takeaways

  • Dedicating some business hours to Innovation may encourage developers to express their potentiality, creating solutions that would be useful in daily activities
  • Make Open Source, products or solutions that solve a common problem may help other people
  • Passion is a key ingredient for good software
  • BULL provides a useful speed-up of the development phase whilst it reduces the possibility of introducing errors
  • In real-world scenarios, BULL does not introduce any performance degradation

Useful links

This article has been originally published by InfoQ.
A detailed guide on how to use it is available on Dzone.

What’s next

The library is under continuous evolution, and new features are released constantly.
All the on-going activities can be followed here.

Expedia Group Technology

Stories from the Expedia Group Technology teams

Thanks to Abhimanyu Gupta

Fabio Borriello

Written by

Expedia Group Technology

Stories from the Expedia Group Technology teams

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade