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:
regolatorepublic 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!
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). –
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. –
@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