While deploying an EAR, I kept getting this error when instantiating my Spring beans which happen to use Hibernate to talk to the database:
java.lang.ClassCastException: org.jboss.tm.TxManager
at org.hibernate.transaction.JNDITransactionManagerLookup.getTransactionManager(JNDITransactionManagerLookup.java:23)
at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:302)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1176)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:825)
Of course, good old ClassCastException doesn't tell me what class it expected, only what class it got. From looking at the javadocs, its expecting a javax.transaction.TransactionManager. However, org.jboss.tm.TxManager does, in fact, implement that interface.
So what gives? Well, its going to be a classloader issue. Again, ClassCastException (or most likely the caller) fails to realize that a class's name isn't enough to uniquely identify a class. The classloader that loads it is very important.
Given that I'm using Maven2, I figured that I must be including a copy of javax.transaction.TxManager somewhere.
This command will list the contents of all jars:
find -name '*.jar' -exec unzip -l '{}' \;
Redirect that to a text file, then grep for javax/transaction/TransactionManager
I found I was bundling jta-1.0.1B.jar in my ear. How did that get there? Transitive dependencies, of course. I didn't have to guess too hard as to who might be including that: Hibernate. Now, I thought I was already exlcuding the jta dependency. Turns out I'd only done it in a sub-project. I decided to fix it for all hibernate dependencies in my project by adding it in the parent pom.xml:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.1.3</version>
<exclusions>
<!--
This is container-provided; we don't need the dependency here;
In fact, java.lang.ClassCastException: org.jboss.tm.TxManager may occur if we
accidentally include a jta jar
-->
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
</exclusions>
</dependency>
With that, the problem is solved.