2015-10-25 13 views
6

私が作業しているサンプルのSpring Boot webappでOrikaを使ってエンティティをDTOにマッピングする際に、奇妙なClassCastExceptionが発生しました。埋め込まれたTomcatの配備されたアプリケーションでマッピングを実行しようとすると例外が発生しますが、JUnitテストコンテキストでマッピングを正常に実行できます。これは、(彼らはすべての非常に単純です)関連のクラスがある:Spring Boot webappのOrika ClassCastException

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: [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] 

。私はポジションをポジションにキャストしようとしているところにはいない。これは、Positionだけでなく、すべてのエンティティ/ dtoクラスで発生します。

私はユニットテストの際に問題なくこれらのクラスをマップすることができます。完全に動作し、すべてのフィールドが正しくマップされるため、Orika構成の問題とは思われません。例外は、埋め込みTomcatにwebappをデプロイし、残りのコントローラメソッド内でマッピングメソッドが呼び出された場合にのみ発生します。

これはシンプルなSpring Bootアプリケーションであり、これが私が書いた最初の残りのエンドポイントです。たぶん私は設定で何かが不足している(私は@EnableAutoConfigurationを持っているので、それほど設定する必要はない)が、オリカがこの例外をスローしていることを推測することはできない。

ここで何が起こっているのかについてのヒントやヒントは非常に高く評価されます。

ありがとうございます!

+4

Spring BootのDevツールを使用していますか?あなたが[この既知の問題](https://github.com/spring-projects/spring-boot/issues/3697)に当たっているようです。 –

+0

これは厳しいものでした。Andyに感謝します。はい、私はDev Tools、Orika 1.4.6とBoot 1.3.0 M5を使用しています。今度は、位置から位置までのClassCastExceptionが、各クラスが別のクラスローダーによってロードされていることが原因であることを理解しています。 Orikaと一緒に発生するだけでなく、Orikaの人たちも問題に取り組んでいるし、1.5のために修正されるかもしれないので、皆さんが解決策に取り組んでいるのを見ることができます。 –

+0

@AndyWilkinsonとDavid私はあなたに今大きな男の子のキスを与えることができました。私はこれにどれくらいの時間を費やしたのか分かりません...しかし、私は考えるのが悲しいです。マッピングはdev/liveで単体テストではうまくいきませんでした。私はこのポストにつまずくまで、あらゆる種類の他の赤いシリングを追いかけていました。歓声 – wired00

答えて

4

数か月前にすでにSpring Boot 1.4.0(私はそれがこのバージョンだと思います)からDevool Toolsをプロパティファイルでカスタマイズする可能性を紹介して以来、このエラーの回避策があることに気付きました。 src/main/resourcesMETA-INFフォルダを作成します

  1. :に私たちは持ってこの問題を解決するために

  2. spring-devtools.propertiesファイルを作成します。
  3. restart.include.orika=/orika-core.*\.jarをファイルに追加します。

Docsで述べたように、restart.includeは「再起動」クラスローダに正規表現に一致するすべてのjarファイルをプルアップします。例えば、orika-core-1.4.6.jarファイルを含めています。

+0

これは完璧に働いていました。そのgithubの問題がうまくいけば、orikaの人はこれを修正できます。これらの手順に従って、アプリケーション>幸せな日々を正確に再起動します。 – wired00