views:

98

answers:

7

I have a general question on what is the proper way to manage your compile and deployment jar dependencies. I typically lay out the dev directories like the following for a simple library/application.

Calculator
   src
   test
   build
   lib
   …

There are many ways to do this, but this is my typical layout for generic projects. My question revolves around the lib directory. I typically place jars that my project is dependent on in the lib directory (log4j, etc.) So at compile time I can set my various paths as lib\log4j.jar or something like that. Now when we create a distributable package, I have tended to mirror this layout.

dist
   Calculator.jar
   lib
      log4j.jar
      addition.jar
      subtraction.jar

This allows me to either setup a script that sets my classpath relative to where the main jar, or I can setup the classpath in the manifest for the main jar ( Calculator.jar in this case ) This may or may not be the best way to do this, but it has worked for me and seems to be the accepted way of dealing with dependencies by other developers I have talked to about this.

My question comes when I then want to create a new project that makes use of some other project that I have laid out this way.

So let’s say I want to create a new calculator project that uses the Calculator project from the sample above. If I follow the same layout, I would get something like the following:

dist
   ScentificCalculator.jar
   lib
      Calculator.jar
      lib 
         Log4j.jar
         addition.jar
         subtraction.jar

Of course, this could get out of hand the deeper your dependency tree is:

SuperWhizBangCalculator.jar
lib
   ScientificCalculator.jar
   lib 
      Calculator.jar
      lib
         log4j.jar
         addition.jar
         subtraction.jar

Another option would be to flatten out the tree:

SuperWhizBangCalculator
   lib
      ScientificCalculator.jar
      Calculator.jar
      log4J.jar
      addition.jar
      subtraction.jar

But something just does not seem right about this. You lose the structure that tells you what libraries go with which component that you are dependent on. So I was wondering if there is a community driven standard way of doing this, with the understanding that there is never a once size fits all.

Thanks for the time...

+1  A: 

I don't think you'll find a community-driven standard, but I think that overall having a lib-in-a-lib is not a good idea. You risk duplicating many jar files that would be common to your projects. That wastes disk space, and gives you the risk of upgrading the jar that isn't first in your classpath...

I think your third option is the best one.

Also, I would give some thought about how Eclipse manages the links between two different projects... you can put a project in the build path of another project...

mlaverd
I don't see the valuable contribution Eclipse is making to this problem. Eclipse does in effect use a structured layout of libs and I think we both agree this is a bad idea for a distribution setup
Jens Schauder
A: 

I'd absolutely go with the last approach. Imagine a program A using libraries B and C which both use D. In a structured layout you would have two instances of D around, which is just begging for version conflicts.

Jens Schauder
A: 

there are two types of things here

  1. External Dependency with third party libraries like log4j
  2. Internal Dependency within the project

ideally, you should have the lib directory for your internal dependency. you should build the external dependency dynamically when creating the deployment plan.

coder
+1  A: 

Does not answer your question directly. But you could have a look at Apache's Maven 2 which can do most of the "dependency management" for you.

Be informed that there is some learning curve in getting Maven 2 up, running and working :)

Other than that the third options makes sense to me.

Calm Storm
I have used maven in the past. I would need to setup my internal repository as my company is not keen on pulling in software from outside the walls wihtout going through a level if process
Rob Goodwin
I'd always recommend creating an internal repository for anything but the most trivial project.
hbunny
+1  A: 

To echo another answer, "Why not just use Maven?"

Maven will manage all your dependencies for you, and when another project wants to use your jar, it will be far, far easier for them to do so. If there is a standard for build, layout and dependencies in the Java world, it's Maven.

noah
I agree, I have used maven in the past. I would need to setup my internal repository as my company is not keen on pulling in software from outside the walls wihtout going through a level if process.
Rob Goodwin
+1  A: 

Go for your last option - flat lib directory. This is what you'll find if you download any open source project that has dependencies (they may use another level of sub-directory if there's a number of related JARs).

Don't confuse a directory structure with dependency management - they are completely separate things. If you want smart dependency management, then you need to look at something like Maven, ANT with Ivy, or possibly some module system with explicit dependencies (OSGi).

hbunny
A: 

The crucial piece of information is how the classes will be loaded. In a "java -jar SuperWhizBang.jar" situation you will have one classloader loading all classes. Then it would make perfect sense to merge the dependencies.

If you choose to have separate classloaders then a hierarchy would be a good idea. This typically happens in an OSGi setting, but that is probably overkill for your solution.

Thorbjørn Ravn Andersen