1

I am getting class cast exception while trying to Index the entity through Hibernate5 Search API on Websphere 8.5.5.10. The transactions are being managed by Spring Transaction. The document entities are getting indexed properly on local tomcat but not on WebSphere.

I have created a RESTFUl web service call to index the entities.

Spring 4.2 Hibernate Core 5.0.11.Final Hibernate Search 5.5.5.Final

Here is my config file

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="datasource" />
    <property name="packagesToScan">
        <list>
            <value>model</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">false</prop>
            <prop key="hibernate.default_schema">dev</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.search.default.directory_provider">filesystem</prop>
            <prop key="hibernate.search.default.indexBase">/var/lucene/indexes</prop>

        </props>
    </property>

</bean>


<bean id="transactionManager"
    class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

And the stack trace in websphere app logs:-

HSEARCH000058: HSEARCH000116: Unexpected error during MassIndexer operation org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformException: Could not obtain WebSphere TransactionManager at org.hibernate.engine.transaction.jta.platform.internal.WebSphereJtaPlatform.locateTransactionManager(WebSphereJtaPlatform.java:66) at org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform.retrieveTransactionManager(AbstractJtaPlatform.java:87) at org.hibernate.search.batchindexing.impl.BatchTransactionalContext.lookupTransactionManager(BatchTransactionalContext.java:53) at org.hibernate.search.batchindexing.impl.BatchTransactionalContext.(BatchTransactionalContext.java:42) at org.hibernate.search.batchindexing.impl.BatchIndexingWorkspace.runWithErrorHandler(BatchIndexingWorkspace.java:118) at org.hibernate.search.batchindexing.impl.ErrorHandledRunnable.run(ErrorHandledRunnable.java:32) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:483) at java.util.concurrent.FutureTask.run(FutureTask.java:274) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1157) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:627) at java.lang.Thread.run(Thread.java:798) Caused by: java.lang.ClassCastException: com.ibm.ws.tx.jta.TranManagerSet incompatible with javax.transaction.TransactionManager at org.hibernate.engine.transaction.jta.platform.internal.WebSphereJtaPlatform.locateTransactionManager(WebSphereJtaPlatform.java:63)

I am not sure what am I doing wrong here. Apart from Index Webservice call, other REST webservices are running fine and my UI is populating as expected.

Any help will be much appreciated.

creed
  • 51
  • 1
  • 5

3 Answers3

4

We ran into this issue.

Issue: If we use a hibernate version that uses JPA 2.1 (> hibernate version 4.3), it will conflict with older versions of websphere (versions 7, 8.5 without the JPA 2.1 fix packs). Specifically the exception you would see is this:

nested exception is java.lang.NoSuchMethodError: javax/persistence/Table.indexes()[Ljavax/persistence/Index;

Solution 1: One way to resolve this issue is setting the classloader to parent_last so that JPA 2.1 that ships with hibernate will be used. However, you will run into other problems like the ones mentioned above.

  1. Conflict with TransactionManager that ships with hibernate, Exception:

    java.lang.ClassCastException: com.ibm.ws.tx.jta.TranManagerSet incompatible with javax.transaction.TransactionManager

    This can be solved by excluding the following jar (example maven configuration for the hibernate dependency) that causes the conflict:

    <exclusion>
        <artifactId>jboss-transaction-api_1.2_spec</artifactId>
        <groupId>org.jboss.spec.javax.transaction</groupId>
    </exclusion>
    
  2. Conflict with xml-apis.jar that ships with hibernate resulting in the exception:

    javax.xml.parsers.FactoryConfigurationError: Provider for javax.xml.parsers.DocumentBuilderFactory cannot be found

    This can be resolved by excluding the xml-apis.jar from hibernate dependency like so:

    <exclusion>
        <artifactId>xml-apis</artifactId>
        <groupId>xml-apis</groupId>
    </exclusion>
    

Solution 2:
Use a custom PersistenceProviderResolver so that the Websphere classes do not interfere with Hibernate:

https://stackoverflow.com/a/37354979/5150013

code4kix
  • 3,937
  • 5
  • 29
  • 44
1

According to this article, this is a conflict between 2 different versions of java.transaction packages (one is in websphere, one in GemFire.jar, a lib deployed with websphere).

It also suggests a fix :

Drop the package javax.transaction from GemFire.jar: zip -d gemfire.jar javax/transaction/*

Hope this helps.

Benoit
  • 5,118
  • 2
  • 24
  • 43
  • Thanks for the help but my WebSphere settings are already set to : class Loader - parent_last , War Class - "Class loader for each WAR file in application" – creed Dec 02 '16 at 21:54
  • The javax.transaction.TransactionManager is a platform interface: changing the class loader options will not help. You have to make sure that your application does not include any transitive dependency which might conflict. – Sanne Dec 05 '16 at 11:00
  • Then you should try the first solution, hack the `GemFire.jar`. @ Sanne : thanks for the comment. I will update my solution accordingly. – Benoit Dec 05 '16 at 11:07
  • @Sanne I have only JTA 1.1 dependency in my classpath. The problem is happening when I try to index the entities on WebSphere. – creed Dec 05 '16 at 17:00
  • @Benoit I don't have any GemFire.jar in my application classpath. I am not sure if i perfectly understood your comment. – creed Dec 05 '16 at 17:01
  • @creed Forget about GemFire.jar, it must be another jar. As pointed out by Sanne, 2 versions of javax.transactions packages are conflicting. As it is a platform interface, you have to remove it from your own jars. If you happen to use both maven and eclipse for your build, there is a power tool to detect which jar import specific package. – Benoit Dec 06 '16 at 08:44
1

From SpringBoot version 2.2.0.RELEASE, there is transaction manager api used from jakarta. In case you want to make it work just exclude

<dependency>
    <groupId>jakarta.transaction</groupId>
    <artifactId>jakarta.transaction-api</artifactId>
</dependency>

from

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

The basic thought is to have only one transaction manager. Here we are removing the one being provided from the sprintboot-jpa