How to get an exception thrown from another application in Java? - java

I have the following code which prints the output of the DataIntegrationV8.jar to the JTextArea. Is it possible to print an exception thrown by that program in the same JTextArea?
protected Integer doInBackground() throws Exception {
Process process;
InputStream iStream;
try {
//run the DataIntegration.jar
process = Runtime.getRuntime().exec("java -jar DataIntegrationV8.jar sample.xml");
istream = process.getInputStream();
} catch (IOException e) {
throw new IOException("Error executing DataIntegrationV8.jar");
}
//get the output of the DataIntegration.jar and put it to the
//DataIntegrationStarter.jar form
InputStreamReader isReader = new InputStreamReader(iStream);
BufferedReader bReader = new BufferedReader(isReader);
String line;
while ((line = bReader.readLine()) != null) {
jtaAbout.append(line + "\n");
}
Thread.sleep(1);
return 42;
}

By default exception stacktraces are displayed to System.err. You could include the output from the ErrorStream to the JTextArea.
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errorLine = null;
while ((errorLine = error.readLine()) != null) {
jtaAbout.append(errorLine + "\n");
}

You could check the error code returned by the program and it it is not zero, you know the output is a java stacktrace as the program terminated ...... poorly.

Related

communicating with the process while executing a shell command with java

I'm going to execute a shell command from java and i need to pass arguments to the output stream while executing the command..
following is the shell command
./darknet detect cfg/yolo-voc.2.0.cfg backup/yolo-voc_20000.weights
when executing this command it is yielding for the path of the image file in the terminal i can provide the path of the image as follows
Loading weights from backup/yolo-voc_21000.weights...Done!
Enter Image Path:
when executing from the terminal i can provide the path there.
I managed to execute this command withing the java process and also i can get an output when i provide an image uri with the command. here is the code
public static void execCommand(String command) {
try {
Process proc = Runtime.getRuntime().exec(command);
// Read the output
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
//reader.readLine();
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
s.add(line);
}
// proc.waitFor();
} catch (IOException e) {
System.out.println("exception thrown: " + e.getMessage());
}
}
but what I want is provide the image path at the runtime not beginning of the execution of the command..
tried with writing to the output stream as below still no luck
public static void execCommand(String command) {
try {
Process proc = Runtime.getRuntime().exec(command);
// Read the output
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
writer.append("data/test2.jpg");
writer.newLine();
//reader.readLine();
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
s.add(line);
}
// proc.waitFor();
} catch (IOException e) {
System.out.println("exception thrown: " + e.getMessage());
}
}
You need to call writer.flush() in order to actually output something to the underlining InputStream
Therefore your code should look like:
public static void execCommand(String command) {
try {
Process proc = Runtime.getRuntime().exec(command);
// Read the output
BufferedReader reader = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
String line = "";
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
writer.append("data/test2.jpg");
writer.newLine();
// **** add flush here ****
writer.flush();
// and remember to close your resource too
writer.close();
//reader.readLine();
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
s.add(line);
}
// ***** close your reader also ****
reader.close();
// proc.waitFor();
} catch (IOException e) {
System.out.println("exception thrown: " + e.getMessage());
}
}

Catching a RuntimeException 'cross-borders" in command line -- originated at one jar and thrown in another

I'm explicitly invoking JVM from within the system i'm developing, say systemA. this is by specs-- I have to process the command in another jre instance.
the command to do this is
java -cp thisJar.jar;thatJar.jar -Djava.security.manager=mySM -Djava.security.policy=my.policy TheClass
, and i'm running this command by the use of Process and ProcessBuilder:
StringBuilder sbResult = new StringBuilder();
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process p=null;
try {
p = builder.start();
p.waitFor();
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line = "";
while ((line = br.readLine()) != null)
sbResult.append(line+System.getProperty("line.separator"));
} catch (Throwable t) { commandResult.error.add(t); }
commandResult.text = sbResult.toString();
} catch (Throwable e1) { commandResult.error.add(e1); }
The type CommandResult is plain enough:
public static class CommandResult {
public String text="";
public List<Throwable> error = new LinkedList<>();
public int statusCode;
}
Whenever there's an error "of interest" in systemA, i'm catching and printing it out with e.printStackTrace(). with this, i'm expecting it to be captured by the above code.
However, ti isn't. the error is thrown and echoed on command prompt. however, the BufferedReader in the above code isn't seeing it. I'm guessing this is because the error is happening/originating in one jar and is thrown in a class in the other jar(?).
Is there a way to still capture this error programmatically?
the only way i can think of is have the class throwing the error write it to a file so that the class in the other jar can read it. or hand in the error text to the class in the other jar by invoking a method of it. but there must be a better solution.
TIA.
//--------------------------
UPDATE
following AR.3's useful suggestion, tried the following:
StringBuilder sbResult = new StringBuilder();
ProcessBuilder builder = new ProcessBuilder(command);
Process p=null;
try {
p = builder.start();
p.waitFor();
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line = "";
while ((line = br.readLine()) != null)
sbResult.append(line+System.getProperty("line.separator"));
} catch (Throwable t) { commandResult.error.add(t); }
commandResult.text = sbResult.toString();
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
String line = "";
while ((line = br.readLine()) != null)
sbResult.append(line+System.getProperty("line.separator"));
} catch (Throwable t) { commandResult.error.add(t); }
commandResult.text += sbResult.toString();
} catch (Throwable e1) { commandResult.error.add(e1); }
and
StringBuilder sbResult = new StringBuilder();
ProcessBuilder builder = new ProcessBuilder(command);
Process p=null;
try {
p = builder.start();
p.waitFor();
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
String line = "";
while ((line = br.readLine()) != null)
sbResult.append(line+System.getProperty("line.separator"));
} catch (Throwable t) { commandResult.error.add(t); }
commandResult.text = sbResult.toString();
} catch (Throwable e1) { commandResult.error.add(e1); }
still not seeing that exception. no change from before.
There is no concept of an exception thrown "cross-borders" between Java applications. The forking process and the subprocess are completely independent processes running in different JVMs. Normally an exception would be printed on the error stream of the subprocess. In order to detect such an exception or any error printed on the error stream, you'd need to read that stream, in a way similar to what you did with the output stream.
However, in this case you should remove the statement builder.redirectErrorStream(true); since this statement will redirect the error stream to the output stream, making it difficult to distinguish between the two types of output. In order to catch error output, just read the Process#getErrorStream:
sbResult = new StringBuilder();
// this read the error stream of the subprocess
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
String line = "";
while ((line = br.readLine()) != null) {
sbResult.append(line+System.getProperty("line.separator"));
}
// errorString would contain the error generated by the subprocess, including thrown exceptions
commandResult.errorString = sbResult.toString();
}

