Ich habe eine seltsame ClassCastException beim Zuordnen einer Entität zu einem DTO mit Orika in einer Beispiel-Spring Boot-Webapp ich arbeite an. Ich erhalte die Ausnahme, wenn ich versuche, das Mapping auf der implementierten App im eingebetteten Tomcat durchzuführen, aber ich kann das Mapping in einem JUnit-Testkontext gut machen. Dies sind die entsprechenden Klassen (sie alle sind sehr einfach):Orika ClassCastException im Frühjahr Boot webapp
JPA-Entität:
@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...
}
Ruhe Controller:
@RestController
public class PositionController {
@Autowired
private PositionService positionService;
@RequestMapping("/position")
public PositionDto get() {
final PositionDto positionDto = positionService.getPosition(1);
return positionDto;
}
}
Service-Klasse:
@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 Klasse:
@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
}
Und das ist die Stacktrace des Classcast:
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]
ich wirklich keine Ahnung, was hier los ist. Ich bekomme nicht, wo es Position in Position zu werfen versucht. Dies geschieht bei jeder Entity/Dto-Klasse, nicht nur bei Position.
Ich kann jede dieser Klassen ohne Probleme zuordnen, wenn ich Unit-Tests jede Methode, es funktioniert perfekt und alle Felder korrekt zugeordnet werden, so glaube ich nicht, es ist ein Orika-Konfigurationsproblem. Die Ausnahme tritt nur auf, wenn ich die Webanwendung im eingebetteten Tomcat bereitgestellt habe und die Mapping-Methode innerhalb der Rest-Controller-Methode aufgerufen wird.
Es ist eine einfache Spring Boot-Anwendung und das ist der erste Rest Endpunkt, den ich darin geschrieben habe. Vielleicht fehlt mir etwas in der Konfiguration (ich habe @EnableAutoConfiguration, also gibt es nicht so viel zu konfigurieren), aber ich kann nicht erraten, was Orika diese Ausnahme verursacht.
Irgendwelche Ideen oder Hinweise darüber, was hier geschehen könnte, würden sehr geschätzt werden.
Danke!
Verwenden Sie Spring Boot Dev Tools?Es klingt, als würdest du [dieses bekannte Problem] treffen (https://github.com/spring-projects/spring-boot/issues/3697). –
Wow das war ein harter, danke Andy. Ja, ich verwende Dev Tools, Orika 1.4.6 und Boot 1.3.0 M5. Jetzt verstehe ich, dass die ClassCastException von Position zu Position von jeder Klasse verursacht wurde, die von einem anderen Klassenlader geladen wurde. Ich kann sehen, dass ihr an einer Lösung arbeitet, da sie nicht nur bei Orika auftritt und die Orika-Jungs auch das Problem angehen und es könnte für 1.5 behoben werden. –
@AndyWilkinson und David Ich könnte dir jetzt einen großen Mann küssen. Ich bin mir nicht sicher, wie viele Stunden ich damit verbracht habe ... aber ich schaudere beim Nachdenken. Mapping funktionierte perfekt in Unit Tests keine Würfel in dev/Live-Lauf. Ich jagte alle möglichen anderen roten Heringe, bis ich auf diesen Posten stolperte. Prost – wired00