Spring Boot webapp 中的 Orika ClassCastException
Orika ClassCastException in Spring Boot webapp
我在示例中使用 Orika 将实体映射到 DTO 时遇到奇怪的 ClassCastException Spring 我正在处理的引导 webapp。当我尝试在嵌入式 Tomcat 中对部署的应用程序进行映射时出现异常,但我可以在 JUnit 测试上下文中很好地进行映射。这是相关的classes(它们都很简单):
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;
}
}
服务class:
@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 class:
@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: ma.glasnost.orika.unenhance.BaseUnenhancer@73c3e10e, 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:
ma.glasnost.orika.unenhance.BaseUnenhancer@73c3e10e, objectFactory:
DefaultConstructorObjectFactory<PositionDto>}
-------------------------------------------------------------------------------
Unenhance strategy: ma.glasnost.orika.unenhance.BaseUnenhancer@73c3e10e
-----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[=16=].mapAtoB(Orika_PositionDto_Position_Mapper43322711137530[=16=].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]
我真的不知道这里发生了什么。我不知道它试图将 Position 转换为 Position 的位置。每个 entity/dto class 都会发生这种情况,而不仅仅是位置。
当我对任何方法进行单元测试时,我可以毫无问题地映射任何这些 classes,它工作完美并且所有字段都正确映射,所以我认为这不是 Orika 配置问题.仅当我在嵌入式 Tomcat 中部署了 webapp 并且在其余控制器方法中调用了映射方法时才会发生异常。
这是一个简单的 Spring 引导应用程序,这是我在其中编写的第一个休息端点。也许我在配置中遗漏了一些东西(我有 @EnableAutoConfiguration 所以没有那么多配置),但我无法猜测是什么让 Orika 抛出这个异常。
任何关于这里可能发生的事情的想法或提示都将不胜感激。
谢谢!
我刚刚意识到这个错误有一个解决方法,因为几个月前已经有了 Spring Boot 1.4.0(我相信是这个版本),当时他们引入了通过属性自定义开发工具的可能性文件。
要解决这个问题,我们只需要:
- 在
src/main/resources
中创建一个 META-INF
文件夹。
- 在其中创建
spring-devtools.properties
文件。
- 将
restart.include.orika=/orika-core.*\.jar
添加到文件中。
如 Docs 中所述,restart.include
将拉入 'restart' 类加载器任何匹配 Regex 的 jar。例如,我们包括 orika-core-1.4.6.jar
文件。
我在示例中使用 Orika 将实体映射到 DTO 时遇到奇怪的 ClassCastException Spring 我正在处理的引导 webapp。当我尝试在嵌入式 Tomcat 中对部署的应用程序进行映射时出现异常,但我可以在 JUnit 测试上下文中很好地进行映射。这是相关的classes(它们都很简单):
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;
}
}
服务class:
@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 class:
@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: ma.glasnost.orika.unenhance.BaseUnenhancer@73c3e10e, 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:
ma.glasnost.orika.unenhance.BaseUnenhancer@73c3e10e, objectFactory:
DefaultConstructorObjectFactory<PositionDto>}
-------------------------------------------------------------------------------
Unenhance strategy: ma.glasnost.orika.unenhance.BaseUnenhancer@73c3e10e
-----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[=16=].mapAtoB(Orika_PositionDto_Position_Mapper43322711137530[=16=].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]
我真的不知道这里发生了什么。我不知道它试图将 Position 转换为 Position 的位置。每个 entity/dto class 都会发生这种情况,而不仅仅是位置。
当我对任何方法进行单元测试时,我可以毫无问题地映射任何这些 classes,它工作完美并且所有字段都正确映射,所以我认为这不是 Orika 配置问题.仅当我在嵌入式 Tomcat 中部署了 webapp 并且在其余控制器方法中调用了映射方法时才会发生异常。
这是一个简单的 Spring 引导应用程序,这是我在其中编写的第一个休息端点。也许我在配置中遗漏了一些东西(我有 @EnableAutoConfiguration 所以没有那么多配置),但我无法猜测是什么让 Orika 抛出这个异常。
任何关于这里可能发生的事情的想法或提示都将不胜感激。
谢谢!
我刚刚意识到这个错误有一个解决方法,因为几个月前已经有了 Spring Boot 1.4.0(我相信是这个版本),当时他们引入了通过属性自定义开发工具的可能性文件。
要解决这个问题,我们只需要:
- 在
src/main/resources
中创建一个META-INF
文件夹。 - 在其中创建
spring-devtools.properties
文件。 - 将
restart.include.orika=/orika-core.*\.jar
添加到文件中。
如 Docs 中所述,restart.include
将拉入 'restart' 类加载器任何匹配 Regex 的 jar。例如,我们包括 orika-core-1.4.6.jar
文件。