ModelMapper не может отображать родительский метод с именем

Я тестировался на ModelMapper 0.7.5.

Если модель имеет следующие условия, то ModelMapper не может их не отображать.

  • имя метода «родительский» и возвращает собственный класс
  • имя метода — «parentPath» и возвращаемая строка

Код теста

public static class SomeModelMapper extends ModelMapper {
    public void init() {
        getConfiguration().setMatchingStrategy(MatchingStrategies.STANDARD);
    }
}

@Data
public static class Dto1 {
    private Dto1 another;
    private String anothorPath;
}

@Data
public static class Dto2 {
    private Dto2 parent;
    private String parentPath;
}

@Test
public void testMapping() {
    SomeModelMapper mapper = new SomeModelMapper();
    mapper.init();
    Map map = new HashMap<>();
    map.put("anothorPath", "x");

    Dto1 dto1 = mapper.map(map, Dto1.class);
    assertThat(dto1.getAnothorPath(), is("x")); // success

    map.clear();
    map.put("parentPath", "y");
    Dto2 dto2 = mapper.map(map, Dto2.class); // failed
    assertThat(dto2.getParentPath(), is("y"));
}

сообщение об ошибке

org.modelmapper.MappingException: ModelMapper mapping errors:

1) Error mapping java.util.HashMap to com.semogyo.api.web.mapper.Object2ObjectMapperTest$Dto2

1 error

    at org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:374)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:69)
    at org.modelmapper.ModelMapper.mapInternal(ModelMapper.java:497)
    at org.modelmapper.ModelMapper.map(ModelMapper.java:340)
    at com.semogyo.api.web.mapper.Object2ObjectMapperTest.testMapping(Object2ObjectMapperTest.java:202)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    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.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    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.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:

1) Failed to set value 'Object2ObjectMapperTest.Dto2(parent=null, parentPath=null)' on com.semogyo.api.web.mapper.Object2ObjectMapperTest$Dto2.setParentPath()

1 error
    at org.modelmapper.internal.Errors.toMappingException(Errors.java:258)
    at org.modelmapper.internal.PropertyInfoImpl$MethodMutator.setValue(PropertyInfoImpl.java:118)
    at org.modelmapper.internal.MappingEngineImpl.setDestinationValue(MappingEngineImpl.java:249)
    at org.modelmapper.internal.MappingEngineImpl.propertyMap(MappingEngineImpl.java:180)
    at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:131)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:101)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:60)
    ... 30 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.modelmapper.internal.PropertyInfoImpl$MethodMutator.setValue(PropertyInfoImpl.java:116)
    ... 35 more

Почему я не могу использовать «родительское» имя метода?


person user3196649    schedule 04.06.2016    source источник


Ответы (1)


Вы можете использовать parent как хотите, но не в этом случае. Если вы измените родительское имя свойства на другой токен, он сработает (например, отец). Но попробуйте изменить свой другой пример Dto1 следующим образом и посмотрите, что произойдет: (свойство anothor на другое):

@Data
public static class Dto1 {
    private Dto1 another;
    private String anotherPath;
}

И ваш HashMap (anothorPath -> AnotherPath):

Map<String, String> map = new HashMap<>();
map.put("anotherPath", "x");
Dto1 dto1 = mapper.map(map, Dto1.class);

Бывает такая же ошибка:

Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:

1) Failed to set value 'Test.Dto1(another=null, anotherPath=null)' on com.example.Test$Dto1.setAnotherPath()
... same trace error

Почему? Просто, как и ваш образец, он генерирует бесконечный цикл.

  1. ModelMapper отображает строку parentPath
  2. ModelMapper сопоставляет родителя DTO2 -> String ParentPath.
  3. ModelMapper сопоставляет родителя DTO2 -> родитель DTO2 -> String parentPath
  4. ModelMapper отображает родитель DTO2 -> родитель DTO2 -> родитель DTO2 -> String parentPath
  5. ....Бесконечный цикл....Кажется, это не остановится...

Позвольте мне объяснить вам, почему. ModelMapper выглядит как аксессор String parentPath, и его можно сопоставить, затем он пытается сопоставить Dto2 parent и так далее... Если вы присвоите другое имя Dto2, он не будет пытаться сопоставить Dto2, и цикл не будет сгенерирован.

Примеры

Дело 1

Представьте, что ваши классы были такими:

@Data
public static class Dto1 {
    private Dto2 another;
    private String parentPath;      
    
}

@Data
public static class Dto2 {
    private Dto1 parent;
    private String parentPath;
    
}

Выход будет Test.Dto2(parent=Test.Dto1(another=null, parentPath=y), parentPath=y). Он будет отображать как String parentDto1, так и Dto2.

Случай 2

Но в случае, если ваши классы были похожи на следующие:

@Data
public static class Dto1 {
    private Dto2 parent;
    private String parentPath;      
}

@Data
public static class Dto2 {
    private Dto1 parent;
    private String parentPath;
}

Опять выдает ошибку, тот же бесконечный цикл.

Вывод

Этот вид отображений не поддерживается, возможно, автор подумал, что так будет лучше, чтобы быть последовательным, я не знаю.

person Pau    schedule 31.07.2016