views:

851

answers:

7

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

You might edit the "Installed JREs" to include your JAR file ("Add external JARs"), add the file to jdk\jre\lib\ext\ directory or specify a CLASSPATH environment variable containing the path to it.

kd304
I would stongly advise against this, as you lose knowledge of dependencies when checking in your code and/or sharing with others on your team, or trying to rebuild a specific working version of your projects
Scott Stanchfield
this is considered as a "worst practice" think about the steps you need to do when setting up a new development environment.
Yonatan Maman
A: 

I'd recommend the "library" project approach.

But even better -- a separate lib project per external jar -- this allows you to track deps between third-party jars and know what needs to change when you're upgrading a dependency.

Make sure you check in these projects so all users are using the same versions of third-party libs and so you can easily regenerate a version of software (use tags/labels in your version control to group which versions of which projects go together)

Scott Stanchfield
I would recommend against doing this in the IDE. The next developer that is going to have to maintain the code may not have access to your IDE settings.
sal
the question was about running in eclipse; the assumption is that all developers have the same IDE
Scott Stanchfield
+14  A: 
Robert Munteanu
+1 for Maven. Let each application explicitly define which other JARs/projects they depend on, and let the build script determine which of these to fetch. This will also introduce the idea of "versioning" these artifacts to you - which is very useful.
matt b
+1 more for Maven (and also ivy) being portable across other environments besides Eclipse.
tschaible
+1 for maven/ivy or ant. You should avoid defining your dependencies in your IDE and make them part of your project. When they are part of the project, the next poor shlub will get the dependencies when they get the source rather than try to re-create your environment.
sal
+1 for Ant and Ivy, for being much less complex than Maven, yet comparable in power. :-) Ivy is a fabulous way to manage dependencies, particularly when different applications may require different versions of a given library. By all means, try to avoid putting your JAR files in source control.
Quinn Taylor
-1 for maven or ivy. I agree with what the previous comments say about build scripts defining dependencies, IDE independence etc, but you can achieve those things very easily without Maven. When people say "Don't put your jars in source control", it sounds intuitively correct so we don't question it. But what's the downside? Compared with Maven it is simpler, just as easy and more likely to work. The cost of download time is cheap compared to the cost of managing Maven's complexities and working around its limitations.
Kevin Stembridge
@Kevin Stembridge: see my update for the reasons I advocate such an approach. Also, you add a (-1 for maven or ivy) but list some (perceived) downsides for Maven only. Why is that?
Robert Munteanu
Hi Robert. I didn't comment on Ivy because I ran out of space :) Also, I don't have as much experience with Ivy as I do with Maven. But when I was getting fed up with Maven I looked at Ivy as an alternative and I could see that it was a more powerful dependency manager, but still I didn't need the complexity. I'm going to run out of space again but I'd like to respond to your update so I'll add to my original posting.
Kevin Stembridge
Maven looks a bit much for my needs, but I think I'll give Ivy a try.
Zarjay
I like both approaches. Maven can be very powerful, but you need to go through hell in order to become good at it. Time spent learning this tool should be carefully considered compared to Ant and project based jars.
JamesC
Regarding m2eclipse. This plug-in is good but not perfect. However I would not use Maven without it.
JamesC
Please see http://kent.spillner.org/blog/work/2009/11/14/java-build-tools.html
JamesC
+1  A: 

It depends on your needs, but there are several viable options. My work uses an external folder and all projects reference that folder, which makes life easier running builds outside of eclipse. A user library is a slightly more plesant way of doing things, as long as you don't mind the slight eclipse dependancy. I don't see a whole lot of benefit to a library project on it's own, but if you have some sort of universal 'util' type project that all other projects already load, you could just put all the external jars in that project.

dimo414
A: 

We have decided on a more tedious method but which allows us to have everything inhouse, but will probably only work well for a small set of developers.

Each set of jar files is set up as a Eclipse project named appropriately after the jar set, added to the build path, source jars and javadoc jars correctly set on each jar in the build path, and each project then includes those library projects needed for that project. The resulting multi-project workspace is then exported as a ProjectSet.psf file which can then be read in in a raw Eclipse bringing in the whole workspace again. We then have all the above projects in CVS including the jar files.

This has worked very wellf or us.

If you are in a larger organization the dependency handling in Maven may work well for you. You should definitively have a local cache of artifacts so the whole world doesn't stop if your internet connection is lost.

Also note that the new Eclipse 3.5 coming out this sommer, will have a "Create Runnable Jar" which can output the needed jars next to the generated runnable jar and set up the Class-PAth line in the Manifest correctly. I expect that to be a big time saver - check it out.

Thorbjørn Ravn Andersen
+7  A: 

Hi Zargay,

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

Kevin Stembridge
Agreed. Maven causes pain due to the execution of its implementation.See http://kent.spillner.org/blog/work/2009/11/14/java-build-tools.html
JamesC
+1  A: 

One approach is to put all your jar files in one location on your machine, in your eclipse ide, define an environment variable, say LIB_LOCATION that points to that directory and have your projects use the jars relative to that variable. This way, you get the ease of use, no multiple jars, portable across machines, as long as you have the variable defined correctly. I have been trying maven for a group of decent size projects and it seems I have to fight at least as much as I used to. Bugs and wired behaviors in the plug ins, m2eclipse and q4eclipse.

kamal