L. G.
L. G.

Reputation: 9761

Is there a way to map a Set to a List with BeanUtils.copyProperties?

I'm using BeanUtils.copyProperties to convert two beans.

BeanUtils.copyProperties(organization, dtoOrganization);

I would like to have a List in one bean and a Set in the other one.

First bean:

public class Form {

  private Set<Organization> organization;

}

Second bean:

public final class DTOForm {

  private List<DTOOrganization> organization;

}

The result is an exception as stated here: argument type mismatch by Using BeanUtils.copyProperties

Is it possible to customize BeanUtils.copyProperties to achive it?

Upvotes: 3

Views: 3571

Answers (2)

bsiamionau
bsiamionau

Reputation: 8229

You can solve it using custom converters. Main idea is to register new converter for Sets using ConvertUtils.register(Converter converter, Class<?> clazz). It's not a problem to implement your custom set-to-list converter's convert(Class<T> type, Object value) method.

Here is simple example for your issue:

ListEntity, which has List property (don't ignore setters and getters, as far as I know, their existence is mandatory):

public class ListEntity {
    private List<Integer> col = new ArrayList<>();

    public List<Integer> getCol() {
        return col;
    }

    public void setCol(List<Integer> col) {
        this.col = col;
    }
}

SetEntity, which has Set property:

public class SetEntity {
    private Set<Integer> col = new HashSet<>();

    public Set<Integer> getCol() {
        return col;
    }

    public void setCol(Set<Integer> col) {
        this.col = col;
    }
}

Simple test class to make in work:

public class Test {
    public static void main(String... args) throws InvocationTargetException, IllegalAccessException {
        SetEntity se = new SetEntity();
        se.getCol().add(1);
        se.getCol().add(2);
        ListEntity le = new ListEntity();
        ConvertUtils.register(new Converter() {
            @Override
            public <T> T convert(Class<T> tClass, Object o) {
                List list = new ArrayList<>();
                Iterator it = ((Set)o).iterator();
                while (it.hasNext()) {
                    list.add(it.next());
                }
                return (T)list;
            }
        }, List.class);
        BeanUtils.copyProperties(le, se);
        System.out.println(se.getCol().toString());
        System.out.println(le.getCol().toString());
    }
}

The main idea of this code snipper: we register converter for all destination class List properties, it will try to convert some object o to List. Assuming, that o is a collection, we iterate over it and then return newly created list.

As a result, le will contains both 1 and 2 values. If you don't need this converter anymore, you can unregister it using ConvertUtils.deregister().

Upvotes: 1

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 299218

Converting from a set of one type to a list of another type is quite a stretch.

While you may be able to achieve it by creating custom JavaBeans PropertyEditors, I'd prefer to use a Mapper Framework like Dozer.

Upvotes: 1

Related Questions