我可以将 Orika 配置为忽略 return 类型的 setter
Can I configure Orika to disregard return type of setter
由于从不相关的库进行了版本升级,我们的 DTO 具有流畅的设置器。基本上是件好事,但现在 Orika 无法映射属性
public class DebugOrikaTest {
@Test
public void simpleToFluent() {
final MapperFacade mapper = new ConfigurableMapper();
final SimpleWithBoolean a = new SimpleWithBoolean();
a.setFoo(Boolean.TRUE);
a.setBar("foobar");
final FluentWithBoolean b = new FluentWithBoolean();
// act
mapper.map(a, b);
// assert
Assertions.assertEquals("foobar", b.getBar());
Assertions.assertTrue(b.isFoo());
}
@Test
public void simpleToOther() {
final MapperFacade mapper = new ConfigurableMapper();
final SimpleWithBoolean a = new SimpleWithBoolean();
a.setFoo(Boolean.TRUE);
a.setBar("foobar");
final OtherWithBoolean b = new OtherWithBoolean();
// act
mapper.map(a, b);
// assert
Assertions.assertEquals("foobar", b.getBar());
Assertions.assertTrue(b.isFoo());
}
public static class SimpleWithBoolean {
private Boolean foo;
private String bar;
public Boolean isFoo() {
return foo;
}
public void setFoo(Boolean foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
public static class FluentWithBoolean {
private Boolean foo;
private String bar;
public Boolean isFoo() {
return foo;
}
public FluentWithBoolean setFoo(Boolean foo) {
this.foo = foo;
return this;
}
public String getBar() {
return bar;
}
public FluentWithBoolean setBar(String bar) {
this.bar = bar;
return this;
}
}
public static class OtherWithBoolean {
private Boolean foo;
private String bar;
public Boolean isFoo() {
return foo;
}
public void setFoo(Boolean foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
}
simpleToOther
测试为绿色,但 simpleToFluent
失败。有没有办法配置 Orika 以将标准 JavaBean setter 映射到流畅的 setter?
罪魁祸首(至少在 Orika 1.5.2 中)是 IntrospectorPropertyResolver,它使用 java.beans:
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
这将 不 return 具有流畅的属性 setter。以下子类使用 Apache beanutils,它有一个 FluentPropertyBeanIntrospector
:
public class LenientIntrospectorPropertyResolver extends IntrospectorPropertyResolver {
private boolean includeTransientFields;
public LenientIntrospectorPropertyResolver(boolean includePublicFields) {
super(includePublicFields);
}
public LenientIntrospectorPropertyResolver(boolean includePublicFields, boolean includeTransientFields) {
super(includePublicFields, includeTransientFields);
this.includeTransientFields = includeTransientFields;
}
public LenientIntrospectorPropertyResolver() {
}
@Override
protected void collectProperties(Class<?> type, Type<?> referenceType, Map<String, Property> properties) {
PropertyUtils.addBeanIntrospector(new FluentPropertyBeanIntrospector());
final PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(type);
for (final PropertyDescriptor pd : descriptors) {
processPropertyDescriptor(type, referenceType, properties, pd);
}
}
private void processPropertyDescriptor(Class<?> type, Type<?> referenceType, Map<String, Property> properties, PropertyDescriptor pd) {
try {
Method readMethod = PropertyUtils.getReadMethod(pd);
if (readMethod == null && Boolean.class.equals(pd.getPropertyType())) {
/*
* Special handling for Boolean "is" read method; not strictly
* compliant with the JavaBeans specification, but still very common
*/
try {
readMethod = type.getMethod("is" + capitalize(pd.getName()));
} catch (NoSuchMethodException e) {
readMethod = null;
}
}
if (!includeTransientFields && (readMethod != null) && (readMethod.getAnnotation(Transient.class) != null)) {
return;
}
final Method writeMethod = PropertyUtils.getWriteMethod(pd);
processProperty(pd.getName(), pd.getPropertyType(), readMethod, writeMethod, type, referenceType, properties);
} catch (final Exception e) {
throw new RuntimeException("Unexpected error while trying to resolve property " + referenceType.getCanonicalName() + ", [" + pd.getName() + "]", e);
}
}
}
然后需要注册PropertyResolver
factoryBuilder.propertyResolverStrategy(new LenientIntrospectorPropertyResolver());
由于从不相关的库进行了版本升级,我们的 DTO 具有流畅的设置器。基本上是件好事,但现在 Orika 无法映射属性
public class DebugOrikaTest {
@Test
public void simpleToFluent() {
final MapperFacade mapper = new ConfigurableMapper();
final SimpleWithBoolean a = new SimpleWithBoolean();
a.setFoo(Boolean.TRUE);
a.setBar("foobar");
final FluentWithBoolean b = new FluentWithBoolean();
// act
mapper.map(a, b);
// assert
Assertions.assertEquals("foobar", b.getBar());
Assertions.assertTrue(b.isFoo());
}
@Test
public void simpleToOther() {
final MapperFacade mapper = new ConfigurableMapper();
final SimpleWithBoolean a = new SimpleWithBoolean();
a.setFoo(Boolean.TRUE);
a.setBar("foobar");
final OtherWithBoolean b = new OtherWithBoolean();
// act
mapper.map(a, b);
// assert
Assertions.assertEquals("foobar", b.getBar());
Assertions.assertTrue(b.isFoo());
}
public static class SimpleWithBoolean {
private Boolean foo;
private String bar;
public Boolean isFoo() {
return foo;
}
public void setFoo(Boolean foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
public static class FluentWithBoolean {
private Boolean foo;
private String bar;
public Boolean isFoo() {
return foo;
}
public FluentWithBoolean setFoo(Boolean foo) {
this.foo = foo;
return this;
}
public String getBar() {
return bar;
}
public FluentWithBoolean setBar(String bar) {
this.bar = bar;
return this;
}
}
public static class OtherWithBoolean {
private Boolean foo;
private String bar;
public Boolean isFoo() {
return foo;
}
public void setFoo(Boolean foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
}
simpleToOther
测试为绿色,但 simpleToFluent
失败。有没有办法配置 Orika 以将标准 JavaBean setter 映射到流畅的 setter?
罪魁祸首(至少在 Orika 1.5.2 中)是 IntrospectorPropertyResolver,它使用 java.beans:
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
这将 不 return 具有流畅的属性 setter。以下子类使用 Apache beanutils,它有一个 FluentPropertyBeanIntrospector
:
public class LenientIntrospectorPropertyResolver extends IntrospectorPropertyResolver {
private boolean includeTransientFields;
public LenientIntrospectorPropertyResolver(boolean includePublicFields) {
super(includePublicFields);
}
public LenientIntrospectorPropertyResolver(boolean includePublicFields, boolean includeTransientFields) {
super(includePublicFields, includeTransientFields);
this.includeTransientFields = includeTransientFields;
}
public LenientIntrospectorPropertyResolver() {
}
@Override
protected void collectProperties(Class<?> type, Type<?> referenceType, Map<String, Property> properties) {
PropertyUtils.addBeanIntrospector(new FluentPropertyBeanIntrospector());
final PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(type);
for (final PropertyDescriptor pd : descriptors) {
processPropertyDescriptor(type, referenceType, properties, pd);
}
}
private void processPropertyDescriptor(Class<?> type, Type<?> referenceType, Map<String, Property> properties, PropertyDescriptor pd) {
try {
Method readMethod = PropertyUtils.getReadMethod(pd);
if (readMethod == null && Boolean.class.equals(pd.getPropertyType())) {
/*
* Special handling for Boolean "is" read method; not strictly
* compliant with the JavaBeans specification, but still very common
*/
try {
readMethod = type.getMethod("is" + capitalize(pd.getName()));
} catch (NoSuchMethodException e) {
readMethod = null;
}
}
if (!includeTransientFields && (readMethod != null) && (readMethod.getAnnotation(Transient.class) != null)) {
return;
}
final Method writeMethod = PropertyUtils.getWriteMethod(pd);
processProperty(pd.getName(), pd.getPropertyType(), readMethod, writeMethod, type, referenceType, properties);
} catch (final Exception e) {
throw new RuntimeException("Unexpected error while trying to resolve property " + referenceType.getCanonicalName() + ", [" + pd.getName() + "]", e);
}
}
}
然后需要注册PropertyResolver
factoryBuilder.propertyResolverStrategy(new LenientIntrospectorPropertyResolver());