Download - Apache Commons Exec

Transcript
Page 1: Apache  Commons Exec

Apache Apache Commons ExecCommons Exec

Reliably Executing Reliably Executing

External ProcessesExternal Processes

Siegfried Goeschl

Page 2: Apache  Commons Exec

History

• Code originated from Apache Ant

• Started 2005 by Niclas Gustavsson

• Dormant in the Commons Sandbox

• Resurrected in 2008

• In 2009 release of version 1.0

• Version 1.1 just hit the road

2Apache Commons Exec

Page 3: Apache  Commons Exec

Common Use Cases

• ImageMagick to convert images

• Foxit Reader for printing PDFs

• WinSCP for secure file transfer

3Apache Commons Exec

Page 4: Apache  Commons Exec

Why To Use Commons Exec

“How to bring down an Application

Server?!”

“How to bring down an Application

Server?!”

Launch an external process!

4Apache Commons Exec

Page 5: Apache  Commons Exec

The Problems Ahead

• JDK provides only low-level API– ProcessBuilder & Runtime– Difficult to use– Error prone

• When you mess up– Synchronization Issues– Resource Depletion

5Apache Commons Exec

Page 6: Apache  Commons Exec

Synchronization Issues

• Process.waitFor can wait forever– Launched process may never terminate

• Process output must be promptly consumed to avoid deadlock– Writes into a fixed-size buffer

• Process.waitFor does not clear thread interrupt flag when it throws InterruptedException

6Apache Commons Exec

Page 7: Apache  Commons Exec

Resource Depletion Ahead

• Process resources are not automatically freed until finalization– Leaves stdin, stdout, stderr open

• Process.destroy() might not work– OpenVMS

• Process.destroy() doesn’t kill process grandchildren depending on OS– Affects all Windows platforms

7Apache Commons Exec

Page 8: Apache  Commons Exec

What is the one thing you What is the one thing you want your audience to want your audience to

remember?!remember?!8Apache Commons Exec

Page 9: Apache  Commons Exec

9Apache Commons Exec

Page 10: Apache  Commons Exec

How I Became Contributor

“Siegfried, can we actually print a PDF invoice?!”

“Siegfried, can we actually print a PDF invoice?!”

Sure!

10Apache Commons Exec

Page 11: Apache  Commons Exec

The First Print Job

String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();int exitValue = executor.execute(commandLine);

String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();int exitValue = executor.execute(commandLine);

Blows up because the exit code ‘1’ is always returned!Blows up because the exit

code ‘1’ is always returned!

11Apache Commons Exec

Page 12: Apache  Commons Exec

Handling the Exit Value

String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);int exitValue = executor.execute(commandLine);

String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);int exitValue = executor.execute(commandLine);

Got stuck when printerwas out of paper!

Got stuck when printerwas out of paper!

12Apache Commons Exec

Page 13: Apache  Commons Exec

Tame the Runaway Process

String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);executor.setWatchdog(watchdog);int exitValue = executor.execute(commandLine);

String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);executor.setWatchdog(watchdog);int exitValue = executor.execute(commandLine);

Failed miserably when printing 'C:\\Document And Settings\\documents\\

432432.pdf'

Failed miserably when printing 'C:\\Document And Settings\\documents\\

432432.pdf'

13Apache Commons Exec

Page 14: Apache  Commons Exec

Quoting Is Your Friend

String fileName = file.getAbsolutePath();String line = "AcroRd32.exe /p /h \"“ + fileName + "\"";CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);executor.setWatchdog(watchdog);int exitValue = executor.execute(commandLine);

String fileName = file.getAbsolutePath();String line = "AcroRd32.exe /p /h \"“ + fileName + "\"";CommandLine commandLine = CommandLine.parse(line);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);executor.setWatchdog(watchdog);int exitValue = executor.execute(commandLine);

Building the command line sucks!

Building the command line sucks!

14Apache Commons Exec

Page 15: Apache  Commons Exec

Incremental Command Line CommandLine cmdLine = new CommandLine("AcroRd32.exe");cmdLine.addArgument("/p");cmdLine.addArgument("/h");cmdLine.addArgument("${file}");Map map = new HashMap();map.put("file", new File(„invoice.pdf"));cmdLine.setSubstitutionMap(map);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);executor.setWatchdog(watchdog);int exitValue = executor.execute(cmdLine);

CommandLine cmdLine = new CommandLine("AcroRd32.exe");cmdLine.addArgument("/p");cmdLine.addArgument("/h");cmdLine.addArgument("${file}");Map map = new HashMap();map.put("file", new File(„invoice.pdf"));cmdLine.setSubstitutionMap(map);DefaultExecutor executor = new DefaultExecutor();executor.setExitValue(1);ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);executor.setWatchdog(watchdog);int exitValue = executor.execute(cmdLine);

Would be nice to printin the background!

Would be nice to printin the background!

15Apache Commons Exec

Page 16: Apache  Commons Exec

CommandLine cmdLine = new CommandLine("AcroRd32.exe");cmdLine.addArgument("/p");cmdLine.addArgument("/h");cmdLine.addArgument("${file}");Map map = new HashMap();map.put("file", new File("invoice.pdf"));commandLine.setSubstitutionMap(map);

DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);Executor executor = new DefaultExecutor();executor.setExitValue(1);executor.setWatchdog(watchdog);executor.execute(cmdLine, resultHandler);

// some time later ...int exitValue = resultHandler.waitFor();

CommandLine cmdLine = new CommandLine("AcroRd32.exe");cmdLine.addArgument("/p");cmdLine.addArgument("/h");cmdLine.addArgument("${file}");Map map = new HashMap();map.put("file", new File("invoice.pdf"));commandLine.setSubstitutionMap(map);

DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);Executor executor = new DefaultExecutor();executor.setExitValue(1);executor.setWatchdog(watchdog);executor.execute(cmdLine, resultHandler);

// some time later ...int exitValue = resultHandler.waitFor();

16Apache Commons Exec

Page 17: Apache  Commons Exec

Tips and Tricks (1)

• Creating complex command line– CommandLine.parse() is fragile when

mixing single & double quotes– Build the command line incrementally– You can control quoting per argument– Use “printargs” script for debugging

17Apache Commons Exec

Page 18: Apache  Commons Exec

Tips and Tricks (2)

• Redirecting streams– Redirection is implemented by the shell

• Killing a process– Killing a process works (mostly)– Its child processes might not be killed at

all depending on your OS (Windows)– If in doubt avoid convenience scripts to

start a process

18Apache Commons Exec

Page 19: Apache  Commons Exec

Conclusion

• Using plain Java API is error prone– Deadlocks– Resource Depletion

• Use commons-exec instead– Automatic stream pumping– Killing of run-away processes– Asynchronous processing

19Apache Commons Exec

Page 20: Apache  Commons Exec

Resources• http://commons.apache.org/exec/

• http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

• http://kylecartmell.com/?p=9

• http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4890847

• http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092

20Apache Commons Exec


Top Related