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

后端 未结 7 1774
眼角桃花
眼角桃花 2020-12-23 22:14

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

相关标签:
7条回答
  • 2020-12-23 22:26

    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.

    0 讨论(0)
  • 2020-12-23 22:35

    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.

    0 讨论(0)
  • 2020-12-23 22:38

    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.

    0 讨论(0)
  • 2020-12-23 22:48

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

    0 讨论(0)
  • 2020-12-23 22:50

    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.

    0 讨论(0)
  • 2020-12-23 22:51

    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)

    0 讨论(0)
提交回复
热议问题