4

I'm relatively new to Java & maven, and so to get to know my way around, I decided to do a project as a means for learning.

I picked a pretty common stack :

  • Java 1.6
  • Hibernate (with annotations)
  • Spring (with annotations)
  • JUnit 4
  • Tomcat
  • Oracle XE / In-mem hsqldb

By far one of the biggest problems I've experienced is getting the correct combination of jar versions to get a stable environment. It's an issue I'm still fighting with over two months later.

Quite often I get noSuchMethod or classNotFound exceptions thrown, and it turns out to be that Spring module A x.x.x is not compatible with Hibernate module B y.y.y. Or even, just as commonly, spring module A x.x.x is not compatible with spring module B y.y.y

I expected in starting from a clean slate, version dependencies should be minimal -- just grab the latest version and everything should work... but that has not been the case.

I expected that using maven would simplify this process, and no doubt it has.

But it's certainly be far from painless. I'd have thought that if module A requires a specific version of module B, that it be enforced somewhere along the line, and certinaly provide more meaningful messages that just "noSuchMethod".

Additionally, it seems that the only way I discover these problems is to try a new method call, get the dreaded noSuchMethod error, and start googling.

Have I missed something along the way here that has made this more difficult on myself than it needed to be?

For reference, here's the dependencies section of my pom...if you notice anything horrendously non-standard, please let me know!

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.4</version>
    </dependency>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.3</version>
    </dependency>
    <dependency>
        <groupId>ojdbc</groupId>
        <artifactId>ojdbc</artifactId>
        <version>14</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency><!-- java bytecode processor -->
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.8.0.GA</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.2.1</version>
    </dependency>
    <dependency>
        <groupId>hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <version>1.8.0.7</version>
    </dependency>
    <dependency>
        <groupId>org.dbunit</groupId>
        <artifactId>dbunit</artifactId>
        <version>2.4.4</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-annotations</artifactId>
        <version>3.4.0.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>3.3.0.ga</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.3.1.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>3.1.0.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.4.0.GA</version>
    </dependency>

    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.3</version>
    </dependency>
</dependencies>

Thanks

Marty

Community
  • 1
  • 1
Marty Pitt
  • 28,822
  • 36
  • 122
  • 195

2 Answers2

2

One thing that I've found challenging is determining what is in each package, especially from Spring.

To that end, I've found Netbeans' support for maven to be outstanding in how it lets you know what libraries are pulled in by each requirement. 6.7 Beta contains a graphical tree which is outstanding, and m2eclipse also has a very nice graphical dependency tree. How else would you know that spring-orm includes, spring-beans, spring-core, spring-context, and spring-tx? You can ask maven for the dependencies using the dependency plugin from the command line, but the graphical representation is quite handy. dependency:tree is the goal you want to run. Obviously you can also run that from Netbeans or Eclipse.

So, as an example of one of your collisions:

 <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-annotations</artifactId>
   <version>3.4.0.GA</version>
 </dependency>

actually includes hibernate-commons-annotations-3.1.0.GA not 3.3. It also includes hibernate-core-3.3.0.SP1, not 3.3.1.GA.

I would start at your "biggest" component, and start to see what parts that already includes and only add what is missing. Even then, double check that you don't have a duplicate dependency and if need be, exclude the duplicate as shown in the answer to this question.

Community
  • 1
  • 1
Mike Cornell
  • 5,909
  • 4
  • 29
  • 38
  • FYI - the m2eclipse plugin for Eclipse also has the ability to graph dependencies – matt b May 19 '09 at 13:49
  • Also I think you can use mvn help:effective-pom to get a breakdown of ALL dependencies – matt b May 19 '09 at 13:50
  • I agree with you that determining the necessary modules to use with Spring is difficult. It would be great if there was a "map" specifying which packages were part of which modules. Does anyone know of such a reference? – Paul Morie May 19 '09 at 20:26
  • http://mvnrepository.com will, but it just basically lists the entries in the POM of the artifact you're trying to use. For example: http://mvnrepository.com/artifact/org.springframework/spring-orm/2.5.6 lists what spring-orm uses. – Mike Cornell May 20 '09 at 12:46
0

If you are using eclipse, then you should download the maven plugin from sonatype here http://m2eclipse.sonatype.org/.

This comes with a useful graphic visualisation of your dependencies (in particular transitive dependencies - dependencies you have not explicitly defined in your POM), and also shows conflicting dependencies.

Update: from the comments below, your mileage may vary.

toolkit
  • 49,809
  • 17
  • 109
  • 135
  • I've been using m2eclipse for a while, and find it can be pretty flaky, especially around WTP and nested modules. However, I thought I'd install the POM editor so I could see these transitive dependencies. The first thing that happened in m2eclipse when I tried to view them? "java.lang.NoSuchMethodError". I love irony. – Marty Pitt May 19 '09 at 14:10
  • I find the m2eclipse "list view" to be much more readable than the graphical view. And it has much better interactions. e.g. Clicking on commons-logging will narrow down and show you just the places that use it. – Dominic Mitchell May 19 '09 at 14:11
  • Try running the dependency:tree goal in Eclipse. I think it may help if you're having issues with the graphical plugin. – Mike Cornell May 19 '09 at 15:10