Skip to content
This repository has been archived by the owner on Aug 8, 2020. It is now read-only.
Sebastian Gröbler edited this page Aug 6, 2013 · 10 revisions

What is this about?

This project provides convenience methods to do Java bean introspection. It's main functionality is to provide a very thin wrapper around the java.beans.Introspector, which can not handle generic classes to well in Java version 1.6.

These are the known bugs, this project works around:

What is Java beans introspection?

The Java beans introspection facilities allow to inspect Java beans. This means it encapsulates the hassle of doing a lot of manual reflection work to retrieve property information from beans. The problem with the implementation prior to Java 1.7 is, that generic properties may not be resolved correctly.

The problem

Assume we have the following interface:

public interface Identifiable<T> {
	T getId();
}

and let's say we have this implementing class:

public class User implements Identifiable<Integer> {

	private Integer id;

	@Override
	public Integer getId() {
		return this.id;
	}

	public void setId(final Integer id) {
		this.id = id;
	}

	// hashCode, equals and toString omitted
	...
}

and let's say you want to check if a given type has a property with the name "id" and provides a public setter and getter:

public static boolean hasIdProperty(Class<?> type) {
	BeanInfo beanInfo = Introspector.getBeanInfo(type);
	for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
		boolean matchesName = propertyDescriptor.getName().equals("id");
		boolean hasGetter = propertyDescriptor.getReadMethod() != null;
		boolean hasSetter = propertyDescriptor.getWriteMethod() != null;

		if (matchesName && hasGetter && hasSetter) {
			return true;
		}
	}
	return false;
}

The following test will randomly fail in Java versions 1.5 and 1.6:

@Test
public void introspectorMustFindGenericIdProperty() {
	assertFalse(hasIdProperty(User.class));
}

The reason

The reason why this happens is because the introspector tries to find getter and setter methods that match the name of the defined properties and have the same type, either as input (setter) or as output (getter). Since Java erases generic type information at compile time it replaces the generics with so called bridged methods that will bridge between Object and the actual type defined, in this case Integer. This means for the case shown above there will be two getters for the property "id" in the compiled class, one that returns an Object and one that returns an Integer.

In case the introspector finds the getter that returns Object first it will conclude there is no getter, because the return type is not the type of the property.

Clone this wiki locally