2015-10-25 26 views
6

Ho una strana ClassCastException mentre mappo un'entità a un DTO con Orika in una webapp di esempio Spring Boot su cui sto lavorando. Ottengo l'eccezione quando tento di eseguire la mappatura sull'app distribuita in Tomcat incorporato, ma posso eseguire correttamente la mappatura in un contesto di test JUnit. Questo sono le classi interessate (sono tutti molto semplici):Orika ClassCastException in Spring Boot webapp

JPA entità:

@Entity 
public class Position { 

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

DTO:

regolatore
public class PositionDto { 

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

Riposo:

@RestController 
public class PositionController { 

    @Autowired 
    private PositionService positionService; 

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

Classe di servizio:

@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); 
    } 
} 

classe 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 

} 

E questo è lo StackTrace del 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] 

ho veramente idea di cosa sta succedendo qui. Non capisco dove sta provando a lanciare Posizione-posizione. Questo succede con ogni entità/classe dto, non solo con la posizione.

Non riesco a mappare nessuna di queste classi senza problemi quando eseguo un test di unità su qualsiasi metodo, funziona perfettamente e tutti i campi vengono mappati correttamente, quindi non penso che sia un problema di configurazione di Orika. L'eccezione si verifica solo quando ho installato il webapp in Tomcat incorporato e il metodo di mapping viene chiamato all'interno del metodo rest controller.

È una semplice applicazione Spring Boot e questo è il primo endpoint di riposo che ho scritto. Forse mi manca qualcosa nella configurazione (ho @EnableAutoConfiguration quindi non c'è molto da configurare), ma non posso indovinare che cosa sta facendo Orika lanciare questa eccezione.

Qualsiasi idea o suggerimento su ciò che potrebbe accadere qui sarebbe molto apprezzato.

Grazie!

+4

Stai utilizzando gli strumenti di sviluppo di Spring Boot?Sembra che tu stia colpendo [questo noto problema] (https://github.com/spring-projects/spring-boot/issues/3697). –

+0

Wow, questo è stato un duro, grazie Andy. Sì, sto usando Dev Tools, Orika 1.4.6 e Boot 1.3.0 M5. Ora capisco che ClassCastException dalla posizione alla posizione è dovuto al fatto che ogni classe viene caricata da un classloader diverso. Vedo che vi state lavorando su una soluzione poiché non si verifica solo con Orika e anche i ragazzi di Orika stanno affrontando il problema e potrebbero essere risolti per 1.5. –

+0

@AndyWilkinson e David Potrei darti un bacio da grande uomo in questo momento. Non sono sicuro di quante ore ho passato su questo ... ma rabbrividisco a pensare. la mappatura ha funzionato perfettamente nei test unitari senza dadi in dev/live run. Stavo dando la caccia a tutti i tipi di altre falsità finché non sono incappato in questo post. evviva – wired00

risposta

4

Ho appena realizzato che c'è un rimedio per questo errore da alcuni mesi fa con Spring Boot 1.4.0 (credo sia questa versione), quando hanno introdotto la possibilità di personalizzare Dev Tools tramite un file di proprietà.

per risolvere questo problema non ci resta che:

  1. Creare una cartella META-INF in src/main/resources.
  2. Creare il file spring-devtools.properties in esso.
  3. Aggiungi restart.include.orika=/orika-core.*\.jar al file.

Come indicato nella Docs, il restart.include tirerà su nel classloader 'restart' qualsiasi vaso corrispondente all'espressione regolare. Quindi stiamo includendo il file orika-core-1.4.6.jar per esempio.

+0

Questo ha funzionato perfettamente per me, come da quel problema github, spero che i ragazzi di orika possano risolvere il problema. Segui questi passaggi per ricominciare da capo l'applicazione> giorni felici. – wired00