Dozer无法映射Collection <interface> member </interface>

时间:2014-04-23 15:32:04

标签: java dozer

我有一个包含Collection的对象:

public class Wrapper {
    private Collection<Base> bases = new LinkedList<Base>();
    public Collection<Base> getBases() {return bases;}
    public void setBases(final Collection<Base> bases) {this.bases = bases;}
}

界面的实现非常简单:

public class BaseOne implements Base {
}

public class BaseTwo implements Base {
}

当我进行简单测试时:

@Test
public void testCopyOther() {
    final Wrapper wrapper =  new Wrapper();
    wrapper.getBases().add(new BaseOne());

    final Wrapper copy = dozer.map(wrapper, Wrapper.class);
}

我得到了这个例外:

org.dozer.MappingException: java.lang.NoSuchMethodException: com.usamp.biddingtool.model.service.impl.Base.<init>()
    at org.dozer.util.MappingUtils.throwMappingException(MappingUtils.java:82)
    at org.dozer.factory.ConstructionStrategies$ByConstructor.newInstance(ConstructionStrategies.java:261)
    at org.dozer.factory.ConstructionStrategies$ByConstructor.create(ConstructionStrategies.java:245)
    at org.dozer.factory.DestBeanCreator.create(DestBeanCreator.java:65)
    at org.dozer.MappingProcessor.mapCustomObject(MappingProcessor.java:489)
    at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:446)
    at org.dozer.MappingProcessor.addOrUpdateToList(MappingProcessor.java:776)
    at org.dozer.MappingProcessor.addOrUpdateToList(MappingProcessor.java:850)
    at org.dozer.MappingProcessor.mapListToList(MappingProcessor.java:686)
    at org.dozer.MappingProcessor.mapCollection(MappingProcessor.java:541)
    at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:434)
    at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342)
    at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:187)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:124)
    at org.dozer.MappingProcessor.map(MappingProcessor.java:119)
    at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120)
    at com.usamp.biddingtool.model.service.impl.DozerTest.testCopyOther(DozerTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

因此,似乎Dozer正在尝试创建集合中使用的实际类型的实例,而类型只是一个接口。由于无法实例化接口,因此会产生错误。

我见过其他人问过这个问题,但并没有真正得到任何具体答案。这个问题有什么解决方案吗?

感谢。 -AP_

2 个答案:

答案 0 :(得分:2)

您必须向Dozer提供有关Base实施的提示。否则它将尝试实例化接口,这是不可能的。 <mapping> <class-a>Wrapper</class-a> <class-b>Wrapper</class-b> <field> <a>bases</a> <b>bases</b> <a-hint>BaseOne,BaseTwo</a-hint> <b-hint>BaseOne,BaseTwo</b-hint> </field> </mapping>

http://dozer.sourceforge.net/documentation/baseattributes.html

替代(更新): <mapping> <class-a>BaseOne</class-a> <class-b>BaseOne</class-b> </mapping> <mapping> <class-a>BaseTwo</class-a> <class-b>BaseTwo</class-b> </mapping>

答案 1 :(得分:0)

一种解决方案可以是创建custom DozerConverter。在转换器方法中,您可以在运行时检查具体实例类型。