Tuesday, November 3, 2009

How to run an external processes from a Java program

A QA engineers recently asked for my help invoking an external process from a Java program.
I told him "use java.lang.Runtime.exec" (link opens in a new tab).
It's been a long time since I used it, the opportunity rarely rises.
He struggled with the API, and couldn't understand how to write the output of the process to his Java console.
So I took a longer look in the API and sent this back as an example:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ProcessRunner {

public static void main( String[] args ) throws Exception {
execute( "cmd.exe /c dir" );
execute( "cmd.exe /c java1" );
execute( "java -version" );
execute( "java -versiond" );
}

public static void execute( String cmd ) throws Exception {
Process p = Runtime.getRuntime().exec( cmd );

OutputReader stdout = new OutputReader( p.getInputStream() );
Thread t1 = new Thread( stdout );
t1.start();

OutputReader stderr = new OutputReader( p.getErrorStream() );
Thread t2 = new Thread( stderr );
t2.start();

int status = p.waitFor();
System.out.println( "status " + status );
System.out.println();
}

private static class OutputReader implements Runnable {
InputStream is;
public OutputReader( InputStream is ) {
this.is = is;
}

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

Looks cumbersome, but then many mundane operations in Java feel the same (e.g. read from a file).