Elegant way to check whether external long-term jar launched successfully - java

I am trying to execute external jar from java app.
What is the most elegant way to check if the process has been started successfully and running?
ExtApp.jar is long-term running process, so I can not use Process.waiFor() because it would block my app. I have come up with following code, with idea behind is that the exitValue() throws IllegalThreadStateException if the process has not been yet terminated.
boolean success = false;
try {
Process process = Runtime.getRuntime().exec("java -jar ExtApp.jar");
try {
if (process.exitValue() == 0)
success = true;
} catch (IllegalThreadStateException e) {
success = true;
}
} catch (Exception e) {}
System.out.println(success);
But it is kind of ugly solution. Any ideas for a better one?

There seems to be no elegant solution to the problem. E.g. I ran your code on my PC and got "success" though there is no ExtApp.jar on it. That is, from the point of view of Runtime.exec the process (java.exe) started successfully, no matter what happens afterwards.

The above seems very dubious. You're going to spawn off your process and then test it immediately. The process itself may not have determined whether it's running ok or not (e.g. when does it actually check that jar file eixsts/is loadable/is valid ?)
I think you're better off spawning the process via a new thread, calling/blocking in that thread via Process.waitFor() and then notifying the parent thread (via whatever means - state variable, wait()/notify(), a java.util.concurrent.Future etc.) once the process has exited and you've collected the exit status.
Apache Commons Exec is a useful library for doing this sort of work, including asynchronous spawning/notification of process exit. See the DefaultExecuteResultHandler for more info.

Related

How to detect an external process crash in Java?

