Execute Another Jar in a Java Program

how to run a java executable jar in another java program

This works For Me..

public class JarRunner {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "C:\\JCcc.jar");
pb.directory(new File("C:\\"));
try {
Process p = pb.start();
LogStreamReader lsr = new LogStreamReader(p.getInputStream());
Thread thread = new Thread(lsr, "LogStreamReader");
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}

class LogStreamReader implements Runnable {

private BufferedReader reader;

public LogStreamReader(InputStream is) {
this.reader = new BufferedReader(new InputStreamReader(is));
}

public void run() {
try {
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

This is what the Docs says-

ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");

You can pass any number of arguments in constructor.

Read more about process builder here.

Run a jar File from java program

Using ProcessBuilder(java.lang.ProcessBuilder) will solve your problem. Syntax is as follows -

ProcessBuilder pb = new ProcessBuilder("java", "-jar", "absolute path upto jar");
Process p = pb.start();

You can redirent input/output/error to/from files as follows

File commands = new File("absolute path to inputs file");
File dirOut = new File("absolute path to outputs file");
File dirErr = new File("absolute path to error file");

dirProcess.redirectInput(commands);
dirProcess.redirectOutput(dirOut);
dirProcess.redirectError(dirErr);

Java run jar from another jar with passing arguments

Here we are , below two different example which answer to your question

Process proc = Runtime.getRuntime().exec("java -jar C:\\...\\Run1.jar 1");
proc.waitFor();

//2 inputstream for the result and for the errors in subprogram
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();

byte b[]=new byte[in.available()];
in.read(b,0,b.length);
System.out.println(new String(b));

byte c[]=new byte[err.available()];
err.read(c,0,c.length);
System.out.println(new String(c));

ProcessBuilder pb = new ProcessBuilder("java", "-jar", "C:\\...\\Run1.jar", "1");
Process proc2 = pb.start();
proc2.waitFor();

InputStream in2 = proc2.getInputStream();
InputStream err2 = proc2.getErrorStream();

byte b2[]=new byte[in.available()];
in.read(b,0,b.length);
System.out.println(new String(b));

byte c2[]=new byte[err.available()];
err.read(c,0,c.length);
System.out.println(new String(c));

Output from IDE (Eclipse)

Sample Image

Output from command line :

Sample Image

Note: the "ok" is a my System.out.println i put in Run1.jar ( i saved the files jar with capital letter , but you can use yours names )

How to execute the jar file from a java class

Do following:

Runtime.getRuntime().exec("java -jar <PATH_OF _JAR>");

in your Main class.

And as @Yoav has suggested. You need to take care of errors by adopting proper error handling strategy.

Do Read - https://www.tutorialspoint.com/java/lang/runtime_exec.htm

Running a jar from within another jar

I hate having to answer my own question, but in this case I feel like it needs to be done...

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import org.w3c.dom.Document;

public class updater {
public static void main(String[] args) throws IOException {
try{
DefaultHttpClient httpclient = ClientMaker();
HttpGet get = new HttpGet("http://encorpops04:8080/Updater-test/Version.xml");
HttpResponse response = httpclient.execute(get);
InputStream in = response.getEntity().getContent();

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(in);

//Parse the Xml.
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//version/number/text()");
String result = (String) expr.evaluate(doc, XPathConstants.STRING);
System.out.println(result);

File f = new File(System.getProperty("user.dir")+ "\\Version.xml");
in = new FileInputStream(f) ;
doc = builder.parse(in);
expr=xpath.compile("//version/number/text()");
String result2 = (String) expr.evaluate(doc, XPathConstants.STRING);
System.out.println(result2);

if(Double.parseDouble(result2) < Double.parseDouble(result)){
HttpGet get2 = new HttpGet("http://encorpops04:8080/Updater-test/MyOutput.jar");
HttpResponse response2 = httpclient.execute(get2);
InputStream in2 = response2.getEntity().getContent();
File f2 = new File("MyOutput.jar");
OutputStream fos = new FileOutputStream(f2);
byte buf[] = new byte[1024];
int len;
while ((len = in2.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fos.close();
in.close();
}
System.out.println("cmd.exe /C javaw -jar" +System.getProperty("user.dir") + "\\MyOutput.jar");
Process p = Runtime.getRuntime().exec("cmd.exe /C javaw -jar " +System.getProperty("user.dir") + "\\MyOutput.jar");
p.waitFor();
p.destroy();
}catch(Exception e){ e.printStackTrace(); }

}

public static DefaultHttpClient ClientMaker() {
int connectiontimeout = 30000; // 1 second int sockettimeout = 1000;
HttpParams httpparameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpparameters,
connectiontimeout);
HttpConnectionParams.setSoTimeout(httpparameters, connectiontimeout);
DefaultHttpClient httpclient = new DefaultHttpClient(httpparameters);
return httpclient;
}

}

Version.xml looks like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<version>
<number>1.0</number>
</version>

Sidenote- I didn't make version.xml update automatically, you can either edit the number in there to match, or just pull the one that you check against to replace it.

How to Run a jar from another jar and show the console output from the first runnable during the execution

Buffered/unbuffered

It seems like an issue with buffered output.

Executed process (in this case java -jar <path>) buffers output and writes it only when it's done (in big chunks, we don't like that!)

So one way to go is execute process through unbuffering (very hacky tools):

  • unbuffered <command>
  • stdbuf -i0 -o0 -e0 <command>
  • use terminal emulation

Hacking

stdbuf is part of GNU tools.

https://www.gnu.org/software/coreutils/manual/html_node/stdbuf-invocation.html

unbuffered is part of expect package.

https://wiki.tcl.tk/3548

The key thing is making the program thinking that it's in interactive mode (like you are launching it from console).

The first two options are very hacky and do not work in all cases (idk if java command works with them?)

Emulation

The third option is most promising.
We launch a program (terminal emulator) that emulates interactive terminal making program think it's working in real active session!

Pty4j

You might use pty4j too:

From there: https://github.com/traff/pty4j


// The command to run in a PTY...
String[] cmd = { "java", "-jar", "path_to_jar" };
// The initial environment to pass to the PTY child process...
String[] env = { "TERM=xterm" };

PtyProcess pty = PtyProcess.exec(cmd, env);

OutputStream os = pty.getOutputStream();
InputStream is = pty.getInputStream();

// ... work with the streams ...

// wait until the PTY child process terminates...
int result = pty.waitFor();

// free up resources.
pty.close();

Zt-exec

Maybe it's worth trying zt-exec?

I have no idea how it executes commands.

But it may be it (I didn't test that).

Using https://github.com/zeroturnaround/zt-exec


new ProcessExecutor().command("java", "-jar path_to_jar")
.redirectOutput(new LogOutputStream() {
@Override
protected void processLine(String line) {
...
}
})
.execute();

That should work, but I didn't test that.
In general, there are no ways to nicely resolve your problem.

Depending on what platforms you want to target consider using unbuffered, stdbuff or the (slowest) terminal emulation...

Please let me know if that helps and good luck! :)



Related Topics



Leave a reply



Submit