41

springframework.beans.BeanUtils is very useful to copy objects, and I use the "ignoreProperties" option frequently. However, sometimes I want to copy only specific objects (basically, the opposite of "ignore Properties"). Does anyone know how can I do that? Any help will be appreciated.

import org.springframework.beans.BeanUtils;

public class Sample {    
    public static void main(String[] args) {    
        DemoADto demoADto = new DemoADto();
        demoADto.setName("Name of Demo A");
        demoADto.setAddress("Address of Demo A");

        DemoBDto demoBDto = new DemoBDto();

        // This is "ignoreProperties" option
        // But I want to know how I can copy only name field by using BeanUtils or something.
        BeanUtils.copyProperties(demoADto, demoBDto, new String[] {"address"});

        System.out.println(demoBDto.getName());
        System.out.println(demoBDto.getAddress());    
    }    
}

public class DemoADto {    
    private String name;    
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }    
}

public class DemoBDto {    
    private String name;    
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }    
}
Donut
  • 110,061
  • 20
  • 134
  • 146
zono
  • 8,366
  • 21
  • 75
  • 113

6 Answers6

65

You can use the BeanWrapper technology. Here's a sample implementation:

public static void copyProperties(Object src, Object trg, Iterable<String> props) {

    BeanWrapper srcWrap = PropertyAccessorFactory.forBeanPropertyAccess(src);
    BeanWrapper trgWrap = PropertyAccessorFactory.forBeanPropertyAccess(trg);

    props.forEach(p -> trgWrap.setPropertyValue(p, srcWrap.getPropertyValue(p)));

}

Or, if you really, really want to use BeanUtils, here's a solution. Invert the logic, gather excludes by comparing the full property list with the includes:

public static void copyProperties2(Object src, Object trg, Set<String> props) {
    String[] excludedProperties = 
            Arrays.stream(BeanUtils.getPropertyDescriptors(src.getClass()))
                  .map(PropertyDescriptor::getName)
                  .filter(name -> !props.contains(name))
                  .toArray(String[]::new);

    BeanUtils.copyProperties(src, trg, excludedProperties);
}
Fabio Bonfante
  • 5,128
  • 1
  • 32
  • 37
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
3

If you don't want to use Commons BeanUtils you can still use Spring by using the BeanWrapper.

You will have to manually loop through all the properties so you will want to make a static helper method.

You can always just copy what copyProperties is doing and adjust to your liking: http://tinyurl.com/BeanUtils-copyProperties

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
2

Check this out: BeanPropertyCopyUtil.

Example:

copyProperties(user, systemUser, "first firstName", "last lastName");

You'll also need Apache Commons BeanUtils.

eolith
  • 1,366
  • 10
  • 14
  • This is not appropriate way to achieve this. What if your attribute name modified ? passing it as string is not better approach, rather fetch all the fields using Field[] fields = destination.getClass().getDeclaredFields(); And iterate over the fields for (Field field : fields){ //ur copy stuff here } – Sadanand Oct 23 '14 at 02:46
  • This is not working with child properties, let's say i wanted to ignore all properties with name "id". – Yogesh Prajapati Apr 16 '19 at 12:26
2

beanUtils has an overloaded method wherein we can pass an array of fields that we want to ignore.

Eg.

String[] ignoreProperties= new String[]{"field1","field2"};

BeanUtils.copyProperties(a, b,ignoreProperties);

enter image description here

AConsumer
  • 2,461
  • 2
  • 25
  • 33
1

You may use org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable) throws BeansException

Ensure the target implements the interface editable which defines the properties which would be copied.

Gautam Pal
  • 51
  • 2
0

Here is an Example with Spring BeanUtils class:

public static void copyList(List sourceList,
        List targetList, Class targetType) {

    try {

        for (Object source : sourceList) {
            Object target = null;
            target = targetType.newInstance();
            BeanUtils.copyProperties(source, target);
            targetList.add(target);
        }

    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}