Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to share JARs across multiple projects?

Tags:

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:

  • Place all the JARs in a folder and have each project look in that folder.
  • Using Eclipse, create a "User Library" and have each project reference that user library.
  • Create a "Library" project that references each JAR, and have each project reference that library project.
like image 446
JR. Avatar asked Jun 12 '09 20:06

JR.


2 Answers

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:

m2eclipse

Maven classpath container http://img229.imageshack.us/img229/4848/mavendependencies.png

IvyDE

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.

like image 39
Robert Munteanu Avatar answered Sep 23 '22 14:09

Robert Munteanu


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:

  • Copy the jar from JAR_REPO to project lib dir.
  • Add jar to build.properties
  • Add jar to classpath in build.xml
  • Add jar to build path in Eclipse.

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.

  • What does groupId mean?
  • What does artifactId mean?
  • Where does the jar come from?
  • Where is the jar now?
  • What is provided scope? Who's providing it?
  • How did that jar file end up in my WAR file?
  • Why does this dependency not have a version element?
  • I don't understand this error message. What on Earth does it mean?
  • Where on Earth did that jar file come from? I didn't declare it.
  • Why do I have 2 versions of the same jar file on my classpath?
  • Why does the project not build any more? Nothing has changed since the last time I built it.
  • How do I add a third-party jar that's not in the Maven repository?
  • Tell me again where I get that Eclipse plugin from.

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:

  • Reading poor Maven documentation.
  • Reading even poorer Codehaus Mojo documentation.
  • Setting up shared internal repositories.
  • Educating team members.
  • Writing Maven plugins to fill the gaps.
  • Trying to workaround defective plugins (release, assembly).
  • Installing Eclipse plugins for Maven.
  • Waiting for the plugin to give me back control of Eclipse.

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. :)

like image 76
KevinS Avatar answered Sep 21 '22 14:09

KevinS