Search code examples
jbossspring-data-jpaclasscastexceptionspring-wsclassloading

ClassCastException with spring-data-jpa


I'm working with Spring Web Services and Spring JPA Data.

I have three projects:

  • doc-ws. Web application that it's the endpoint of my documental web services.
  • sign-ws. Web application that it's the endpoint of my sign web services.
  • data-ws. Jar module with all the jpa entities (@Entity), spring jpa repositories (@Repository) and spring services classes (@Services).

Doc-ws and sign-ws has a dependence with data-ws, so a data-ws.jar is included in doc-ws.war and sign-ws.war.

When I deploy doc-ws web application alone, all the web services tests works fine. When I deploy sign-ws web application alone, all the web services tests works fine. But when I deploy both web applications together in the same Jboss EAP 7.1, I'm getting ClassCastExceptions when I exectute the web services tests.

java.lang.ClassCastException: com.ieci.mugeju.data.entity.IdocConfiguration cannot be cast to com.ieci.mugeju.data.entity.IdocConfiguration

    List<IdocConfiguration> properties = idocConfigurationRepository.findAll();   <-- works fine

    for (IdocConfiguration property: properties)    <-- Here throws the ClassCastException
    {
       .... // CODE
    }

Exception message reference the same jpa entity (com.ieci.mugeju.data.entity.IdocConfiguration), so I don't understand why this exception is being throwed.

It must be a classloading issue between both web applications, but I'm not sure.

I'm working with JBoss EAP 7.1, spring-data-jpa 2.0.5, eclipseling 2.6.4, spring-ws-core 3.0.1.

Any idea why I'm getting this exception? How could I solve?

Thanks


Solution

  • I discovered what the problem was. When I defined the 'entityManagerFactory', I was not setting the property called 'persistenceUnitName'. Then when the persistence context was created, it was created with the name 'default' in both web projects.

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter" ref="jpaAdapter" />
        <property name="jpaDialect" ref="jpaDialect"/>      
        <property name="packagesToScan" value="com.ieci.mugeju.data.entity" />              
        ...
    </bean>
    

    I don't know why but 'find repository methods' of second project return jpa entity classes defined in first project classloader. Very strange behaviour, I expected every web application using its own classloader, and isolated one from each other.

    If I set a persistenceUnitName for every project, then everything works fine, and every web application uses its own classloader.

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter" ref="jpaAdapter" />
        <property name="jpaDialect" ref="jpaDialect"/>      
        <property name="packagesToScan" value="com.ieci.mugeju.data.entity" />      
        <property name="persistenceUnitName" value="${spring.application.name}" />
        ...
    </bean>