【问题标题】:Custom Converter set by Dozer java API not invoked for field没有为字段调用由 Dozer java API 设置的自定义转换器
【发布时间】:2012-11-09 19:40:55
【问题描述】:

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

如果我在下面的代码中使用替代 1 运行我的转换器,并删除了 alt 2 - xml 文件中的映射,则转换工作正常并且我的自定义转换器被调用。 如果我使用备选方案 2 运行转换器 - 使用 java API 映射,则映射器永远不会调用我的转换器。 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 中提供的。

(我也知道推土机作者建议将推土机用作单例,但这不包括在下面的示例中。)

有什么提示吗?

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>

【问题讨论】:

    标签: dozer


    【解决方案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);
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 2019-09-15
      相关资源
      最近更新 更多