【问题标题】:Orika ClassCastException in Spring Boot webappSpring Boot webapp 中的 Orika ClassCastException
【发布时间】:2015-10-25 00:47:36
【问题描述】:

在我正在处理的示例 Spring Boot webapp 中使用 Orika 将实体映射到 DTO 时,我遇到了一个奇怪的 ClassCastException。当我尝试在嵌入式 Tomcat 中对已部署的应用程序进行映射时出现异常,但我可以在 JUnit 测试上下文中很好地进行映射。这是相关的类(它们都很简单):

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: 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$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 类都会发生这种情况,而不仅仅是位置。

当我对任何方法进行单元测试时,我可以毫无问题地映射任何这些类,它运行良好并且所有字段都被正确映射,所以我认为这不是 Orika 配置问题。仅当我将 webapp 部署在嵌入式 Tomcat 中并且在 rest 控制器方法中调用映射方法时才会发生异常。

这是一个简单的 Spring Boot 应用程序,这是我在其中编写的第一个 rest 端点。也许我在配置中遗漏了一些东西(我有 @EnableAutoConfiguration 所以没有那么多配置),但我猜不出是什么让 Orika 抛出这个异常。

任何关于这里可能发生的事情的想法或提示都将非常感激。

谢谢!

【问题讨论】:

  • 你在使用 Spring Boot 的开发工具吗?听起来你在打this known issue
  • 哇,这是一个艰难的过程,谢谢安迪。是的,我正在使用开发工具、Orika 1.4.6 和 Boot 1.3.0 M5。现在我了解从 Position 到 Position 的 ClassCastException 是由于每个类都由不同的类加载器加载。我可以看到你们正在研究解决方案,因为它不仅发生在 Orika,而且 Orika 的人也在解决这个问题,它可能会在 1.5 中得到修复。
  • @AndyWilkinson 和 David 我现在可以给你们两个大男人的吻。我不知道我花了多少时间在这上面……但我不禁想到。映射在单元测试中完美运行,在开发/实时运行中没有骰子。我一直在追逐各种其他的红鲱鱼,直到我偶然发现了这篇文章。干杯
  • 很高兴你解决了这个问题,wired00!它在测试中运行良好的事实确实非常令人困惑。谢天谢地,Spring Boot 团队很棒,他们通过属性文件增加了对开发工具调整的支持 :)

标签: java spring spring-mvc spring-boot orika


【解决方案1】:

我刚刚意识到这个错误有一个解决方法,因为几个月前 Spring Boot 1.4.0(我相信是这个版本),当时他们引入了通过属性文件自定义开发工具的可能性。

要解决这个问题,我们只需要:

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

Docs 中所述,restart.include 会将任何匹配正则表达式的 jar 拉入“重新启动”类加载器。例如,我们将包含orika-core-1.4.6.jar 文件。

【讨论】:

  • 这对我来说非常有效,根据那个 github 问题,希望 orika 家伙可以解决这个问题。按照这些步骤精确地重新启动您的应用程序 > 快乐的日子。
  • 这让我省了一大堆头痛 :) 我已经找了几个小时了。谢谢!
猜你喜欢
  • 2020-02-27
  • 2016-10-05
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 2019-09-09
  • 2015-06-24
  • 2011-08-18
相关资源
最近更新 更多