In one of my previous post I wrote that using development frameworks pays off and it is generally worth investing your time in learning how to use them. I was also clear that learning process is not easy and you could lose some hair from your head or simply go mad.
I would like to present an example how easily you can get lost using Spring Framework together with Struts 2 and Maven. The problem I'm going to present is often referred as a JAR Hell. I will present ideas how to cope with that.
In the following paragraphs I'm going to present libraries dependency problems I encountered integrating Spring Framework with Struts2. I will also present how I discovered what the real problem is and how I solved it.
Let's go
In one of my projects I use Spring integration with Struts2. In order to use this integration I have to add following dependency to pom.xml:
dependency entries with one (full Spring package with all components - it's about 2.8 MB):Here is my full pom.xml I'm using in the example.
JUnit errors
I built the project and my tests were OK - I was happy. Unfortunately when I started developing next feature I created new Spring-based unit test i.e. (please refer to Spring documentation for details):
That's pretty strange one :) And the whole build process was OK when launched by Maven!
Investigation
I checked the Spring Forum and I found what causes this problem: So basically, just make sure you are using spring.jar and spring-test.jar from 2.5 RC1, and that should do the trick.
But Hey! I'm using Spring 2.5.5! WTF? After some brainstorming with myself I checked my project's build path and I found something strange - in my classpath there were Spring libraries spring-beans, spring-core, etc. with version 2.0.5 (yes - spring-2.5.5.jar was also there). It took me some time and brain-effort to identify my enemy. I checked struts2-spring-plugin POM. Everything became clear - this plugin imported Spring JARs in different versions than those I needed.
There are two solutions to this problem.
First way
First one is to define Spring dependencies as separate modules i.e. this way. Maven will not import old JARs because you explicitly define which version you want.
Disadvantage of this solution is that you will have to know which components are used in runtime by your system - it's not always obvious at the beginning and you will have to understand many runtime exceptions before you get the correct dependency configuration. It's also possible that you will not set dependency for all Spring modules imported by Struts2 and in your classpath you will have almost all JARs with version let's say 2.5.5 but still some Spring modules will be imported with version 2.0.1.
The other one
The second solution is to define Spring dependency this way. With this solution you have to exclude problematic dependencies from struts2-spring-plugin:
This way you tell Maven that you only want struts2-spring-plugin and you don't need it's dependencies to be resolved automatically.
I think I don't have to describe disadvantages of this solution - anyway this is my preferred way of doing this.
I'm not going to throw away Spring and Struts2 integration because I have some problems with it. OK - I lost some significant amount of time on investigation the problem and finding the solution but I now know that I have to careful with Maven2 dependencies. Even if you depend on some concrete version of some framework Maven will automatically download and add missing dependencies. The problem is that it can make real mess in your classpath adding unnecessary JARs and it will be difficult to find the problem occurring in runtime.
The truth is that even with tools that manage software dependencies for you you may encounter some problems like the one I described. Managing dependencies is hard and I have no simple answer how to do it right at once. When you develop Java project you should use Maven-like tool but it still is not perfect (and probably will never be). The good idea in general is to version libraries you use (JARs, DLLs, whatever) and to put the used version in the file name (Maven does that automatically).
It's not very helpful tip but you should be careful :) and most of the time know what dependencies will be included with the next library you're going to use. You have to check for possible conflicts and resolve them by removing unnecessary dependencies.
I know it doesn't help much but that's the way it is - dependency management is hard. Full stop.
Comments
Maven DependencyManagement
August 7, 2008 by Simon Tiffert (not verified), 1 year 26 weeks ago
Comment id: 1741
Hello,
have you tried to setup a DependencyManagement region in your (parent) pom?
We have worked around our dependency problems with this.
More information:
http://maven.apache.org/guides/introduction/introduction-to-dependency-m...
Simon
Re: Maven DependencyManagement
August 8, 2008 by pbielicki, 1 year 26 weeks ago
Comment id: 1742
Thanks for your comment and a tip. However Maven DependencyManagement will not save me from dependency problem I had :) It can save others developing my projects later on. But I still have to know the dependencies in order to configure DependencyManagement, right?
Przemek
Re: Maven DependencyManagement
August 8, 2008 by Simon Tiffert (not verified), 1 year 26 weeks ago
Comment id: 1743
No the dependency management won't save you to learn about the involved dependencies.
But you can force Maven to get exactly the version you need for your projects, which can be very helpful when dealing with a lot of dependencies and frameworks.
And yes, Maven can be very painful.
Re: Maven DependencyManagement
August 8, 2008 by pbielicki, 1 year 26 weeks ago
Comment id: 1746
It's not Maven - it's dependency management IMHO. I don't know better tool than Maven and I know that Maven is sometimes pain in the ass :)
I think many people blame Maven for being painful and in my opinion it's unfair. Maven is just like the messenger (don't kill the messenger) who tells you that dependency management is really hard - no matter which tool you use.
PS. I blame Maven also very often for all the pain it causes - but if I go back in my memories to the times when I was building my projects using Ant I see the bright side of Maven :)
Find dependencies
August 8, 2008 by Simon Tiffert (not verified), 1 year 26 weeks ago
Comment id: 1747
Forget to mention how to find the involved dependencies:
"mvn site" will have a section with all dependencies listed as a tree. I normally use this, when I want to know, what dependencies in which build phase are involved.
Also there is the dependency-plugin which can find mismatches or just list the dependency tree:
http://maven.apache.org/plugins/maven-dependency-plugin/plugin-info.html
Wildcard exclude wish
August 8, 2008 by Tech Per (not verified), 1 year 26 weeks ago
Comment id: 1750
Been there, hated it :-(
And when faced with such problems, I always come to miss the feature of doing wildcard matching for dependency exclusions. Like this:
But maven does not support it...
Maven 0 OSGi 1
August 9, 2008 by Anonymous (not verified), 1 year 26 weeks ago
Comment id: 1751
Another example of where Maven's naive dependency management is lacking compared to OSGi.
Post new comment