views:

235

answers:

1

I have 5 maven projects: simple-model, simple-weather, simple-persist, simple-webapp and simple-console. (They are from the Maven Definitive Guide book). The simple-console depends on simple-weather and simple-persist. simple-persist and simple-weather both depend on simple-model:

simple-console ---> simple-weather ----> simple-model
             \                       /
              \---> simple-persist--/

simple-console depends on spring and hibernate, in effect depends on a jar that contains javax.transaction.TransactionManager. I generate eclipse projects for these 5 projects. The Main class inside simple-console (which invoke a Hibernate method) run fine in eclipse. However, when I tried to execute it with Maven'sexec:java goal or java -cp (assemblied with jar-with-dependencies), I always got this error: Caused by: java.lang.NoClassDefFoundError: javax/transaction/TransactionManager

It really confused me because, while eclipse knows how to include necessary jars before execution, maven plugins don't make sense of that. Why?

P/S: I have uploaded the source code of these projects here: http://seamoo.com/simple-parent.tar.gz

+3  A: 

If you run mvn dependency:tree in simple-console, you won't see the JTA artifact:

[INFO] org.seamoo:simple-console:jar:1.0
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] +- org.seamoo:simple-persist:jar:1.0:compile
[INFO] |  +- org.seamoo:simple-model:jar:1.0:compile
[INFO] |  +- org.hibernate:hibernate:jar:3.2.5.ga:compile
[INFO] |  |  +- net.sf.ehcache:ehcache:jar:1.2.3:compile
[INFO] |  |  +- asm:asm-attrs:jar:1.5.3:compile
[INFO] |  |  +- antlr:antlr:jar:2.7.6:compile
[INFO] |  |  +- cglib:cglib:jar:2.1_3:compile
[INFO] |  |  +- asm:asm:jar:1.5.3:compile
[INFO] |  |  \- commons-collections:commons-collections:jar:2.1.1:compile
[INFO] |  +- org.hibernate:hibernate-annotations:jar:3.3.0.ga:compile
[INFO] |  |  \- javax.persistence:persistence-api:jar:1.0:compile
[INFO] |  \- org.hibernate:hibernate-commons-annotations:jar:3.3.0.ga:compile
[INFO] +- org.seamoo:simple-weather:jar:1.0:compile
[INFO] |  +- log4j:log4j:jar:1.2.14:compile
[INFO] |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  |  \- xml-apis:xml-apis:jar:1.0.b2:compile
[INFO] |  +- jaxen:jaxen:jar:1.1.1:compile
[INFO] |  |  +- jdom:jdom:jar:1.0:compile
[INFO] |  |  +- xerces:xercesImpl:jar:2.6.2:compile
[INFO] |  |  \- xom:xom:jar:1.0:compile
[INFO] |  |     +- xerces:xmlParserAPIs:jar:2.6.2:compile
[INFO] |  |     +- xalan:xalan:jar:2.6.0:compile
[INFO] |  |     \- com.ibm.icu:icu4j:jar:2.6.1:compile
[INFO] |  \- velocity:velocity:jar:1.5:compile
[INFO] |     +- commons-lang:commons-lang:jar:2.1:compile
[INFO] |     \- oro:oro:jar:2.0.8:compile
[INFO] +- org.springframework:spring:jar:2.0.7:compile
[INFO] |  \- commons-logging:commons-logging:jar:1.1:compile
[INFO] |     +- logkit:logkit:jar:1.0.1:compile
[INFO] |     +- avalon-framework:avalon-framework:jar:4.1.3:compile
[INFO] |     \- javax.servlet:servlet-api:jar:2.3:compile
[INFO] \- hsqldb:hsqldb:jar:1.8.0.7:compile

And indeed, if you look at simple-persist/pom.xml, you'll see that it has been excluded:

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate</artifactId>
  <version>3.2.5.ga</version>
  <exclusions>
    <exclusion>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
    </exclusion>
  </exclusions>
</dependency>

My guess is that the jta artifact is excluded because the full hibernate jar (hibernate-3.2.5.ga.jar here) depends on jta-1.0.1B.jar which is NOT available in the central repo due to licensing issues while hibernate core (i.e. hibernate-core-3.3.0.GA.jar) depends on jta-1.1.jar, which is available from central.

The reason why it works in Eclipse is that the simple-model depends on hibernate-annotations-3.3.0.ga.jar which depends on hibernate-3.2.1.GA.jar which depends on jta-1.0.1B.jar (that you very likely have in your local repository). So, because the whole hibernate dependencies are a big mess in this project, because there are big dependencies convergences problems, Eclipse "sees" the JTA jar (that's just a fortunate or unfortunate side effect). But Maven doesn't.

To solve the problem, either remove the JTA exclusion in simple-persist/pom.xml (that's the quick and very dirty fix) or fix the hibernate dependencies to make them converge (that would be the right fix):

  • use hibernate-core-3.3.0.SP1.jar wherever required
  • use hibernate-annotations-3.4.0.GA.jar (which depends on the former) wherever required
Pascal Thivent
You are so right. It amazes me how did you figure the problem out. You're a genius.
Phương Nguyễn
@Phuong You make me blush.
Pascal Thivent
@Pascal Thivent no need he is just realistic
c0mrade