apache commons exec

20
Apache Apache Commons Exec Commons Exec Reliably Executing Reliably Executing External Processes External Processes Siegfried Goeschl

Upload: kiara-foley

Post on 02-Jan-2016

52 views

Category:

Documents


3 download

DESCRIPTION

Apache Commons Exec. Reliably Executing External Processes. Siegfried Goeschl. 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. Common Use Cases. - PowerPoint PPT Presentation

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