Best Way to Launch External Process from Java Web-Service?

心已入冬 提交于 2020-01-01 18:53:27

问题


I've inherited a Java web-services code-base (BEA/Oracle Weblogic) and need to start/launch an external background application from a web-service.

I've already tried:

ProcessBuilder pb = new ProcessBuilder(arg);
pb.start();

as well as:

Runtime.exec(cmdString);

But am experiencing strange behaviors when launching applications in this manner (i.e. the launched application stops working even though the process is still active. -- The application works fine when manually run from a normal command line).

Is there a better way to launch an external processes?

EDIT: ----------------------

I have some additional information that may help shed some light on the problem.

  • The process we are trying to start will require hours to complete so waiting for completion (using waitfor()) in the webservice will not be an ideal scenario.
  • Yes, the process we are trying to start from the webservice was created by a fellow team member [cue: your eyes roll... now]

I have had success when I use process builder to start a bash script, where the external application is launched as a background process (using "&").

#!/bin/bash
java -jar myApp.jar &

This obviously creates an orphaned process but at least the application does continue to execute.


回答1:


Simply put: if the launched application writes to SDTOUT/STDIN and you don't flush them frequently (see Process.getErrorStream/Process.getInputStream) then the process will block when the buffer is full (that is really small, 4KB or less).

I recommend you to invoke ProcessBuilder.redirectErrorStream() before starting the process. Then, after that, create a thread with the run() method along the lines of:

public void run() {
    BufferedReader reader = 
        new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}



回答2:


By "stops working even though the process is still active" I am assuming you might be expecting some output from the application you have launched and not getting anything.

Try using the following:

ProcessBuilder pb = new ProcessBuilder(arg);
Process p = pb.start();
p.waitFor();

waitFor() causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.

http://java.sun.com/javase/6/docs/api/java/lang/Process.html#waitFor()




回答3:


Firstly, is this happening on Windows or on Linux? Also, what is the launched application supposed to more or less do? (is it a script? is it a binary? is it your binary?)

EDIT

OK, so starting a bash script (using ProcessBuilder) which in turns spawns a new JVM (java -jar myApp.jar) works.

What happens exactly when you try to spawn the new JVM directly using ProcessBuilder? You originally said:

the launched application stops working

  1. By launched application do you mean "java -jar myApp.jar", when invoked directly, not via an intermediate bash script?
  2. What are the exact and complete parameters (and their values) you pass to the various ProcessBuilder methods (and in which order) when you try to launch Java directly and this new JVM stops working? (e.g. provide annotated code)
  3. If you install lsof on your *nix machine, what file is shown to be associated with file descriptor 2 (look at the FD column) when running: lsof -p 1234 (where 1234 is the process ID of the "hung" JVM?) It might be interesting to attach the entire output of the lsof command here.
  4. What is appended to the file you have identified in step 3 above (for file descriptor 2), up to several seconds after you issue the command: kill -QUIT 1234 (where 1234 is the process ID of the "hung" JVM?)



回答4:


Are you properly handling the standard input and output of the process? If the standard input or output is being processed by your application and you are not properly handling it, then the process you execute will hang waiting for I/O.

A way to test this is to write a script that runs your program, redirecting standard input, output and error to files. Then have your web service app run the script instead of the program. If the program runs to completion this way, then the problem is handling of the output of the process.




回答5:


I'm guessing that the problem might be the thread that launches the process gets TERMINATED or whatever after the request is over. Try having a single thread in the applicaton that you are sure is kept alive always, you can use this for starting the processes by making calls to it from other threads.



来源:https://stackoverflow.com/questions/644511/best-way-to-launch-external-process-from-java-web-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!