0

I have a main class in 'outer.jar' file. Inside this jar, there is another jar called 'inner.jar' in classes/lib folder. How can I make the inner jar run when I run the outer jar using the command java -jar outer.jar?

My main class is running another jar called 'inner.jar' and consuming the output. Now my application is also packaged as a jar called 'outer.jar' and when I run this 'outer.jar', then the main class is unable to run the inner.jar

outer jar main class code:

public class OuterJarMain{
    public static void main(String[] args) {

            String path = OuterJarMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            ProcessBuilder pb = new ProcessBuilder("java", "-jar", path.substring(1)+"lib/inner.jar", "1");
            try {
                Process p = pb.start();

            } catch (IOException e) {
                e.printStackTrace();
            }

The code works fine when the main class is executed from IDE because the inner.jar is available in target/classes/lib folder. But when I run the outer.jar from command line then the path is displayed as /C:/....../outer.jar!/.../classes!/ and the inner.jar is not executed

firstpostcommenter
  • 2,328
  • 4
  • 30
  • 59

1 Answers1

1

Since files inside jar is archived, you can't access them the same way as normal files.

What you can do is copy the entry inside the jar out to a folder, as demonstrated in this post, and then execute the jar with java -jar , afterwards if you don't need the jar you can call File.deleteOnExit()

EDIT: I modify the code in that post and the example is shown below. The method returns the absolute location of the exported inner jar.

public static String exportInnerJar(){
    String jarDir = ""; 
    try {
        //Get the parent directory of the outer jar.
        jarDir = URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(),"UTF-8");
    } catch (UnsupportedEncodingException e) {
        System.err.println("Fail to find the outer jar location");
        e.printStackTrace();
    }
    //The location of the inner jar
    //The example means the innar jar is at outer.jar/example/inner.jar where "example" is a folder under the root of the outer jar.
    InputStream is = ClassName.class.getResourceAsStream("/example/inner.jar");

    //The location to be exported to, you can change this to wherever you want
    File exportInnerJar = new File(jarDir).toPath().resolve("inner.jar").toFile();

    //Create the file
    exportInnerJar.createNewFile();

    //Use FileOutputStream to write to file
    FileOutputStream fos = new FileOutputStream(exportInnerJar);

    //setup a buffer
    int readBytes;
    byte[] buffer = new byte[4096];

    //export
    while ((readBytes = is.read(buffer)) > 0) {
        fos.write(buffer, 0, readBytes);
    }

    // close streams
    is.close();
    fos.close();

    return exportInnerJar.getAbsolutePath();
}
Judger
  • 208
  • 1
  • 4
  • Hi, I should export the main class of inner jar to some folder of outer jar? I just want to trigger the inner jar and use the output using process.getInputStream() in the outerjarmain.class – firstpostcommenter Nov 29 '17 at 18:06
  • You should export the entire inner jar and execute it. – Judger Nov 29 '17 at 18:24
  • Will this approach work for linux, docker, etc since I would not know the folder to export to? – firstpostcommenter Nov 29 '17 at 18:51
  • You can choose the folder where the export is. I added an example, you can check it out. – Judger Nov 30 '17 at 01:20
  • Hi, My main class is inside the outer.jar. so the jarDir value is not coming correctly – firstpostcommenter Nov 30 '17 at 09:20
  • I tried to copy the inner.jar to system property "java.io.tempdir" location. I get nullpointerexception at `jarDir = URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(),"UTF-8");` when running `java -jar outer.jar`. But from IDE it is working fine – firstpostcommenter Nov 30 '17 at 12:22
  • https://stackoverflow.com/questions/30515915/getresourceasstream-returns-null-only-when-in-jar-file – firstpostcommenter Nov 30 '17 at 12:28
  • I copied the inner.jar from lib folder of my outer.jar to `java.io.tmpdir` location and used processbuilder to run the inner.jar. P.S, All this code is written in the main class which is present in outer.jar – firstpostcommenter Nov 30 '17 at 16:44