bpelc tool, but I invoked it using Java's ProcessBuilder and Process classes.A friend of mine, Tomek, warned me about problem I might come across by not reading error and input streams.
He was right, some time ago while working on Nuntius 0.5 I wrote an integration test whose goal was to detect WS-BPEL errors. The error output generated by
bpelc was so large that my process blocked itself and waited for the error stream to be read.Today I present a bullet-proof version of my process runner. You can easily refactor this class to run any command line tools from Java.
ProcessBuilder
No comments, just the source code. Note the private
InputStreamReaderThread class which I use for reading both error and input streams:public class BPELCRunner {
private static final Log log = LogFactory.getLog(BPELCRunner.class);
private ProcessBuilder pb;
private String message;
public BPELCRunner(String command, String bpel) {
pb = new ProcessBuilder(command, bpel);
}
public boolean compile() {
Process p = null;
try {
p = pb.start();
InputStreamReaderThread errorReader = new InputStreamReaderThread(p.getErrorStream());
errorReader.start();
InputStreamReaderThread inputReader = new InputStreamReaderThread(p.getInputStream());
inputReader.start();
p.waitFor();
if (errorReader.getInput() != null) {
message = errorReader.getInput();
return false;
}
} catch (Throwable t) {
log.error("Could not validate WS-BPEL process", t);
message = "Error occurred while validating WS-BPEL process";
return false;
}
return true;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
private class InputStreamReaderThread extends Thread {
private InputStream is;
private String input;
public ThreadInputStreamReader(InputStream is) {
this.is = is;
}
@Override
public void run() {
try {
byte[] output = IOUtils.toByteArray(is);
input = new String(output);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getInput() {
return input;
}
}
}I hope this simple class saves you a lot of time :)
Cheers,
Łukasz

6 comments:
Have you seen http://commons.apache.org/exec library? It seems to serve the same purpose, although it's still in Commons Sandbox.
Hi Tomek,
I haven't seen that library before.
For now, I'm happy with my lightweight approach. In my case I just want to run bpelc command line tool, and detect whether it succeeded or not.
But I will keep it in my mind, maybe one day I will need more advanced/complex solution.
thanks,
Łukasz
A w ThreadInputStreamReader nie lepiej zrobić zamiast (!(is.available() > 0)) { Thread.sleep(100); }
nie lepiej po prostu zacząć z is czytać? Wątek i tak się przecież zatrzyma, jak nie będzie inputu.
Zresztą i tak nadpisujesz w każdej iteracji input to to jest średnio przydatne. Jak chcesz po prostu opróżniać bufor to:
public void run() {
is.read(); //No i try catch
}
powinno dać radę.
Czy może ominąłem coś oczywistego?
@jb
Masz rację, kod zaktualizowałem.
dzięki,
Łukasz
Along those same lines, I've created and published something I call JavaInvoke that makes it easy to spawn off additional VMs from a Java process.
Take a look at: http://blog.palantirtech.com/2009/07/28/javainvoke/
Typo on line 37:
ThreadInputStreamReader should be InputStreamReaderThread
Also Thread should be a static class
Post a Comment