Monday, October 18, 2010

Maven and Hibernate hell.

I am a Maven newbie and wanted to setup an example Maven + Spring + Hibernate + Mockito project. I have been fairly successful at that but not without my struggles with Maven.

Here is my hibernate dependency structure in pom.xml. Some experienced maven and hibernate users probably would spot the mistake right away. Anyway, let me go on and fix the "errors" myself.


        
            org.hibernate
            hibernate-core
            3.6.0.CR2
        
        
            org.hibernate
            hibernate-annotations
            3.5.7-SNAPSHOT
        
        
            org.hibernate
            hibernate-commons-annotations
            3.3.0.ga
        
        
            org.hibernate
            hibernate-entitymanager
            3.6.0.CR2
        



Struggle #1: Maven and transitive dependencies.

I try to deploy my application in Tomcat and get the error below:

org.springframework.beans.factory.BeanCreationException: 
  Error creating bean with name 'sessionFactory' defined in 
  ServletContext resource [/WEB-INF/spring/hibernate-config.xml]: 
  Invocation of init method failed; nested exception is
  java.lang.IncompatibleClassChangeError: Implementing class


After researching I found that the reason is multiple hibernate jars in the classpath. I check and yes there is a: hibernate.3.2.1.ga.jar and b: hibernate-core-3.6.0.CR2.jar. So now I have the task of finding out which hibernate dependency is bringing the 2 different hibernate jars.

On further research I find that hibernate-commons-annotation.3.3.0.ga.pom has dependency on hibernate.3.2.1.ga and hibernate-annotations-3.5.7-SNAPSHOT.pom has dependency on hibernate-core-3.6.0.CR2.

So that explains why I see two jars. I manually exclude the hibernate jar from hibernate-commons-annotations:


            org.hibernate
            hibernate-commons-annotations
            3.3.0.ga
            
                
                
                    org.hibernate
                    hibernate
                
            
        


And that takes care of multiple hibernate jars on the classpath. Is there is an easy way to not have transitive dependency in maven?

Struggle #2: Now on deployment I get:

Caused by: java.lang.NoClassDefFoundError:
  org/hibernate/annotations/common/reflection/MetadataProvider


hibernate-commons-annotation.3.3.0.ga.jar does not have MetadataProvider class. After googling the error I find: http://forum.springsource.org/showthread.php?t=89693

From hibernate-commons-annotation readme:

Version '3.3.0.ga' was a mistake during the release process, please disregard.
There is not such version 3.3.0.ga.

The solution then is to use hibernate-commons-3.2.0.Final

Final working dependency structure:


        
            org.hibernate
            hibernate-annotations
            3.5.7-SNAPSHOT
        
        
        
            org.hibernate
            hibernate-commons-annotations
            3.2.0.Final
        
        
            org.hibernate
            hibernate-entitymanager
            3.6.0.CR2
        

I wonder if all of this effort would have been saved had I just downloaded the jars from hibernate.org directly. Which makes me wonder if Maven is worth it for small projects?

6 comments:

  1. You are creating your own hell. Why do you mix different versions of hibernate-core and hibernate-annotations at the first place?!?! And even snapshots of them?!? It's just crazy. Use most recent 3.5.6 or 3.6.0 and STOP overriding hibernate-commons-annotations version

    ReplyDelete
  2. Another way to find out the dependency issue with Maven is to use the dependency:tree lifecycle. This gives a clear picture which dependency is causing the duplicate jars along with its version.
    I think, that would have been an easier way to figure out.

    ReplyDelete
  3. Or check Hibernate Matrix for older versions:

    http://community.jboss.org/wiki/HibernateCompatibilityMatrix

    You would be in a similar hell using downloaded jars in these particular versions.

    ReplyDelete
  4. @Anthavio: Thank you for the post. I did not know that the rule of thumb was to use the same versions. I will keep that in mind.

    The day I started on the demo project, I just wanted to pick the latest available in the repository and hence the different versions.

    Also, just wanted to make below known:

    Version '3.3.0.ga' was a mistake during the release process, please disregard.
    There is not such version 3.3.0.ga.

    ReplyDelete
  5. @Arpit: Cool! I checked it out. I liked it. Thank you for your comment. Next time I am trying to figure out why the duplicates, I would definitely use mvn dependency:tree -Dverbose

    ReplyDelete
  6. @Michal: Thanks mate!!! That is great information.

    ReplyDelete

Your comments are welcome. It will help me improve my communication and content...plus it will encourage me! :-)