我正在使用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>
答案 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);
}
}