Read/Write to command-line .exe Java

I'm trying to launch a process in java, read the output, write to the program, then read what it responds with. From all the other answers on SO, this is what I have come up with:
class Main
{
public static void main(String[] args) {
String line = "";
try {
ProcessBuilder pb = new ProcessBuilder("C:\\myProgram.exe");
Process p = pb.start();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
output.write("foo");
output.newLine();
output.flush();
while ((line = input.readLine()) != null) {
System.out.println(line);
}
p.destroy();
}
catch (IOException e){
}
}
}
It launches the program, and gives me the output just as expected.
When i write foo, I expect the program to come back with another response, but it never does.
What am I doing wrong?

BufferedReader not working as expected

The below code is not getting executed completely after this line " bufferedReader.readLine(); ". The Program works fine when i execute the system command with
out mentioning IPAddress of the remote PC.
class Test
{
public static void main(String arg[])
{
Process p;
Runtime runTime;
String process = null;
try {
runTime = Runtime.getRuntime();
p = runTime.exec("sc \\xx.xx.xx.xx query gpsvc"); // For Windows
InputStream inputStream = p.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = bufferedReader.readLine();
process = "&";
while (line != null) {
line = bufferedReader.readLine();
process += line + "&";
}
StringTokenizer st = new StringTokenizer(proc, "&");
System.out.println("token size "+st.countTokens());
while (st.hasMoreTokens()) {
String testData = st.nextToken();
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
}
} catch (IOException e) {
System.out.println("Exception arise during the read Processes");
e.printStackTrace();
}
}
}
Check your command inside exec method
p = runTime.exec("sc \\xx.xx.xx.xx query gpsvc");
The syntax is wrong here and if you execute this from command prompt, you will be prompted with the below question.
Would you like to see help for the QUERY and QUERYEX commands? [ y | n ]:
And the program wouldn't return until you enter y or n. Since the program is not terminating, you wouldn't be able to read the console output and that's the reason your program is getting stuck on String line = bufferedReader.readLine();

Java Process can't get ErrorStream message

everyone, I have a process that needs to get standard output and log/error/exception output from the subprocess. The standard output is fine, but I can't get ErrorStream, therefore the program is stuck there because of that. Here is my simple code. There is nothing magic, but why can't I get the error stream here? Thanks for looking at it.
BufferedReader standard =
new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader error =
new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = standard.readLine()) != null) {
System.out.println(line);
}
while ((line = error.readLine()) != null) {
System.out.println(line);
}
Now, as suggested, i used two threads to process the output and error streams, but still had the same problem, as follows. Can anybody give me some insights? Thanks.
ProcessBuilder pb = new ProcessBuilder(listArgs);
pb.redirectErrorStream();
Process process = pb.start();
StreamThread output = new StreamThread(process.getInputStream());
StreamThread error = new StreamThread(process.getErrorStream());
output.start();
error.start();
while (true) {
try {
output.join();
break;
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
The definition of the StreamThread:
public static class StreamThread extends Thread{
private InputStream input = null;
public StreamThread(InputStream in){
input = in;
}
String line = null;
public void start(){
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
try{
while( (line=reader.readLine()) != null ){
System.out.println(line);
}
reader.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
Look at your loops:
while ((line = standard.readLine()) != null) {
System.out.println(line);
}
while ((line = error.readLine()) != null) {
System.out.println(line);
}
You're going to keep reading from the output stream until it's finished - which is likely to be when the process terminates. Only then do you start reading the error stream.
You should probably put at least one of these into a different thread, so you can read from both streams at the same time.

Categories