2015-10-25 11 views
6

У меня возникло странное исключение ClassCastException при сопоставлении сущности с DTO с Orika в образце Spring Boot webapp, над которым я работаю. Я получаю исключение, когда я пытаюсь выполнить сопоставление во развернутом приложении во встроенном Tomcat, но я могу сделать отображение просто отлично в контексте теста JUnit. Это есть соответствующие классы (они все очень просто):Orika ClassCastException in Spring Boot webapp

JPA лицо:

@Entity 
public class Position { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 
    private String name; 
    // getters/setters... 
} 

DTO:

контроллер
public class PositionDto { 

    private Integer id; 
    private String name; 
    // getters/setters... 
} 

отдых:

@RestController 
public class PositionController { 

    @Autowired 
    private PositionService positionService; 

    @RequestMapping("/position") 
    public PositionDto get() { 
     final PositionDto positionDto = positionService.getPosition(1); 
     return positionDto; 
    } 
} 

Класс обслуживания:

@Service 
public class PositionServiceImpl implements PositionService { 

    @Autowired 
    private PositionRepository positionRepository; 
    @Autowired 
    private OrikaBeanMapper mapper; 

    @Transactional(readOnly = true) 
    @Override 
    public PositionDto getPosition(final Position.ID id) { 
     // This returns a populated Position object with id=1 and name = "Creator" 
     final Position position = positionRepository.findOne(id.getId()); 
     // This is where the mapping occurs 
     return mapper.map(position, PositionDto.class); 
    } 
} 

класс OrikaBeanMapper:

@Component 
public class OrikaBeanMapper extends ConfigurableMapper implements ApplicationContextAware {   

    public OrikaBeanMapper() { 
     super(false); 
    } 

    @Override 
    protected void configureFactoryBuilder(final DefaultMapperFactory.Builder factoryBuilder) { 
     factoryBuilder.mapNulls(false); 
    } 
    // Omitted non-important methods 

} 

И это StackTrace из ClassCastException:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is ma.glasnost.orika.MappingException: While attempting the following mapping: 
sourceClass = class com.dlizarra.startuphub.position.Position 
destinationType = com.dlizarra.startuphub.position.PositionDto 
resolvedStrategy = InstantiateAndUseCustomMapperStrategy<Position, PositionDto> {customMapper: GeneratedMapper<Position, PositionDto> {usedConverters: [], usedMappers: [], usedMapperFacades: [], usedTypes: [] }, unenhancer: [email protected], objectFactory: DefaultConstructorObjectFactory<PositionDto>} 
Error occurred: java.lang.ClassCastException: com.dlizarra.startuphub.position.Position cannot be cast to com.dlizarra.startuphub.position.Position 
-----begin dump of current state----------------------------- 
Registered object factories: 1 (approximate size: 110.8 kB) 
    [PositionDto] : {Position=DefaultConstructorObjectFactory<PositionDto>} 
------------------------------------------------------------------------------- 
Registered mappers: 1 (approximate size: 17,643.0 kB) 
    [0] : GeneratedMapper<Position, PositionDto> {usedConverters: [], usedMappers: [], usedMapperFacades: [], usedTypes: [] } 
------------------------------------------------------------------------------- 
Registered concrete types: 5 (approximate size: 294.3 kB) 
    [interface java.util.List] : ArrayList<Object> 
    [interface java.util.Set] : LinkedHashSet<Object> 
    [interface java.util.Collection] : ArrayList<Object> 
    [interface java.util.Map] : LinkedHashMap<Object, Object> 
    [interface java.util.Map$Entry] : MapEntry<Object, Object> 
    ------------------------------------------------------------------------------- 

Resolved strategies: 1 (approximate size: 19,850.8 kB) 

{source: Position, dest: PositionDto, in-place:false}: InstantiateAndUseCustomMapperStrategy<Position, PositionDto> 
{customMapper: GeneratedMapper<Position, PositionDto> {usedConverters: [], usedMappers: [], usedMapperFacades: [], usedTypes: [] }, unenhancer: 
[email protected], objectFactory: 
DefaultConstructorObjectFactory<PositionDto>} 
------------------------------------------------------------------------------- 
Unenhance strategy: [email protected] 
-----end dump of current state-------------------------------] with root cause 
java.lang.ClassCastException: com.dlizarra.startuphub.position.Position cannot be cast to com.dlizarra.startuphub.position.Position 
at ma.glasnost.orika.generated.Orika_PositionDto_Position_Mapper43322711137530$0.mapAtoB(Orika_PositionDto_Position_Mapper43322711137530$0.java) ~[orika-core-1.4.6.jar:na] 
at ma.glasnost.orika.impl.mapping.strategy.UseCustomMapperStrategy.map(UseCustomMapperStrategy.java:67) ~[orika-core-1.4.6.jar:na] 
at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:742) ~[orika-core-1.4.6.jar:na] 

Я действительно понятия не имею, что здесь происходит. Я не понимаю, куда он пытается отнести позицию в позицию. Это происходит с каждым классом entity/dto, а не только с позицией.

Я могу отобразить любой из этих классов без проблем, когда я тестирую модуль любым методом, он отлично работает, и все поля правильно отображаются, поэтому я не думаю, что это проблема конфигурации Orika. Исключение возникает только тогда, когда у меня есть webapp, развернутый во встроенном Tomcat, и метод сопоставления вызывается в рамках метода остаточного контроллера.

Это простое приложение Spring Boot, и это первая конечная точка отдыха, которую я написал в ней. Может быть, мне что-то не хватает в конфигурации (у меня есть @EnableAutoConfiguration, поэтому не так много, чтобы настроить), но я не могу догадаться, что делает Orika выбросить это исключение.

Любые идеи или подсказки о том, что может происходить здесь, будут очень оценены.

Спасибо!

+4

Вы используете инструменты Dev Spring Boot?Похоже, вы бьете [этот известный вопрос] (https://github.com/spring-projects/spring-boot/issues/3697). –

+0

Ничего себе это было тяжело, спасибо Энди. Да, я использую Dev Tools, Orika 1.4.6 и Boot 1.3.0 M5. Теперь я понимаю, что ClassCastException из Position to Position было связано с тем, что каждый класс загружается другим загрузчиком классов. Я вижу, что вы, ребята, работаете над решением, так как это происходит не только с Orika, но и с Orika ребята также решают проблему, и это может быть исправлено для 1.5. –

+0

@ AndyWilkinson и David Я мог бы дать вам поцелуй большого человека прямо сейчас. Я не уверен, сколько часов я потратил на это ... но я содрогнулся, чтобы подумать. отображение отлично работало в модульных тестах без кубиков в dev/live run. Я преследовал всевозможные другие красные сельди, пока не наткнулся на этот пост. cheers – wired00

ответ

4

Я только что понял, что есть обходной путь для этой ошибки, так как несколько месяцев назад уже с Spring Boot 1.4.0 (я считаю, что это эта версия), когда они представили возможность настроить Dev Tools через файл свойств.

Чтобы решить эту проблему, мы просто должны:

  1. Создать папку META-INF в src/main/resources.
  2. Создать spring-devtools.properties файл в нем.
  3. Добавить restart.include.orika=/orika-core.*\.jar в файл.

Как указано в Docs, то restart.include потянет в «перезагрузке» загрузчик классы любой банки, совпадающую с Regex. Поэтому мы включаем файл orika-core-1.4.6.jar.

+0

Это отлично сработало для меня, согласно этой проблеме github, надеюсь, ребята из orika могут это исправить. Следуйте этим шагам, чтобы точно перезапустить приложение> счастливые дни. – wired00

Смежные вопросы