It's often good if you don't have to talk for 10 mins to make a single point. Similarly, it’s good if you don't need to write 50 lines of code to do a simple task. To bring this layer of abstraction and remove the boilerplate code, many libraries exist such as apache-commons and spring-beans.
Let's take a closer look at one of the most powerful and very commonly used utility classes that both of these libraries expose in their own version i.e. BeanUtils.
BeanUtils.copyProperties
We've all worked in multi-tiered applications with the responsibility of different tiers being very clearly defined. So to convert a DTO (data transfer object) to an Entity and back, we usually need to write code that looks like something like this:
Here we're trying to convert an object Bot into its data transfer object BotDTO. The object has 6 fields of primitive data type and a nested object of Config. In the next example, I'm using a builder which is better but still looks pretty verbose.
But with BeanUtils, we can modify it to look something like this:
Looks much neater right? But it’s more than what it looks like in this simple example.
Key Considerations When Using BeanUtils
The above quote from the documentation of apache-commons shows that if your DTO or Entity do not have field signature matching or if your target object has a few nested fields, BeanUtils will not populate those fields for you. So there is no easy way to be sure which fields haven't been copied except by writing elaborate test cases around each field to ensure that the desired fields have been copied.
Internally these utility libraries use reflection to do all the magic of copying field values from source to target. So if the objects in question have a specific way of constructing using a few mandatory fields in the class or if they are mutable only to a certain level then this utility may not be the best fit (although this utility does provide exclusionFields which then you can handle manually).
The concept of deep copying an object means that all nested objects within an object at all levels of nesting get copied when an attempt is made to copy the parent-level object.
So in this example when we try to copy fields of Bot to BotDTO, fields in Config object also should get copied to ConfigDTO. But BeanUtils.copyProperties does not perform a deep copy of fields and each level has to be created and separately copied.
More Efficient Coding Approach
We're not trying to say that there are all problems with these libraries and we shouldn't use them. This is a very powerful utility tool for simple POJOs and many cases to reduce boilerplate code. But we need to be careful as the library isn't a universal solution and at times, you may need something more custom for your purpose. And along with using this library, we need to absolutely make sure that we write good unit test cases to ensure that all expected fields are getting copied correctly.
Thanks for reading! We hope you found this article helpful.