4

I have been extracting 3rd-party library JARs into my open source Java library in order for the dependencies to work at runtime.

I remember when I tried doing this in Eclipse a while ago (different project) it produced a warning to check licensing before doing this.

What exactly are the general rules regarding when it's ok to repackage library contents into your JAR, how it should be done, and which widely used licenses forbid it?

Specifically, the libraries I'm repackaging use BSD and LGPL.

Thanks in advance for your help.

Edit

I actually ended up separating out the dependencies to prevent code conflicts as several commenters suggested. Thanks again for the suggestions and information provided.

bgroenks
  • 1,859
  • 5
  • 34
  • 63
  • 1
    A far better solution is to use Maven to build your project (or Ant with a dependency manager like Ivy, or really, *anything that manages dependencies for you*. – parsifal Mar 21 '13 at 20:53
  • 1
    And even if you don't like the idea of Maven, I can guarantee you that the possible consumers of your JAR will like duplicate dependencies even less. – parsifal Mar 21 '13 at 20:55
  • @parsifal The question may still be applicable in some cases, for example when packaging a `jar-with-dependencies`. – ach Mar 21 '13 at 20:55
  • The idea here is to package the JAR with it's dependencies. A developer utilizing the API should be able to use it without searching for separate dependencies or having to worry about putting them on the classpath of their distributed Java application. – bgroenks Mar 21 '13 at 20:58
  • @bgroenks - I can only speak for myself, but I would instantly reject any third-party library that contained its own copy of, say Jakarta Commons Lang (at least one that didn't rename all of the packages). I don't know what your library does, but I do know that it doesn't do anything that would justify [classpath hell](http://stackoverflow.com/questions/373193). – parsifal Mar 21 '13 at 21:05
  • But if you're really intent on doing this, I suggest you Google on PSE. There are a bunch of answers to "open source license jar dependencies site:stackexchange.com", most of which are of the form "I am not a lawyer." – parsifal Mar 21 '13 at 21:06
  • But that's exactly why I'm extracting the third party libraries into the JAR. That way there is no classpath hell, they are all just loaded either by the implementer's URLClassLoader or the system if it's on their standard classpath. – bgroenks Mar 21 '13 at 22:40
  • @bgroenks - You really don't get it. If you're producing an *application*, fine, do what you want. But you say "my open source Java library." Which means that your library will only be a part of a bigger application, built by someone else. And the people who build that application may not want to use the same dependency versions that you do. Maybe they want to use newer, *maybe they want to use older*. Maybe they need to use an older dependency, because the newer one has a bug in a class that you don't use. – parsifal Mar 22 '13 at 13:03
  • *Dependency management is a solved problem.* You're ignoring that fact, and making life more difficult for anyone who isn't building a toy application. But as I said above, it's your choice to do this, and the choice of your potential user base whether the potential pain is worth the potential benefit. – parsifal Mar 22 '13 at 13:04
  • So you're saying I should just leave it up to the library user to link all of the appropriate dependencies? What if they don't use Maven? – bgroenks Mar 23 '13 at 17:34
  • You're right. It is more practical to keep them separate. That is what I ended up doing, but I also provided a bundle of all the required dependencies for those who don't need a different version along with my library and the individual dependencies. – bgroenks Mar 24 '13 at 14:28
  • 4
    I'm voting to close this question as off-topic because it is about licensing or legal issues, not programming or software development. [See here](http://meta.stackoverflow.com/questions/274963/questions-about-licensing/274964#274964) and [here](http://meta.stackexchange.com/questions/139804/can-licensing-questions-ever-be-on-topic) for details, and the [help] for more. – JasonMArcher Jun 11 '15 at 21:54

2 Answers2

6

What I personally do is make sure that none of the library I use explicitly forbid redistribution. If they do, you're out of luck. Neither BSD nor LGPL do though, so you should be ok. I can't think of a sane open source license that would.

Once you're satisfied you're not violating the terms of the license by repackaging and distributing them, you need to make sure you respect them in other aspects. I find that the following steps are sufficient for 99.99% of the open source licenses out there:

  • create a license.txt file at the root of your JAR file (some people put it in META-INF, but I know of no rule or convention on this and think it's just a matter of preference).
  • list all of the external libraries you import and the license under which they are distributed in license.txt.
  • write the complete text of all licenses that apply in license.txt.
  • ideally, link to each library's web site, download page and license page if available.

This should make sure you don't run afoul of any mainstream license, to the exception of the GPL. I'm not a lawyer, nor am I an expert in the GPL, and any advice I give you on how to respect it might end up entirely wrong, so I'd rather not lead you astray.

There are a few more things you can do, but those are more a matter of professional courtesy:

  • if you're writing a user facing application (webservice, UI application...), link to the libraries you're using in the About section.
  • let the maintainer of the library know that you're using and packaging it - some authors like to maintain a list of popular software using their tools.

While that might sound like a lot of work, it's far less work than writing and maintaining the actual library.

EDIT: I just realised that you were working on a library, as opposed to an application. My answer doesn't actually apply in that case: it's very poor form to package your dependencies in your library's JAR. If anything, it makes it rather harder for third-party developers to integrate your library with existing build tools and dependency management systems (maven, ant / ivy...).

If you want to keep things simple, just include the JAR of all your dependencies in the /lib folder of your distribution files.

To re-iterate my point: I believe you'll alienate the majority of developers by packaging your dependencies in your library's JAR file rather than with it. I certainly would file a bug report and look for alternatives if the issue wasn't addressed.

Nicolas Rinaudo
  • 6,068
  • 28
  • 41
  • I understand. So you're suggesting put all dependencies in one JAR and allow them to use that? – bgroenks Mar 23 '13 at 17:46
  • Well, no, the standard solution is to copy all JAR dependencies in a `/lib` directory of you're project structure - if possible by labelling them clearly and including the library's version number in its file name. – Nicolas Rinaudo Mar 26 '13 at 07:52
  • That's what I ended up doing. I also provided a repackaged JAR with all of the dependencies in one for the convenience of those who are don't need to change them. – bgroenks Mar 26 '13 at 16:30
0

That's pretty ease to achieve with maven. Convert you project to a maven project which will make your life much easier and use the maven-assembly-plugin with descriptorRefs as jar-with-dependencies(a predefined assembly structure). You can create your own if you like so maven packages your code however you like.

Example of maven-assembly-plugin configuration:

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id> <!-- this is used for inheritance merges -->
            <phase>package</phase> <!-- bind to the packaging phase -->
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      [...]
</project>
emd
  • 740
  • 4
  • 12