Search code examples
javamappingdozer

How to tell Dozer to use LinkedHashSet collection in destination field?


In first class i have field:

private Set<Country> countries;

public Set<Country> getCountries() {
    return countries;
}

public void setCountries(Set<Country> countries) {
    this.countries = countries;
}

which will contain LinkedHashSet implementation.

In second class i have identical declaration, but during mapping, Dozer creates HashSet implementation in destination class, which destroys the order of elements. How to tell Dozer to use LinkedHashSet in destination class?


Solution

  • When Dozer maps a Set, it uses the org.dozer.util.CollectionUtils.createNewSet to create the destination Set instance. You get either a HashSet or TreeSet.

    If the order of your elements is the same as their natural order you might use a SortedSet in the destination. If not, then you need to create the destination object yourself and provide the desired Set implementation.

    Dozer allows using custom create methods or custom bean factories to instantiate objects beyond using the default constructor so you could use either method:

    Create method

    Java code:

    public class MyInstanceCreator {
        public static DestinationObject createDestinationObject() {
            DestinationObject result = new DestinationObject();
            result.setCountries(new LinkedHashSet<Country>());
            return result;
        }
        private MyInstanceCreator() { }
    }
    

    mapping:

    <mapping>
        <class-a create-method="MyInstanceCreator.createDestinationObject">DestinationObject</class-a>
        <class-b>SourceObject</class-b>
        <field>
            <a>countries</a>
            <b>countries</b>
        </field>
    </mapping>
    

    Bean factory

    Java code:

    public class MyBeanFactory implements BeanFactory {
        public Object createBean(Object source, Class<?> sourceClass, String targetBeanId) {
            DestinationObject result = new DestinationObject();
            result.setCountries(new LinkedHashSet<Country>());
            return result;
        }
    }
    

    mapping:

    <mapping>
        <class-a bean-factory="MyBeanFactory">DestinationObject</class-a>
        <class-b>SourceObject</class-b>
        <field>
            <a>countries</a>
            <b>countries</b>
        </field>
    </mapping>