Is it possible to have a jar Manifest to use all jars in a folder

14,419

Solution 1

java does not know the jar files in the libs directory. If you are using java 1.6+, You can run program as

java -cp lib/* -jar MyJar.jar

Solution 2

You should define your Manifest classpath as

Class-Path: libs/lib1.jar libs/lib2.jar

See Oracle documentation for more details https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html

Solution 3

Try extracting these jars. It looks like you cannot add all jars from directory but you can add all classes. You lose obviously all configuration in manifest, however, if you are interested in jars' code content only, it might work.

I tested that with these simple classes

import pkg.B;

public class A {
  public static void main(String[] args) {
    System.out.println(B.class.getName());
  }
}

package pkg;

public class B {}

now I try to separate the classes. I have jarred them into

$ jar tf libA.jar 
META-INF/
META-INF/MANIFEST.MF
A.class
$ jar tf libB.jar 
META-INF/
META-INF/MANIFEST.MF
pkg/B.class

no Class-Path in any manifest. I can run A with java -cp libB.jar:libA.jar A. Now I create another jar with Class-Path set to lib/

$ cat manifest 
Class-Path: lib/
$ jar cfm empty.jar manifest

my directory tree look like

$ ls -R
.:
A.java  empty.jar  lib  lib.jar  manifest  pkg

./lib:
libA.jar  libB.jar

./pkg:
B.java

Now I try jar

$ java -jar empty.jar 
Error: Could not find or load main class A

Hopeless, right? Then I extracted libA.jar and libB.jar into lib (same as [this guy][2]). Now all is fine

$ java -jar empty.jar 
pkg.B
Share:
14,419
javydreamercsw
Author by

javydreamercsw

@javydreamercsw

Updated on July 03, 2022

Comments

  • javydreamercsw
    javydreamercsw almost 2 years

    I'm trying to set a jar manifest so it loads all the libraries (jars) within a folder next to the jar.

    The manifest looks like this:

    Manifest-Version: 1.0
    Class-Path: libs/
    Main-Class: path.to.my.class.Main
    

    The layout is as follows:

    - MyJar.jar
    - libs/
    -----lib1.jar
    -----lib2.jar
    

    And I'm trying to run like this:

    java -jar MyJar.jar
    

    And I get NoClassDefinition errors about classes in the jar within the folder.

    In case someone is curious, this folder might contain optional jars that are processed during class loading. That' swhy I can't use the hardcoded or autogenerated ones.

    Any idea?

    Update Rephrased the question as this is not currently possible from the manifest itself. The answer was the only really viable without the need of extracting the jars, although it also works.

    So as a summary the answer is no, this can't be done from manifest file alone if you have unespecified dependencies.

    • 11thdimension
      11thdimension over 7 years
      AFIK JAR's classpath starts at the root of the JAR file. You can't put classes or JARs in sub directories unless you're going to load them dynamically like Spring Boot or OSGI containers.
    • 11thdimension
      11thdimension over 7 years
      Turns out, it can be done, you have to specify path with the JAR name. Check this link todayguesswhat.blogspot.com/2011/03/…
    • javydreamercsw
      javydreamercsw over 7 years
      I ran across that link earlier and my manifest above is based on that but it doesn't work. It only finds the files within that folder that are defined in the classpath. The folder alone doesn't seem to work. (i.e. libs/ or ./libs/)
    • 11thdimension
      11thdimension over 7 years
      According to the link Class-Path: ./libs/lib1.jar should work.
    • javydreamercsw
      javydreamercsw over 7 years
      Yes it does, but I don't know the dependencies before hand. I would like to use all jars in there without the need of knowing before hand. Is for a plugin system.
  • javydreamercsw
    javydreamercsw over 7 years
    Didn't work as written. had to do this: java -cp libs/ -jar MyJar.jar. Sadly this is not what I asked as I'm trying to see if it's possible from the manifest.
  • javydreamercsw
    javydreamercsw over 7 years
    That only works if you know before hand the jars that the folder will have. This is intended for optional jars that the application detects when they are in the classpath.
  • Issam El-atif
    Issam El-atif over 7 years
    Did you try Class-Path: libs/*.jar ?
  • Issam El-atif
    Issam El-atif over 7 years
    Apparently Class-Path entry in manifest file did not support wildcards
  • javydreamercsw
    javydreamercsw over 7 years
    This just won't work for my scenario as non-technical users won't be able to do this. Asking them to put jars in a directory is hard enough. Thanks
  • javydreamercsw
    javydreamercsw over 7 years
    I ended up using a version of this to make it work: java -cp libs/* path.to.my.class.Main
  • javydreamercsw
    javydreamercsw over 7 years
    Updated question to accomodate this as the only vaid answer.
  • orshachar
    orshachar almost 7 years
    java does not allow both -cp and -jar flags: stackoverflow.com/questions/15930782/…
  • Sam
    Sam about 2 years
    Yes, Class-Path entry in manifest file did not support wildcards, but a decent project has symbolic links without the version numbers to link.