2015-10-25 29 views
6

我有一個奇怪的ClassCastException,而實體映射到一個DTO與Orika在示例春季啓動webapp我正在努力的DTO。當我嘗試對嵌入式Tomcat中的已部署應用程序執行映射時,發現異常,但我可以在JUnit測試上下文中完成映射。這是相關類(他們都是很簡單):Orika ClassCastException在春季啓動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 

} 

這是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] 

我真的不知道是怎麼回事。我不知道它在試圖將位置轉換爲位置。這發生在每個實體/ dto類,而不僅僅是Position。

我可以映射任何沒有問題這些類的時候,我的單元測試的任何方法,它完美的作品和所有的領域得到正確映射,所以我不認爲這是一個Orika配置問題。只有當我將webapp部署在嵌入式Tomcat中並且映射方法在其餘控制器方法中被調用時纔會發生異常。

這是一個簡單的Spring Boot應用程序,這是我寫的第一個休息端點。也許我在配置中缺少一些東西(我有@EnableAutoConfiguration,所以沒有太多的配置),但我無法猜測是什麼讓Orika拋出這個異常。

什麼可能會發生在這裏的任何想法或提示將非常讚賞。

謝謝!

+4

您是否使用Spring Boot的開發工具?這聽起來像你擊中[這個已知的問題](https://github.com/spring-projects/spring-boot/issues/3697)。 –

+0

哇這是一個艱難的,謝謝安迪。是的,我正在使用開發工具,Orika 1.4.6和Boot 1.3.0 M5。現在我明白從位置到位置的ClassCastException是由於每個類由不同的類加載器加載。我可以看到你們正在研究一種解決方案,因爲它不僅與Orika一起發生,而且Orika傢伙也在解決這個問題,它可能會被固定爲1.5。 –

+0

@AndyWilkinson和David我現在可以給你一個大男人的吻。我不確定我花了多少小時......但是我不寒而慄。映射在單元測試中完美工作,沒有骰子在開發/實時運行。我正在追逐各種其他紅鯡魚,直到我偶然發現這篇文章。歡呼聲 – wired00

回答

4

我才意識到有此錯誤的解決方法,因爲幾個月前已經與Spring引導1.4.0(我相信這是這個版本),當他們推出定製開發工具通過一個屬性文件的可能性。

爲了解決這個問題,我們只需要:

  1. src/main/resources創建META-INF文件夾。
  2. 在其中創建spring-devtools.properties文件。
  3. restart.include.orika=/orika-core.*\.jar添加到文件中。

正如Docs所述,restart.include將拉起到「重啓」的類加載器的任何廣口瓶的匹配的正則表達式。例如,我們包含orika-core-1.4.6.jar文件。

+0

這對我來說非常合適,因爲github問題希望orika傢伙能夠解決這個問題。按照這些步驟準確地重新開始您的應用程序>快樂的日子 – wired00