I am working on an application that needs to launch a process and wait for its output. Sometimes the process crashes (very often,) but is not really an issue since I have mitigation tasks. The problem is that Windows detects the process crashed and prompts for user input, to either check for a solution online, or just close the program.
I tried to solve this by waiting for the process to complete in a Runnable submitted to an ExecutorService and using the Future returned to specify a timeout. Speed is not really a concern for the application, and the external process is supposed to run for just a couple of seconds.
This is the code I am using:
final Process process = ...
final ExecutorService service = Executors.newSingleThreadExecutor();
try {
final Future<?> future = service.submit(new Runnable() {
#Override
public void run() {
try {
process.waitFor();
} catch (InterruptedException e) { /* error handling */}
}
});
future.get(10, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
// The process may have crashed
process.destroy();
} catch (final Exception e) {
// error handling
} finally {
service.shutdown();
}
The code above worked well, but the crash dialog still pops up and it doesn't go away without user interaction.
This question presents a similar problem but from a .Net perspective and
proposes to suppress the pop up through the Windows registry, which I cannot do, given that its effect is global to all process in the machine.
Is there a way to prevent the dialog from being displayed at all?
or
Is there a way to detect the application crash and handle it directly
from Java without needing user interaction?
Additional details:
I don't have the source of the external process.
The external process is a console based application (i.e. no GUI.)
Preferably I'm looking for a pure Java based solution (no JNI.)
Thank you.
As already suggested you should use SetErrorMode win32 call. It won't change for the whole system but only for your process and it's children (which is what you want apparently).
The correct call seems to be :
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
See also the MSDN documentation :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx
Regards.

Hanging thread in SOAPUI Tests in Java app

I am trying to execute my SOAPUI test suites through a Java app rather than on the UI. However, when creating a WSDLProject a thread is starting that never gets killed, so when my code is executed and all the tests are run, the app doesnt end as this thread is still sitting there.
It looks like an AWT Daemon Thread
In the Eclipse Debugger:
Daemon Thread [AWT-Windows] (Running)
Here is my code:
WsdlProject projectName = String.format(
"src/main/resources/%s-soapui-project.xml", projectName);
WsdlProject project = new WsdlProject(projectName); //This line starts the thread
List<TestSuite> testSuites = project.getTestSuiteList();
//Loop over each testsuite
//Loop over each test case
Does anyone know how to kill this thread?
Ive searched and searched the SOAPUI API, but the documentation is terrible and I cant find any decent examples of how to approach this.
For the past two days I have been struggling with the same problem. I have a solution which may help. The reason your does not end is not the AWT-Windows thread. The culprit is the thread labeled "Thread-2" which is of type SoapUIMultiThreadedHttpConnectionManager.IdleConnectionMonitorThread
Unfortunately this thread which is created when you instantiate WsdlProject, has no directly accessible shutdown method. This is what I had to do in-order to shut it down and have the JVM exit when my main routine exits:
Have your main method or some other method execute the following at the end:
// Need to shutdown all the threads invoked by each SoapUI TestSuite
SoapUI.getThreadPool().shutdown();
try {
SoapUI.getThreadPool().awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Now to shutdown the monitor thread setup by SoapUI
Thread[] tarray = new Thread[Thread.activeCount()];
Thread.enumerate(tarray);
for (Thread t : tarray) {
if (t instanceof SoapUIMultiThreadedHttpConnectionManager.IdleConnectionMonitorThread) {
((SoapUIMultiThreadedHttpConnectionManager.IdleConnectionMonitorThread) t)
.shutdown();
}
}
// Finally Shutdown SoapUI itself.
SoapUI.shutdown();
Although ugly, I hope this solution helps you.
I have fixed this with the following solution. It is not ideal but I could not find a way round this and the SOAP UI documentation is incredibly painful.
Firstly, I save the results of each test step to an xml file.
Next, once the tests have run I exit:
System.exit(runner.getOverallResult() ? 0 : 1);
Finally, another app executes this through a command line .sh script. After executing it the other app reads the XML file to determine the results.

Order a Runtime exec and a ProcessBuilder.start?

I've been confronted to a weird problem while running and killing processes through java.
Basically, I have a method which kills one process using taskkill :
private static void kill() {
try {
Runtime.getRuntime().exec("taskkill /F /IM app.exe");
} catch (IOException e) {
e.printStackTrace();
}
}
I call this method to be sure all the processes are killed before I start a new one :
kill();
ProcessBuilder procBuilder = new ProcessBuilder(args);
try {
Process p = procBuilder.start();
} catch (Exception e) {
e.printStackTrace();
}
The problem is the process started seems to be killed by the taskkil. Without the call to kill, it works perfectly fine; while with the kill, the process starts but the GUI doesn't appear.
Is this a problem of priority between the two calls ? (a runtime.exec would be of lower priority than a ProcessBuilder.start ?).
I've solved that using a waitFor on the return of the Runtime exec but I'm curious about why this problem appeared.
Basically the Runtime.exec starts a new process in the OS asynchronously, and there is no guarantee that it is finished before your new process is started. Theoretically you sould wait for the taskkill to return with a SUCCESS result and start your new job only after that. According to its documentation taskkill will tell you with 0 return code if it has successfully killed its suspect.
The issue is not priority related, since both of them will have the default priority. A possible issue is that Runtime.exec using a String will have to parse the input and then execute the command, while ProcessBuild will execute the given command without the needed parsing logic. Because of this you can see a small delay and you need the waitFor to work as intended. You can eliminate this delay by using the String[] version of the Runtime.exec.
Also note that the threads are scheduled by the system scheduler and the execution order is unpredictable, see Java thread unpredictable.

Regarding shutdownhook understanding

I was going through shutdown hook feature of java , My analysis was ..shutdownhook allows to register a thread that will be created immediatly but started only when the JVM ends ! So it is some kind of "global jvm finalizer", and you can make useful stuff in this thread (for example shutting down java ressources like an embedded hsqldb server). This works with System.exit(), or with CTRL-C / kill -15 (but not with kill -9 on unix, of course).
Please advise more practical uses and please also if possibe an small example will help to make understanding more clear..!
When a shutdown hook is added to a Runtime instance, it is added to a list of Threads to start upon clean termination of the JVM.
Example: Using shutdown hook to ensure that a java.awt.TrayIcon is removed from the system tray.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
if (SystemTray.isSupported()) {
SystemTray.getSystemTray().remove(yourTrayIcon);
}
} catch (Exception e) {
// failed to remove
e.printStackTrace();
}
}
});
More can be read in the offical documentation.

How can I interrupt IMAP's IDLE?

I am using the Javamail API connecting to my IMAP server. Everything is working great with the javax.mail.Folder.idle() method. My listener gets called when a new mail comes in. However the problem is idle blocks forever, how do I interrupt it? How do I actually stop the listening without killing my Java program?
I've tried calling Thread.interrupt() on the idle'd thread. Nothing happens. I am running out of ideas.
Performing any operation on that folder (from another thread) will cause idle() method to return immediately. So if you want to forcefully interrupt it, just call close() from a new thread.
If you read the documentation properly, and read the source code, you'll realise that you have to create a new thread for calling .idle().
Allocate that thread to a variable, and whenever you want call the interrupt() on that thread, or just ignore notifications!
If you need to get idle() going again, just rerun the thread!
I created something similar, so you might wanna check it out.
https://github.com/mofirouz/JavaPushMail/blob/master/src/main/java/com/mofirouz/javapushmail/JavaPushMailAccount.java
Good luck
A proper way to abort IDLE command is the following snippet. Note that the Folder instance should be the same as the one used to start idling. I've tested the other solutions proposed on this thread but they didn't work in my case.
IMAPFolder folder = store.getFolder("INBOX");
try {
folder.doOptionalCommand("Abort IDLE error mesage", new IMAPFolder.ProtocolCommand() {
#Override
public Object doCommand(IMAPProtocol p) throws ProtocolException {
p.idleAbort();
return Boolean.TRUE;
}
});
} catch (MessagingException e) {
e.printStackTrace();
}

Categories