The Unbearable Lightness of Java

BeanUtil beanutil

Bean utilities, in short, allow setting and reading bean properties. However, several things make it different from other similar libraries. First, it is the fastest bean manipulation utility. Second, it may work with attributes and properties in the same time: when class doesn't define setters and getters, its attributes may be used. Third, there is a nice variety of available functions that might suit most needs. Code is divided in logical sections, so it is easy to use it even in specific way, if there is such requirement.

Working with bean properties

Bean property is a class field with its (optional) setter and getter (aka accessors) methods. When accessing properties, BeanUtil first tries to use accessors methods. If such doesn't exist, BeanUtil failbacks to using the field of the same visibility. Therefore, existence of accessors methods is not required and depends on usage, what sometimes may be handy. BeanUtil is used internaly inside Jodd library, so this behavior applies everywhere.

Simple bean:
public class Foo {
	private String readwrite;	// with gettter and setter
	private String readonly;	// with getter
	...
}
Usage:
Foo foo = new Foo();
BeanUtil.setProperty(foo, "readwrite", "data");
BeanUtil.getProperty(foo, "readwrite");
BeanUtil.setDeclaredProperty(foo, "readonly", "data");

Lines #2 and #3 show common and expected BeanUtil usage: setting value of read-write property through it's accessors methods. Setting readonly property in above example is only possible with setDeclaredProperty() method. It first tries to use setReadonly() method, but since such doesn't exist, field is used directly.

Nested properties

BeanUtil is a also able to manipulate nested properties. Nested property may be bean's property; but also list, map or array element:

		BeanUtil.getProperty(cbean, "list[0].map[foo].foo");
		BeanUtil.setProperty(cbean, "arr[4].map[elem.boo].foo", "test");

In above example, BeanUtil goes one property at time and therefore expects that all nested properties (except the very last one) exist i.e. to be not-null. So the example will actually perform the following pseudo-code:

		cbean.getList().get(0).get("foo").getFoo();
		cbean.getArr()[4].get("elem.boo").setFoo("test");

Forced setting of nested properties

Setting of nested properties fails if one of the (middle) elements on the path is null. To solve this problem, properties may be set in forced mode:

BeanUtil.setPropertyForced(x, "y.foo", value);   
BeanUtil.setPropertyForced(x, "yy[2].foo", "xxx");

If the object x in above example has uninitialized property y, BeanUtil first creates a new instance of y's type, that will be set to property y. Then, foo property of newly created object y will be set. In the second example, yy is an array. If it is uninitialized, BeanUtil will create a new array of length 3. Then, it will create new instance of yy's type that will be stored as third element of the array. Finally, the foo property is set.

In forced mode, BeanUtil tries to instantiate uninitialized properties needed for setting the final property. Instantiation depends of the type: if it is a simple bean, no-args constructor will be invoked. If it is a list, new ArrayList will be created. Similar applies for arrays and map types. Additionally, BeanUtil will check the length of existing initialized arrays and lists, and if the current size is not enough, list or array will be expanded by adding null elements up to the new size.

When creating new element of an list, BeanUtil will consider existing generics information in order to create element of correct type.

Silent setting (no exceptions)

Property setting may fail from various reasons, causing an unchecked exception to be thrown. However, sometimes this is not desired behavior. For such usages, BeanUtil offers silent version of setting methods that will not throw an exception at all. If setting is not successful, simple nothing happens.

Self-reference

In some (rare) occasions BeanUtil has to work on arrays, lists or maps directly instead on beans. In such cases it is needed to somehow reference this object, in order to use its elements. For such situations, BeanUtil introduce special self-reference property name: "*this". It simply points to current reference.

For example, lets say that it is needed to reference some element from context map (or array, or list) using BeanUtil and to set value of one of it's properties: context[foo].boo. Since context is the target bean used as an argument of BeanUtil, it is needed be able to somehow access it in the property name. This is possible with self-reference:

BeanUtil.setProperty(ctx, "*this[foo].boo", value);

Although it's purpose is to be used on very start of nested property name, self-reference may be used anywhere in between. So the following two property names are identical:

BeanUtil.getProperty(fb4, "data[0].bbean.abean.fooProp");
BeanUtil.getProperty(fb4, "*this.data.*this[0].*this.bbean.abean.fooProp");

Testing of property existence

BeanUtil also offers convenient way to test if some property exists:

BeanUtil.hasProperty(fb, "fooInteger")

Performance test

BeanUtil seems almost 20% faster compared to Common's BeanUtils v1.7. However, the performance is not the only key reason why BeanUtil might be a good choice, as seen above.

BeanUtil performance test