3

I need to execute an external application which returns large data (takes more than 2 hours to complete ) nand which continuously outputs data.

What I need to do is execute this program asynchronously and capture the output in a file. I tried using java process builder, however it seems to hang and return output only when the program is exited or forcefully terminated.

I tried to use process builder and spwaned a new thread to capture the output, but still it did not help.

Then I read about apache commons exec and tried the same . however this also seems to be taking a long time and returns different error codes ( for the same input)

CommandLine cmdLine = new CommandLine("/opt/testsimulator");

    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
    ByteArrayOutputStream stdout = new ByteArrayOutputStream();
    PumpStreamHandler psh = new PumpStreamHandler(stdout);
    ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
    Executor executor = new DefaultExecutor();
    executor.setStreamHandler(psh);
    executor.setWatchdog(watchdog);
    try {
        executor.execute(cmdLine);
    } catch (ExecuteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Any help or working examples whould be very helpful

3
  • Is running the program from Java a hard requirement? Seems to me you should just execute the command from the shell and pipe it's output to your target file. Commented May 19, 2012 at 12:35
  • I've done this using ProcessBuilder, taking care to handle the input stream and the error stream, and have had no problems. Perhaps you've got a bug in your program. Commented May 19, 2012 at 12:41
  • Remember to accept an answer below if it helped you. Commented Mar 13, 2015 at 13:04

1 Answer 1

5

Huh. Using ProcessBuilder should work for your configuration. For example, the following pattern works for me:

ProcessBuilder pb = new ProcessBuilder("/tmp/x");
Process process = pb.start();
final InputStream is = process.getInputStream();
// the background thread watches the output from the process
new Thread(new Runnable() {
    public void run() {
        try {
            BufferedReader reader =
                new BufferedReader(new InputStreamReader(is));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            is.close();
        }
    }
}).start();
// the outer thread waits for the process to finish
process.waitFor();

The program that I'm running is just a script with a whole bunch of sleep 1 and echo lines:

#!/bin/sh
sleep 1
echo "Hello"
sleep 1
echo "Hello"
...

The thread reading from the process spits out a Hello every second or so.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, there was some problem with my external application and hence the process builder was hanging. The above code works perfectly fine. I had one more question. I want to execute the program asynchronously and still save the output to a file. If I do not use process.waitFor(); the program would terminate without saving the output. Is there any way of achieving this?
You do not need to record the Process result. If you just ignore it once the process finishes it should just get GC'd. In my example, the thread is not marked as daemon. If the main program finishes then it will wait for the thread to complete. If you don't want it to wait then you can do a thread = new Thread(...); thread.setDaemon(true); thread.start();` pattern.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.