When you have multiple projects that all use the same set of JAR libraries, it's tedious to include the same JARs over and over again with each project. If I'm working on 20 different projects, I'd rather not have 20 of the same exact set of JAR files lying around. What's the best way to make all those projects (and new projects as well) reference the same set of JARs?
I have some ideas, but each of them has some disadvantages:
Use Maven or Ivy to handle these shared jars. If you're wary of changing your projects too much, you can simply use Ivy to manage the extra classpath for you.
Both have good Eclipse plugins:
Maven classpath container http://img229.imageshack.us/img229/4848/mavendependencies.png
IvyDE classpath container http://img76.imageshack.us/img76/3180/cpnode.jpg
which I've used with good results.
You'll note that both of them reference jars outside the workspace, so the duplication is removed.
Update ( prompted by comments ):
My reason for recommending this approach is that I strongly believe that it's simpler and clearer to declare dependencies rather then manually include them. There is a small one-time cost associated with this - smaller for Ivy than for Maven - but in the long run it does pay off.
Another, smaller, benefit is the handling of transitive and conflicting dependencies. It's easy to forget why you need that commons-logging-1.1.jar in the classpath and whether you need to upgrade to 1.1.1. And also it's no fun to pull in all the depencies required for e.g. a Hibernate + Annotation + Spring combo. Focus on programming, not building.
Believe it or not, your 'tedious' approach is probably the simplest, cleanest and least time-consuming approach there is.
Before jumping on the maven bandwagon you should consider what is really wrong with doing things the way you are currently doing them. You mentioned that it is tedious and that you have a lot of jar files lying around. I created the build process on a large multi-module project using Maven then spent the next 18 months battling with it constantly. Believe me it was tedious and there were a lot of jar files lying around.
Since going back to Ant and committing jars to source control alongside the projects that use them it has been a much smoother ride.
I store a bunch of jar files in a single directory on my machine and then when I create a new project or need to add a new jar to an existing project it only takes about 30 seconds:
Over the course of a project, that 30 seconds is insignificant, but it means I have a project that can be checked out of source control and just works without requiring any custom Eclipse configuration or Maven installations or user-specific setup.
This approach has saved me and my project team a huge amount of time, mainly because it is simple, reliable and easy to understand.
Update: Clarification prompted by comments
@Robert Munteanu: Thanks for the feedback and updated comments. This might sound a bit argumentative but I'm afraid I can't agree with you that Maven is simpler and clearer, or that it will save you time in the long run.
From your posting:
"I strongly believe that it's simpler and clearer to declare dependencies rather then manually include them. There is a small one-time cost associated with this - smaller for Ivy than for Maven - but in the long run it does pay off."
It may be easier to have Maven download a jar file for you than having to download it yourself but that's the only advantage. Otherwise Maven is not simpler, not clearer and its complexities and limitations will cost you in the long run.
Clarity
The two dependency declarations below do the same thing. I find the Ant one much clearer than the Maven one.
Ant Style:
<path id="compile.classpath"> <pathelement location="${log4j.jar}" /> <pathelement location="${spring.jar}" /> </path>
Maven Style:
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>${spring.version}</version> <scope>compile</scope> </dependency>
Simplicity
With the Ant version you can hover over the ${log4j.jar} property and it will show you the absolute path to the jar file. You can search for usage of compile.classpath. There's not a whole lot more you need to know.
There is no question that Maven is more complex than the approach I'm suggesting. When you start out with Maven these are just some of the questions that need to be answered.
Transitive Dependencies
"Another, smaller, benefit is the handling of transitive and conflicting dependencies."
In my experience, transitive dependencies are more trouble than they're worth. You end up with multiple versions of the same jar file and you end up with optional jar files that you don't want. I ended up declaring just about everything with provided scope to avoid the hassle.
The Long Term Payoff
"Focus on programming, not building."
I agree. Since going back to Ant and putting my jar files in source control I have been able to spend far less time dealing with build issues.
These are the things I spend less time doing:
Anyways, sorry about the long posting. Maybe now that I've got that off my chest I can bring some closure to my long and painful Maven experience. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With