Question

I have a simple Java POJO that I would copy properties to another instance of same POJO class.

I know I can do that with BeanUtils.copyProperties() but I would like to avoid use of a third-party library.

So, how to do that simply, the proper and safer way ?

By the way, I'm using Java 6.

Was it helpful?

Solution

I guess if you look at the source code of BeanUtils, it will show you how to do this without actually using BeanUtils.

If you simply want to create a copy of a POJO (not quite the same thing as copying the properties from one POJO to another), you could change the source bean to implement the clone() method and the Cloneable interface.

OTHER TIPS

I had the same problem when developing an app for Google App Engine, where I couldn't use BeanUtils due to commons Logging restrictions. Anyway, I came up with this solution and worked just fine for me.

public static void copyProperties(Object fromObj, Object toObj) {
    Class<? extends Object> fromClass = fromObj.getClass();
    Class<? extends Object> toClass = toObj.getClass();

    try {
        BeanInfo fromBean = Introspector.getBeanInfo(fromClass);
        BeanInfo toBean = Introspector.getBeanInfo(toClass);

        PropertyDescriptor[] toPd = toBean.getPropertyDescriptors();
        List<PropertyDescriptor> fromPd = Arrays.asList(fromBean
                .getPropertyDescriptors());

        for (PropertyDescriptor propertyDescriptor : toPd) {
            propertyDescriptor.getDisplayName();
            PropertyDescriptor pd = fromPd.get(fromPd
                    .indexOf(propertyDescriptor));
            if (pd.getDisplayName().equals(
                    propertyDescriptor.getDisplayName())
                    && !pd.getDisplayName().equals("class")) {
                 if(propertyDescriptor.getWriteMethod() != null)                
                         propertyDescriptor.getWriteMethod().invoke(toObj, pd.getReadMethod().invoke(fromObj, null));
            }

        }
    } catch (IntrospectionException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

Any enhancements or recomendations are really welcome.

Another alternative is MapStruct which generates mapping code at build time, resulting in type-safe mappings which don't require any dependencies at runtime (Disclaimer: I'm the author of MapStruct).

Hey friends just use my created ReflectionUtil class for copy one bean values to another similar bean. This class will also copy Collections object.

https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java

Note: This bean must have similar variables name with type and have getter and setters for them.

Now more functionalities are added. You can also copy one entity data to its bean. If one entity has another entity in it then you can pass map option for runtime change of inner entity to its related bean.

Eg.

ParentEntity parentEntityObject = getParentDataFromDB();
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
map.put(InnerBean1.class, InnerEntity1.class);
map.put(InnerBean2.class, InnerEntity2.class);
ParentBean parent = ReflectionUtil.copy(ParentBean.class, parentEntityObject, map);

This case is very useful when your Entities contains relationship.

Have a look at the JavaBeans API, in particular the Introspector class. You can use the BeanInfo metadata to get and set properties. It is a good idea to read up on the JavaBeans specification if you haven't already. It also helps to have a passing familiarity with the reflection API.

There is no simple way to do it. Introspector and the Java beans libraries are monolithic - BeanUtils is a simple wrapper around this and works well. Not having libraries just to not have libraries is a bad idea in general - there's a reason it's commons to begin with - common functionality that should exist with Java, but doesn't.

I ran into some problems with Introspector.getBeanInfo not returning all the properties, so I ended up implementing a field copy instead of property copy.

public static <T> void copyFields(T target, T source) throws Exception{
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getFields()) {
        Object value = field.get(source);
        field.set(target, value);
    }
}

You can achieve it using Java Reflection API.

public static <T> void copy(T target, T source) throws Exception {
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getDeclaredFields()) {
        if (Modifier.isPrivate(field.getModifiers()))
            field.setAccessible(true);
        Object value = field.get(source);
        field.set(target, value);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top