1. Overview
Apache Commons BeansUtils contains all tools necessary for working with Java beans.
Simply put, a bean is a simple Java classes containing fields, getters/setters, and a no-argument constructor.
Java provides reflection and introspection capabilities to identify getter-setter methods and call them dynamically. However, these APIs can be difficult to learn and may require developers to write boilerplate code to perform simplest operations.
2. Maven Dependencies
Here is the Maven dependency need to be included in the POM file before using it:
<dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.3</version> </dependency>
The newest version can be found here.
3. Creating a Java Bean
Let’s create two bean classes Course and Student with typical getter and setter methods.
public class Course { private String name; private List<String> codes; private Map<String, Student> enrolledStudent = new HashMap<>(); // standard getters/setters }
public class Student { private String name; // standard getters/setters }
We have a Course class that has a course name, course codes and multiple enrolled students. Enrolled Students are identified by unique enrollment Id. Course class maintains enrolled students in a Map object where enrollment Id is a key, and the student object will be the value.
4. Property Access
Bean properties can be divided into three categories.
4.1. Simple Property
Single-value properties are also called simple or scalar.
Their value might be a primitive (such as int, float) or complex type objects. BeanUtils has a PropertyUtils class that allows us to modify simple properties in a Java Bean.
Here is the example code to set the properties:
Course course = new Course(); String name = "Computer Science"; List<String> codes = Arrays.asList("CS", "CS01"); PropertyUtils.setSimpleProperty(course, "name", name); PropertyUtils.setSimpleProperty(course, "codes", codes);
4.2. Indexed Property
Indexed properties have a collection as a value that can be individually accessed using an index number. As an extension to JavaBean, BeanUtils considers java.util.List type values as indexed as well.
We can modify an indexed property individual value using a PropertyUtils’s setIndexedProperty method.
Here is example code modifying indexed property:
PropertyUtils.setIndexedProperty(course, "codes[1]", "CS02");
4.3. Mapped Property
Any property that has a java.util.Map as the underlying type is called a mapped property. BeanUtils allows us to update the individual value in a map using a String-valued key.
Here is the example code to modify the value in a mapped property:
Student student = new Student(); String studentName = "Joe"; student.setName(studentName); PropertyUtils.setMappedProperty(course, "enrolledStudent(ST-1)", student);
5. Nested Property Access
If a property value is an object and we need to access a property value inside that object – that would be accessing a nested property. PropertyUtils allow us to access and modify nested properties as well.
Assume we want to access the name property of Student class through Course object. We might write:
String name = course.getEnrolledStudent("ST-1").getName();
We can access the nested property values using getNestedProperty and modify the nested property using setNestedProperty methods in PropertyUtils. Here is the code:
Student student = new Student(); String studentName = "Joe"; student.setName(studentName); String nameValue = (String) PropertyUtils.getNestedProperty( course, "enrolledStudent(ST-1).name");
6. Copy Bean Properties
Copying properties of one object to another object is often tedious and error-prone for developers. BeanUtils class provides a copyProperties method that copies the properties of source object to target object where the property name is same in both objects.
Let’s create another bean class as Course we created above with same properties except it will not have enrolledStudent property instead property name will be students. Let’s name that class CourseEntity. The class would look like:
public class CourseEntity { private String name; private List<String> codes; private Map<String, Student> students = new HashMap<>(); // standard getters/setters }
Now we will copy the properties of Course object to CourseEntity object:
Course course = new Course(); course.setName("Computer Science"); course.setCodes(Arrays.asList("CS")); course.setEnrolledStudent("ST-1", new Student()); CourseEntity courseEntity = new CourseEntity(); BeanUtils.copyProperties(course, courseEntity);
Remember this will copy the properties with the same name only. Therefore, it will not copy the property enrolledStudent in Course class because there is no property with the same name in CourseEntity class.
7. Conclusion
In this quick article, we went over the utility classes provided by BeanUtils. We also looked into different types of properties and how can we access and modify their values.
Finally, we looked into accessing nested property values and copying properties of one object to another object.
Of course, reflection and introspection capabilities in the Java SDK also allow us to access properties dynamically but it can be difficult to learn and require some boilerplate code. BeanUtils allows us to access and modify these values with a single method call.
Code snippets can be found over on GitHub.