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
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.
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:
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:
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:
- 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);
as per today, some of the features available are:
- support copy of immutable beans.
- support copy of mutable beans.
- support copy of hybrid beans (some fields private and some not).
- support copy of Java beans without getter and setters.
- support Validation through annotations
- support copy with Java primitive types
- support copy with Java Collection types
- support copy with nested map fields
- support copy with Array containing primitive and not object types
- support copy with property name mapping
- support copy with recursion copy
- support 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:
- The val field has a different type than the Source object, indeed one is String and one is Double
- 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
- 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.
- 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.
- 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.
Useful links
- Third Party Libraries comparison
- Usage examples
- How to test the library into a real application
- Performances
- Code repository
- Javadoc
- Site
Conclusions and key takeaways
- Dedicating some business hours to Innovation may encourage developers to express their potentiality, creating solutions that would be useful in daily activities. This library is a great example as it has been implemented during those hours, and it’s now allowing Expedia to save time and money
- Make Open Source, a product or solutions that solve a common problem may help other people that for sure would appreciate it and probably will be encouraged to collaborate in its improvements making the software always better
- Passion is the base ingredient for good software as, in most cases, it will take a lot of time, but at the end would compensate the efforts
- BULL provides a useful speed-up of the development phase (in scenarios similar to the one described above) whilst it reduces the possibility of introducing errors
- In real-world scenarios, BULL does not introduce any performance degradation
About the Author
Fabio Borriello has a Master’s Degree of Science in Computer Engineering and a Post Graduate Certificate in Web Technologies. He is a talented and passionate J2EE Software Engineer with proven expertise in object-oriented analysis and design and exceptional record overseeing all facets of the Software Development Life Cycle, from analysis and design to implementation and maintenance. Each time he needs to face with something new it represents for him a challenge and a good occasion to learn something new.