由Dozer java API设置的自定义转换器不会为字段调用

时间:2012-11-21 14:18:21

标签: dozer

我正在使用Dozer框架在Java Bean之间进行转换。我想使用Dozer的Java Api而不是XML创建我的映射,以便能够操作和配置我的自定义转换器。

如果我在下面的代码中使用替代1运行我的转换器并删除了alt 2 - 映射到xml文件中,转换工作正常并且我的自定义转换器被调用。 如果我使用Alternative 2 - 使用java API进行映射来运行我的转换器,则映射器永远不会调用我的Converter。转换bean,但忽略相同类型的嵌套字段,在下面的代码中,转换后父字段为null。

Organization org = ...init organization....
OrganizationDto orgDto = new MyConverter().convert(organization, OrganizationDto.class);
assertEquals(3,orgDto.getParent().getX()) //Fails due to NPE since parent field is not copied

我知道java API不支持类级自定义转换器,但是字段级转换器看起来像是受支持的,因为它是在java映射API example中提供的。

(我也知道Dozer的作者建议使用Dozer作为单身人士,但下面的示例中没有包含Dozer。)

任何提示?

public class OrganizationDto {
   int x;
   OrganizationDto parent ;
   // getters and setters....
}

public class Organization {
   int x;
   Organization parent ;
   // getters and setters....
}


public class MyConverter{


private DozerBeanMapper mapper = null;

public MyConverter() {
        mapper = new DozerBeanMapper();
        // Alternative 1 - works 
//          List<String> myMappingFiles = new ArrayList<String>();
//          myMappingFiles.add("myBeanMappings.xml");
//          mapper.setMappingFiles(myMappingFiles);

        // Alternative 2 - does not work
        Map<String,CustomConverter> customConvertersWithId = new HashMap<String, CustomConverter>();
        customConvertersWithId.put("OrganizationDetailsConverter", new OrganizationDetailsConverter());
        mapper.setCustomConvertersWithId(customConvertersWithId);

        // Also tried variants using
        //mapper.setCustomConverters(Collections.<CustomConverter> singletonList(new OrganizationDetailsConverter()));

        BeanMappingBuilder builder = new BeanMappingBuilder() {
            protected void configure() {
                mapping(OrganizationDto.class, Organization.class)
                .fields("parent",
                        "parent",
                        customConverterId("OrganizationDetailsConverter"));
                }
            };          
            mapper.addMapping(builder);
    }

    public <T, S> T convert(S fromBean, Class<T> toBeanClass) {
    return mapper.map(fromBean, toBeanClass);
    }

}



<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://dozer.sourceforge.net
      http://dozer.sourceforge.net/schema/beanmapping.xsd">
    <mapping>
        <class-a>foo.OrganizationDto</class-a>
        <class-b>foo.Organization</class-b>
        <field custom-converter="foo.OrganizationDetailsConverter">
            <a>parent</a>
            <b>parent</b>
        </field>
    </mapping>
</mappings>

1 个答案:

答案 0 :(得分:1)

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);
   }
}
相关问题