14
votes

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.

8
Um, BeanUtils.copyProperties() is the proper way. It's in that library because there's no easy way to do it otherwise. If you really don't want to use BeanUtils, then download the sourcecode for it, and copy the method. - skaffman
skaffman - I didn't see your comment when I posted my answer, sorry. But as you can see I completely agree with you :) - MetroidFan2002
Note that Spring also includes a BeanUtils.copyProperties method which may be more convenient if you're already using Spring. - pimlottc

8 Answers

12
votes

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.

11
votes

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.

3
votes

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).

3
votes

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.

2
votes

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.

1
votes

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.

1
votes

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);
    }
}
0
votes

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);
    }
}