15

Spring's BeanUtils.copyProperties() provides option to ignore specific properties while copying beans:

public static void copyProperties(Object source,
                 Object target,
                 String[] ignoreProperties) throws BeansException

Does the Apache Commons BeanUtils provide a similar feature?

Also is it possible to ignore null values while using Spring's BeanUtils.copyProperties(), I see this feature with Commons BeanUtils:

Date defaultValue = null;
DateConverter converter = new DateConverter(defaultValue);
ConvertUtils.register(converter, Date.class);

Can I achieve the same with Spring's BeanUtils?

kryger
  • 12,906
  • 8
  • 44
  • 65
Arun
  • 311
  • 3
  • 7
  • 15

6 Answers6

10

In case you are using the org.springframework.beans.BeanUtils you can ignore specific properies using the method copyProperties(Object source, Object target, String... ignoreProperties). An example,

BeanUtils.copyProperties(sourceObj, targetObj, "aProperty", "another");
Georgios Syngouroglou
  • 18,813
  • 9
  • 90
  • 92
5

If you want to ignore null-value you have to do it with the following line of code before copying properties:

BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0);
Patrick Kostjens
  • 5,065
  • 6
  • 29
  • 46
edu
  • 302
  • 1
  • 6
2

This is a sample code snippet which I am using for skip the null fields while copying to target. You can add checks for specific properties using property name, value etc. I have used org.springframework.beans.BeanUtils

public static void copyNonNullProperties(Object src, Object target) {
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
}

public static String[] getNullPropertyNames(Object source) {
    final BeanWrapper src = new BeanWrapperImpl(source);
    PropertyDescriptor[] pds = src.getPropertyDescriptors();

    Set<String> emptyNames = new HashSet<String>();
    for (PropertyDescriptor pd : pds) {
        Object srcValue = src.getPropertyValue(pd.getName());
        if (srcValue == null)
            emptyNames.add(pd.getName());
    }
    String[] result = new String[emptyNames.size()];
    return emptyNames.toArray(result);
}
Prajith Vb
  • 21
  • 3
0

To add to Prajith's answer, here's one way in which I picked the property names with null values present in the source.

For some reason, I feel this is more readable. You can choose to surround with try-catch or add throws at the method level.

public static void copyNonNullProperties(Object src, Object target) {
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
}

public static String[] getNullPropertyNames(Object source) {
        List<String> nullValuePropertyNames = new ArrayList<>();
        for (Field f : source.getClass().getDeclaredFields()) {
            try {
                if (f.get(source) == null) {
                    nullValuePropertyNames.add(f.getName());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return nullValuePropertyNames.toArray(new String[0]);
    }
aayoustic
  • 99
  • 9
0

I have solved this problem with BeansUtils in such way it will work for nested classes as well.

class NullAwareBeanUtilsBean extends BeanUtilsBean {
    
    
    @Override
    public void copyProperty(Object dest, String name, Object value)
            throws IllegalAccessException, InvocationTargetException {
        if (value == null)
            return;
        else if(value instanceof NonNullCopy) {
            Class<?> destClazz = value.getClass();
                Class<?> origClazz = dest.getClass();
                String className = destClazz.getSimpleName();
        
                for(Method m : origClazz.getDeclaredMethods()) {
                    if(m.getReturnType().equals(destClazz)) {
                        copyProperties(m.invoke(dest, Collections.EMPTY_LIST.toArray()),value);
                    }                       
                }
                return;
        }

        super.copyProperty(dest, name, value);
    }

       
}


The complete explanation for the solution I have posted here:

Copy non-null properties from one object to another using BeanUtils or similar

-1

For ignoring null values:

BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0);

For ignoring specific properties:

public static void copyProperties(Object source,
                              Object target,
                              String... ignoreProperties)
                       throws BeansException

documentation for ignoring properties: Spring 4.1.0 docs

prashant.kr.mod
  • 1,178
  • 13
  • 28