Helper in order to copy non null properties from object to another
See the following class
public class Parent {
private String name;
private int age;
private Date birthDate;
// getters and setters
}
Suppose I have created a parent object as follows
Parent parent = new Parent();
parent.setName("A meaningful name");
parent.setAge(20);
Notice according to code above birthDate property is null. Now I want to copy only non-null properties from parent object to another. Something like
SomeHelper.copyNonNullProperties(parent, anotherParent);
I need it because I want to update anotherParent object without overwriting its non-null with null values.
Do you know some helper like this one?
I accept minimal code as answer whether no helper in mind
I supose you already have a solution, since a lot of time has happened since you asked. However, it is not marked as solved, and maybe I can help other users.
Have you tried by defining a subclass of the BeanUtilsBean
of the org.commons.beanutils
package? Actually, BeanUtils
uses this class, so this is an improvement of the solution proposed by dfa.
Checking at the source code of that class, I think you can overwrite the copyProperty
method, by checking for null values and doing nothing if the value is null.
Something like this :
package foo.bar.copy;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtilsBean;
public class NullAwareBeanUtilsBean extends BeanUtilsBean{
@Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value==null)return;
super.copyProperty(dest, name, value);
}
}
Then you can just instantiate a NullAwareBeanUtilsBean
and use it to copy your beans, for example:
BeanUtilsBean notNull=new NullAwareBeanUtilsBean();
notNull.copyProperties(dest, orig);
Using PropertyUtils (commons-beanutils)
for (Map.Entry<String, Object> e : PropertyUtils.describe(parent).entrySet()) {
if (e.getValue() != null && !e.getKey().equals("class")) {
PropertyUtils.setProperty(anotherParent, e.getKey(), e.getValue());
}
}
in Java8:
PropertyUtils.describe(parent).entrySet().stream()
.filter(e -> e.getValue() != null)
.filter(e -> ! e.getKey().equals("class"))
.forEach(e -> {
try {
PropertyUtils.setProperty(anotherParent, e.getKey(), e.getValue());
} catch (Exception e) {
// Error setting property ...;
}
});
Simply use your own copy method:
void copy(Object dest, Object source) throws IntrospectionException, IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
BeanInfo beanInfo = Introspector.getBeanInfo(source.getClass());
PropertyDescriptor[] pdList = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pdList) {
Method writeMethod = null;
Method readMethod = null;
try {
writeMethod = pd.getWriteMethod();
readMethod = pd.getReadMethod();
} catch (Exception e) {
}
if (readMethod == null || writeMethod == null) {
continue;
}
Object val = readMethod.invoke(source);
writeMethod.invoke(dest, val);
}
}
If your setter's return type is not void, BeanUtils of Apache will not work, spring can. So combine the two.
package cn.corpro.bdrest.util;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.springframework.beans.BeanUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
/**
* Author: [email protected]
* DateTime: 2016/10/20 10:17
*/
public class MyBeanUtils {
public static void copyPropertiesNotNull(Object dest, Object orig) throws InvocationTargetException, IllegalAccessException {
NullAwareBeanUtilsBean.getInstance().copyProperties(dest, orig);
}
private static class NullAwareBeanUtilsBean extends BeanUtilsBean {
private static NullAwareBeanUtilsBean nullAwareBeanUtilsBean;
NullAwareBeanUtilsBean() {
super(new ConvertUtilsBean(), new PropertyUtilsBean() {
@Override
public PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass) {
return BeanUtils.getPropertyDescriptors(beanClass);
}
@Override
public PropertyDescriptor getPropertyDescriptor(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return BeanUtils.getPropertyDescriptor(bean.getClass(), name);
}
});
}
public static NullAwareBeanUtilsBean getInstance() {
if (nullAwareBeanUtilsBean == null) {
nullAwareBeanUtilsBean = new NullAwareBeanUtilsBean();
}
return nullAwareBeanUtilsBean;
}
@Override
public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException {
if (value == null) return;
super.copyProperty(bean, name, value);
}
}
}