javareflectionapache-commons-beanutils

Is it possible automatically instantiation of a nested Property with Commons Bean Utils?


I'm using PropertyUtils.setProperty(object, name, value) method of Apache Commons Bean Utils:

Giving these classes:

public class A {
    B b;
}

public class B {
    C c;
}

public class C {
}

And this:

A a = new A();
C c = new C();
PropertyUtils.setProperty(a, "b.c", c); //exception

If I try that I get: org.apache.commons.beanutils.NestedNullException: Null property value for 'b.c' on bean class 'class A'

Is it possible to tell PropertyUtils that if a nested property has a null value try to instantiate it (default constructor) before trying to go deeper?

Any other approach?

Thank you


Solution

  • I solved it by doing this:

    private void instantiateNestedProperties(Object obj, String fieldName) {
        try {
            String[] fieldNames = fieldName.split("\\.");
            if (fieldNames.length > 1) {
                StringBuffer nestedProperty = new StringBuffer();
                for (int i = 0; i < fieldNames.length - 1; i++) {
                    String fn = fieldNames[i];
                    if (i != 0) {
                        nestedProperty.append(".");
                    }
                    nestedProperty.append(fn);
    
                    Object value = PropertyUtils.getProperty(obj, nestedProperty.toString());
    
                    if (value == null) {
                        PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(obj, nestedProperty.toString());
                        Class<?> propertyType = propertyDescriptor.getPropertyType();
                        Object newInstance = propertyType.newInstance();
                        PropertyUtils.setProperty(obj, nestedProperty.toString(), newInstance);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
    }