Does the JAR entry point really need to be inside the JAR?
A bit of context
I am trying to create a minimal framework using a launcher that will be common across multiple projects. However, I am running into difficulties when it comes to running JARs.
My goal is to have a self-contained command java -jar
: MANIFEST knows the classpath and entry point. The delicate bit is this: since I want the launcher to be common across all projects and be DRY compliant, I have a specific JAR with it that will always be in the classpath.
Now I am having problems starting my jar:
java -jar test.jar
should load the classpath and entry point from the manifest. He finds a manifesto, but I finish Could not find or load main class
.
Running more details works:
java -cp test.jar; lib / * org.keyboardplaying.test.TestLauncher
My question
I haven't found any spec to say if this is possible or not, and this is not a standard case, but can I specify in my MANIFEST.MF an entry point that will be found on the classpath but is not included in my JAR?
Additional Information
My MANIFEST.MF
Manifesto-version: 1.0
Archiver-version: Plexus architect
Created: from Apache Maven
Built: Chop
Build-Jdk: 1.7.0_45
Main class: org.keyboardplaying.test.TestLauncher
Class-Path: lib / slf4j-api-1.7.12. jar lib / logback-classic-1. 1.3.jar lib / logback-core-1.1.3.jar
Notes for people with problems
- I have previously tried
Class-Path: lib/*
which I like better, but you cannot use wild cards for the classpath in manifest 1 . You can still use directories, but the classloader will not check the contents of the jars in that directory.
<sub> 1. One of the sources among others: https://stackoverflow.com/a/749862/ ...
<sub> 2. Very interesting link for entering the MANIFEST class: http://todayguesswhat.blogspot.com/2011/03/jar -manifestmf-class-path-referencing.html
source to share
Does the JAR entry point really need to be inside the JAR?
No, it is not. It is wise to put the launcher in a separate jar file, and as long as it should be fine in the classpath specified by the manifest. Here's an example:
Launching \ Launchable.java:
package launch;
public interface Launchable {
void launch();
}
Launching \ Launcher.java:
package launch;
public class Launcher {
public static void main(String[] args) throws Exception {
System.out.println("I am the launcher!");
Class<?> clazz = Class.forName(args[0]);
Launchable launchable = (Launchable) clazz.newInstance();
launchable.launch();
}
}
demo \ Test.java:
package demo;
import launch.Launchable;
public class Test implements Launchable {
public void launch() {
System.out.println("I am Test, being launched");
}
}
manifest.txt:
Manifest-Version: 1.0
Main-Class: launch.Launcher
Class-Path: launcher.jar
Now compile and run:
$ javac -d . launcher/*.java $ javac -d . demo/*.java $ jar cvf launcher.jar launcher $ jar cvfm demo.jar manifest.txt demo $ java -jar demo.jar demo.Test I am the launcher! I am Test, being launched
source to share