Skip to content

Instantly share code, notes, and snippets.

@ThomasGirard
Created October 23, 2013 09:50
Show Gist options
  • Save ThomasGirard/7115693 to your computer and use it in GitHub Desktop.
Save ThomasGirard/7115693 to your computer and use it in GitHub Desktop.
Property initializer addition for PropertyUtilsBean from commons-beanutils
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import org.apache.commons.beanutils.NestedNullException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.beanutils.expression.Resolver;
import org.apache.commons.lang.StringUtils;
/**
* Extension of {@link PropertyUtilsBean} with a method to initialize a bean's members along a path expression.
*/
public class MyPropertyUtilsBean extends PropertyUtilsBean {
private final static MyPropertyUtilsBean instance = new MyPropertyUtilsBean();
public static MyPropertyUtilsBean getInstance() {
return instance;
}
/** Mostly copy-pasted from {@link PropertyUtilsBean.setProperty}. */
public void initProperty(Object bean, String path) throws SecurityException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
if (bean == null) {
throw new IllegalArgumentException("No bean specified");
}
Resolver resolver = getResolver();
// Iterate through path segments
while (resolver.hasNested(path)) {
// Current path segment
String next = resolver.next(path);
// Retrieve the bean for this segment, depending on path type
// TODO add support for non-simple paths
Object nestedBean = null;
if (bean instanceof Map) {
nestedBean = getPropertyOfMapBean((Map) bean, next);
} else if (resolver.isMapped(next)) {
nestedBean = getMappedProperty(bean, next);
} else if (resolver.isIndexed(next)) {
nestedBean = getIndexedProperty(bean, next);
} else {
nestedBean = getSimpleProperty(bean, next);
}
// If the component is null, initialize it
if (nestedBean == null) {
// There has to be a method get* matching this segment
String methodName = "get" + StringUtils.capitalize(next);
Method m = bean.getClass().getMethod(methodName);
// The return type of this method is the object type we need to init.
Class<?> propType = m.getReturnType();
try {
// Since it's a bean it must have a no-arg public constructor
Object newInst = propType.newInstance();
PropertyUtils.setProperty(bean, next, newInst);
// Now we have something instead of null
nestedBean = newInst;
} catch (Exception e) {
throw new NestedNullException("Could not init property value for '" + path + "' on bean class '"
+ bean.getClass() + "'. Class: " + propType);
}
}
// Recurse
bean = nestedBean;
path = resolver.remove(path);
}
}
}
import org.apache.commons.beanutils.NestedNullException;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Assert;
import org.junit.Test;
import ch.hotela.casemgmt.util.MyPropertyUtilsBean;
public class MyPropertyUtilsBeanTest {
@Test
public void testPath() throws Exception {
Foo bean = new Foo();
String path = "foo.foo.foo.bar.value";
Object value = "Hello world";
MyPropertyUtilsBean.getInstance().initProperty(bean, path);
PropertyUtils.setProperty(bean, path, value);
Object o = PropertyUtils.getProperty(bean, path);
Assert.assertEquals(value, o);
}
@Test(expected = NestedNullException.class)
public void testPathNoInit() throws Exception {
Foo bean = new Foo();
String path = "foo.foo.foo.bar.value";
Object value = "Hello world";
// MyPropertyUtilsBean.getInstance().initProperty(bean, path);
PropertyUtils.setProperty(bean, path, value);
Object o = PropertyUtils.getProperty(bean, path);
Assert.assertEquals(value, o);
}
}
// Beans must be in their own source file !
public class Bar {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public class Foo {
private Foo foo;
private Bar bar;
public Foo getFoo() {
return foo;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment