Launch a windows batch file from Java GUI Application - java

I have created a Desktop Application using Java Swing. It takes some input from user, creates a config file and a batch file to run a python scripts. Many concerns are:
- I want the GUI to be in active mode when the batch file execution in progress
- There is a button like ShowLog in the app to check the console output at during execution. That should work on clicking
- I have a "Task in Progress" kind of message in GUI which should be replaced by "Task is Completed" when batch file execution is done
- A "Stop" button also is there to stop the batch file execution forcefully. That should work fine as well
(Note: The batch file execution will take hours to complete)
Can anybody come up with some ideas how I can achieve all these?

As you seem to be aware, Swing is a single threaded framework, which means that anything that is run within the context of the Event Dispatching Thread will prevent it from updating the screen or responding to user input.
The basic solution would be to use a Thread to run the batch process in, but this raises issues with synchornisation of updates to the UI, as you should never modify or interact with the UI from outside the context of the EDT.
A better solution would be to use a SwingWorker, which provides you with the ability to run long running tasks in the background, but provides you with the ability to publish updates to and process updates within the context of the EDT, it also provides you with a done method which is called after the doInBackground method exits and is called within the context of the EDT.
Finally, it provides you with a cancel option - This, however is where the problem occurs. Presumably you will be reading the input from the process in a secondary thread and will be waiting for the process to exit within the same thread (SwingWorker) you started it. SwingWorker relies on the interrupt funcitonality of Thread which may not trigger the waitFor method to return.
Having now gone a read the Process documentation, waitFor does throw an InterruptedException
if the current thread is interrupted by another thread while it is
waiting, then the wait is ended and an InterruptedException is thrown.
This would suggest that when done is called, you would need to call isCancelled to check if the worker was cancelled or not. If it was you would need to call destroy on the Process and shut down any secondary Threads you might have running.
You could use an additional SwingWorker to read the input from the process and utilise it's publish/process functionality to update the logs.
This would mean, you would start a SwingWorker to execute your external process. This would presumably be done in response to some event, like a button push.
When this worker's doInBackground method is called, it would execute the external process and call Process#waitFor. This would stop the doInBackground method from returning until the process has exited.
Before you call Process#waitFor, you could create another SwingWorker and pass the Process's OutputStream to it. This would allow this worker to process the output from the process independently. You would then be able to use this to send output of the process back to the EDT via the SwingWorker's publish/process functionality which could be added to something like a JTextArea.
This would save you a lot of hassle with dealing with SwingUtilities.invokeLater.
Do you need the second work? That depends on what you want to the workers to do. I tend to process all the output of external process in separate threads and allow who ever created the process to use waitFor, it isolates the responsibility a little more and prevents the IO from getting locked up an never reaching waitFor, but that's just me.
Take a look at Concurrency in Swing for more details

You can run bat file in java with Runtime
Runtime.getRuntime().exec("cmd /c start your_batch_file.bat");

Related

Jython, stop script execution from inside of Java code

I'm using Jython as a scripting engine in my Java app.
I can run any Jython script from my Java app by calling pi.execfile(script_name). But the problem is that I also need a way to stop script execution manually from Java code. How can I stop it without modifying Jython script?
I'm running a script in a separate thread, so tried to interrupt it via
scriptRunningThread.interrupt(); and catch InterrupredException, but the thread just suspend and hang... Newly created threads will be hang too
Another way - to share a common object and make Jython script to check if user wants to quit.
The 3rd way is to run a separate process (console mode of my app) and kill it when ever STOP button being pressed. But I don't like this solution...
Any suggestions?
The best way is your second idea: to have the Jython script check for a termination flag and exit cleanly if the flag is set.
If you wanted to terminate the thread from another thread, you could call Thread.stop(), but that is generally a bad idea since it could cause your entire application to hang or otherwise misbehave in certain circumstances.

JNI - Java exits before native threads finish executing

I'm in the early stages of developing an API in C++, which I'm wrapping in Java using JNI. The native code creates a socket listener thread using WinAPI which should run indefinitely, thereby keeping the program open indefinitely (tested and works fine).
However, when I try to invoke this code in Java, the JVM still terminates when it reaches the end of main, ignoring the running thread. A little research has hinted that Java might think the thread is a daemon rather than a "user thread". But if that's the case, then I can't quite figure out how to convince Java that it actually is a user thread.
Does anyone have a clue about this?
You need to call AttachCurrentThread() for all your native threads, to ensure Java knows about them, so it will wait for them to finish.
Windows doesn't have daemon threads. The process exits when ExitProcess() is called or when the initial thread returns from the application's main function. (In principle, it will also exit if the last thread exits, but that can't be relied upon because Windows may create threads in your process that you don't know about.)
The Java runtime presumably waits for all of its own threads to exit (except for those that it considers daemon threads) before exiting the process. But your threads were created directly via the Win32 API, so Java doesn't know about them and therefore won't wait for them.
If your API wants to continue performing some task beyond the natural lifetime of the calling process, it should probably create a child process rather than a thread. (Or, if the API is Java-specific, it can presumably make use of JNI to ask that Java create the thread on its behalf, or to register the thread with Java.)

Keeping java subprocess alive in background

I have a class with a method that creates a process using process builder. I then have 2 other methods that use global variables to write commands and collect responses from the process.
I want to start the process from another class and then be able to write commands using the other methods as I wish from this original class. However, I can't see a way to keep the sub-process alive. If I use .waitFor() then I'm unable to run any other commands as it hangs (waiting for the sub-process to exit). But if I just leave the create method to complete, once I've returned to the original class and call the input method the process has been killed. Is there any way to keep the process alive but asleep? Allowing the program to continue but being able to call back to it.
You need to run your subprocess in new Thread. If you are not familiar with concept of multi-threading and concurrent processing check out this article: http://www.vogella.com/tutorials/JavaConcurrency/article.html
Further if you want your subprocess to live after your main program has finished, you need to set that thread to be daemon thread.
To learn more about Thread and daemon threads checkout Java documentation: http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html

how to run shell script asynchronously from within Java program

I want to run a shell script from within a Java program asynchronously-- i.e. after the java program starts execution of that shell script, it carries on with other operations-- and does some further work only when the shell script returns a response to it.. i.e. it does not explicitly stop and wait for the shell script's response.
Is this possible/feasible? How do I implement such functionality?
Basically i will be monitoring multiple servers using a single server that will manage all those servers-- for this it will run shell scripts on each of those servers...since there are many servers, and in java its recommended that number of threads not exceed number of cpu cores... hence I need a solution to this problem, that is not dependent on threading (because of threading limitations)...so that I can simultaneously (or near-simultaneously) fire off many such shell scripts without waiting for one of those scripts responses' (as waiting would affect processing for other shell script commands)... another issue.. the shell commands need to be invoked either on local machine or on remote machines and response is needed from both types of shell script execution(viz local execution and remote execution)...
did you try anything?
you can try something like:
ProcessBuilder builder = new ProcessBuilder("your command to launch script");
Process process = builder.start();
And it does NOT wait by default for the process to complete, so you can execute your code next.
And if you want to do some processing after the process is finished you can try:
int exitVal = process.waitFor();
When you execute another process and want to obtain a result from it, you usually have to read the output of that process, as the process might block if its output buffer becomes full. The easiest way to achieve this is by having a single thread in your Java application which starts the script and then reads its output into some buffer. Other threads of the Java application can do whatever they want to do, and if the process is done, the thread can signal others about that event and then terminate.
I don't know where your recommendation to not use more threads than CPUs originates from, but I'd not hold with that in general. This is true for worker threads, where each active thread keeps one core busy, but in your case, most threads would be idle most of the time. There is some OS level resource overhead associated even with idle threads, so if there are really really many processes, using a single thread to read from all the streams would be better, but a lot more complicated.
You can use Runtime.exec or ProcessBuilder in a different thread than your application main thread to run your shell script asynchronously.
This post shows how to use Runtime or ProcessBuilder. Read this post to learn java threads if you are not aware of it.

How to execute application continuously without hangs device in blackberry

I have created an application of contacts synchronization. when i run it on device it hangs my device while synchronizing then i am not able to open another application, I am also doing auto synchonization with in a perticular period of time.
I want that synchronization should be perform without hang to device and if i get any interrupt i.e. any call while syncing then it should pause for that moment and continue at call end.
How can i do this ?
I dont know how this is working for Blackberry, but may be an example for Eclipse RCp is helping you.
You have the choice to execute a Runnable between
The thread which calls this method is
suspended until the runnable
completes.
Display.getDefault().syncExec(runnable);
The caller of this method continues to
run in parallel, and is not notified
when the runnable has completed.
Display.getDefault().asyncExec(runnable);
In your case you have to make the decision if you can start the job in asynch mode.
When you ar enot sure, whether your job is executed in asynch mode, you should implement some outputs to the console including timestamp.

Categories

Resources