7

How do I programmatically set custom converter for dozer? The following code doesn't work:

Custom Converter implementation:

class ConverterImpl extends DozerConverter<A, B> {

ConverterImpl() {
    super(A.class, B.class);
}

@Override
public B convertTo(A source, B destination) {
    return destination;
}

@Override
public A convertFrom(B source, A destination) {
    return destination;
}
}

Test code:

DozerBeanMapper mapper = new DozerBeanMapper();
mapper.setCustomConverters(Collections.<CustomConverter>singletonList(new ConverterImpl()));
A a = new A(); 
B b = mapper.map(a, A.class);  

After running the code above, custom converter doesn't get invoked. What is wrong?

andrew.z
  • 1,039
  • 3
  • 15
  • 24

2 Answers2

4

Looks like you have to actually add a specific mapping, and unfortunately you can only specify field-level converters, not class-level converters, using the programmatic API. So if you wrap the A and B classes in container classes, you can specify a mapping for the A and B fields.

For example the following verbose code works as expected:

public class DozerMap {

   public static class ContainerA {
      private A a;
      public A getA() { return a; }
      public void setA(A a) { this.a = a; }
   }

   public static class ContainerB {
      private B b;
      public B getB() { return b; }
      public void setB(B b) { this.b = b; }
   }

   private static class A { };

   private static class B { };

   static class ConverterImpl extends DozerConverter<A, B> {

      ConverterImpl() {
         super(A.class, B.class);
      }

      @Override
      public B convertTo(A source, B destination) {
         Logger.getAnonymousLogger().info("Invoked");
         return destination;
      }

      @Override
      public A convertFrom(B source, A destination) {
         Logger.getAnonymousLogger().info("Invoked");
         return destination;
      }
   }

   public static void main(String[] args) {

      DozerBeanMapper mapper = new DozerBeanMapper();
      mapper.setCustomConverters(Collections.<CustomConverter> singletonList(new ConverterImpl()));
      BeanMappingBuilder foo = new BeanMappingBuilder() {

         @Override
         protected void configure() {
            mapping(ContainerA.class, ContainerB.class).fields("a", "b", FieldsMappingOptions.customConverter(ConverterImpl.class));
         }
      };
      mapper.setMappings(Collections.singletonList(foo));
      ContainerA containerA = new ContainerA();
      containerA.a = new A();
      ContainerB containerB = mapper.map(containerA, ContainerB.class);
   }
}
artbristol
  • 32,010
  • 5
  • 70
  • 103
  • I think the API has changed in 5.5.1. I could not find a method for mapper.setMappings(Collections.singletonList(foo)); Instead I used mapper.addMapping(foo); – rjdkolb Feb 08 '16 at 06:39
0

Why do you want to set it programatically ? I mean do you have any specific needs ? Otherwise, Mapping via an xml file works fine.

In case you want to do it more in a programing way , rather through some xml configuration files, Check out Orika.

It has good API support.

Priyank Doshi
  • 12,895
  • 18
  • 59
  • 82
  • 1
    he's trying to map the classes without specifying the particular class fields – ant May 14 '12 at 08:22