Creating an asynchronous processo in a java servlet - java

I want to create a java servlet that runs an .exe application in the server but as an asynchronous process and returns to the client a hash or token to indentify the process so the client can ask later if the process has finished.
For example:
A user writes in the web browser something like: http://server:8080/videomanager?action=process
The servlet receives the request and execute the .exe application but it doens't wait for it to finish, it inmediately responds to the user with a token/hash=12312312ddsadad31231
The user recieves this token in his web browser
The user can then send a request like: http://server:8080/videomanager?action=status&token=12312312ddsadad31231
The servlet recieves this request and checks if the process it run before (with token 12312312ddsadad31231) is still running and responds to the user with "Finished" or "Still running"
I know that I can use ProcessBuilder or Runtime.exec() to run the .exe application, but I don't know how to make the servlet leave the process running and responds.
Thanks!
Regards,
Xtian

The Process returned by ProcessBuilder is run asynchronously in the background (it's a separate process), so as soon as you call .start() you can have the servlet respond.
If you're seeing the subprocess never finish that would be because you're not reading its output, which you must do in order for the process to continue. You may want to do this in a separate background thread.

This is one of the ways to implement this:
Create a runnable that executes the command (Runtime.exec etc) (a few other things will follow)
Create an id lets say a UUID and initialize the status against the id on a persistant storage to say PENDING
Use a ThreadPoolExecutor, add the runnable to the workQueue allocated to the threadpool.
When the runnable starts executing, it may change the status in say DB to IN_PROGRESS
When the task is completed you can mark the status as COMPLETE
Now at any point of time for the request coming in you shall be able to check the status of the task and respond back accordingly.

Related

Running a continuous background task in Play 2.4.2 server

I'm creating a web application that displays incoming events as strings onto the web browser. The events should be coming in from a listener that I have defined in another part of the program. These events will be emitted through a socket to the client side.
The problem: I need to keep the listener continually running in order to receive messages. The listener is essentially one block of code that's something like listener.run(), and it doesn't terminate. Right now, I am making a separate thread that runs this block of code and I have configured Global settings to run the thread on application startup.
I don't want my task to stop and start every time I refresh the page. How can I make the listener run right when the server starts?
Look at the Scheduling asynchronous tasks at the end of the doc: https://www.playframework.com/documentation/2.4.x/JavaAkka

JAVA web application Asynchronous push notification to let user know status of long running job

I have a spring mvc/struts, hibernate application. We ran into a problem where in we are executing a long running on one of application page. We would like to execute this process in background however we want to show status of the process to end client when process gets completed. The condition is user can navigate to a different page and even on different page he/she should be notified with a dialog box or so for a long running process which was initiated bye him/her.
Any help would be appreciated
Thanks in advance
Anant
Execute the task in a thread, and either poll with ajax through an iframe, or push updates to the client using websockets

Status of the process triggered by request in java

Is it possible to get the status of the process triggered by a request.
Suppose, I have a request, that will trigger the long running process, like copying some files in the server side, or some other really long running process. Now I want to show user about the percentage completion of that task.
How to do it in Java Servlet, or any other frame which supports this?
What I thought was sending the continous response to the page. But this may not be possible. Please help me with this problem.
Thanks.
One solution is to create another servlet that provides the percentage as json (you may store it in a session object), then with javascript periodically poll informations from this servlet and show them directly.
This post might help you:
JQuery Get JSON from servlet
You can follow the above shown model. There are two servlets one for starting the processing and another reporting the status of the processing. A Process Controller class will maintain the status of the processes as well as start/ put a process in queue.
Call the the Start Processing servlet starts a process and returns a unique ID representing the process
JS/JQuery can be used to make periodic requests using the above UID to the Get Processing Progress servlet to know the progress.

Perform Asynchronus db tasks in java servlet application

I have a jsp/servlet based web app.
I have a button "Clean Up" which calls a servlet and the request goes till DAO class.DAO class performs different DB activities like, moving data from Master table to backup table, then deleting data from master table etc.
As of now this activity is Synchronous and user needs to wait until a response is sent.
I want to implement the same scenario as an Asynch task with user just getting a message as
" Clean Up Activities Triggered"
What could be the best/easiest way to perform this task. I cannot use scheduler.
My Container is TomCat.
Simplest but a different solution for this could be to use some AJAX behavior in the client side. There are lot of simple/powerful frameworks(JS files) to help you achieve AJAX in your page. Using AJAX, you just submit the request asynchronously and display the client side message "Clean Up Activities Triggered", while request is being processed in the server side. If user wait, server process will return and display a "success" message otherwise user is free to navigate other pages or perform other actions.
ExecutorService is the most robust solution. Creating a simple thread is enough as well. However the bigger problem is synchronization. Use Semaphore to control whether two users aren't cleaning up simultaneously.
we did this for our project once and it worked pretty well.
We sent the 200 ok to the user as long as there no issues processing the request. And we used the java executorservice to do the cleanup.
And in case something went wrong notified the user separately.

Best method of triggering a shell script from Java

I have a shell script which I'd like to trigger from a J2EE web app.
The script does lots of things - processing, FTPing, etc - it's a legacy thing.
It takes a long time to run.
I'm wondering what is the best approach to this. I want a user to be able to click on a link, trigger the script, and display a message to the user saying that the script has started. I'd like the HTTP request/response cycle to be instantaneous, irrespective of the fact that my script takes a long time to run.
I can think of three options:
Spawn a new thread during the processing of the user's click. However, I don't think this is compliant with the J2EE spec.
Send some output down the HTTP response stream and commit it before triggering the script. This gives the illusion that the HTTP request/response cycle has finished, but actually the thread processing the request is still sat there waiting for the shell script to finish. So I've basically hijacked the containers HTTP processing thread for my own purpose.
Create a wrapper script which starts my main script in the background. This would let the request/response cycle to finish normally in the container.
All the above would be using a servlet and Runtime.getRuntime().exec().
This is running on Solaris using Oracle's OC4J app server, on Java 1.4.2.
Please does anyone have any opinions on which is the least hacky solution and why?
Or does anyone have a better approach? We've got Quartz available, but we don't want to have to reimplement the shell script as a Java process.
Thanks.
You mentioned Quartz so let's go for an option #4 (which is IMO the best of course):
Use Quartz Scheduler and a org.quartz.jobs.NativeJob
PS: The biggest problem may be to find documentation and this is the best source I've been able to find: How to use NativeJob?
I'd go with option 3, especially if you don't actually need to know when the script finishes (or have some other way of finding out other than waiting for the process to end).
Option 1 wastes a thread that's just going to be sitting around waiting for the script to finish. Option 2 seems like a bad idea. I wouldn't hijack servlet container threads.
Is it necessary for your application to evaluate output from the script you are starting, or is this a simple fire-and-forget job? If it's not required, you can 'abuse' the fact that Runtime.getRuntime().exec() will return immediately with the process continuing to run in the background. If you actually wanted to wait for the script/process to finish, you would have to invoke waitFor() on the Process object returned by exec().
If the process you are starting writes anything to stdout or stderr, be sure to redirect these to either log files or /dev/null, otherwise the process will block after a while, since stdout and stderr are available as InputStreams with limited buffering capabilites through the Process object.
My approach to this would probably be something like the following:
Set up an ExecutorService within the servlet to perform the actual execution.
Create an implementation of Callable with an appropriate return type, that wraps the actual script execution (using Runtime.exec()) to translate Java input variables to shell script arguments, and the script output to an appropriate Java object.
When a request comes in, create an appropriate Callable object, submit it to the executor service and put the resulting Future somewhere persistent (e.g. user's session, or UID-keyed map returning the key to the user for later lookups, depending on requirements). Then immediately send an HTTP response to the user implying that the script was started OK (including the lookup key if required).
Add some mechanism for the user to poll the progress of their task, returning either a "still running" response, a "failed" response or a "succeeded + result" response depending on the state of the Future that you just looked up.
It's a bit handwavy but depending on how your webapp is structured you can probably fit these general components in somewhere.
If your HTTP response / the user does not need to see the output of the script, or be aware of when the script completes, then your best option is to launch the thread in some sort of wrapper script as you mention so that it can run outside of the servlet container environment as a whole. This means you can absolve yourself from needing to manage threads within the container, or hijacking a thread as you mention, etc.
Only if the user needs to be informed of when the script completes and/or monitor the script's output would I consider options 1 or 2.
For the second option, you can use a servlet, and after you've responded to the HTTP request, you can use java.lang.Runtime.exec() to execute your script. I'd also recommend that you look here : http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
... for some of the problems and pitfalls of using it.
The most robust solution for asynchronous backend processes is using a message queue IMO. Recently I implemented this using a Spring-embedded ActiveMQ broker, and rigging up a producing and consuming bean. When a job needs to be started, my code calls the producer which puts a message on the queue. The consumer is subscribed to the queue and get kicked into action by the message in a separate thread. This approach neatly separates the UI from the queueing mechanism (via the producer), and from the asynchronous process (handled by the consumer).
Note this was a Java 5, Spring-configured environment running on a Tomcat server on developer machines, and deployed to Weblogic on the test/production machines.
Your problem stems from the fact that you are trying to go against the 'single response per request' model in J2EE, and have the end-user's page dynamically update as the backend task executes.
Unless you want to go down the introducing an Ajax-based solution, you will have to force the rendered page on the user's browser to 'poll' the server for information periodically, until the back-end task completes.
This can be achieved by:
When the J2EE container receives the request, spawn a thread which takes a reference to the session object (which will be used to write the output of your script)
Initialize the response servlet to write an html page which will contain a Javascript function to reload the page from the server at regular intervals (every 10 seconds or so).
On each request, poll the session object to display the output stored by the spawned thread in step 1
[clean-up logic can be added to delete the stored content from the session once the thread completes if needed, also you can set any additional flags in the session for mark state transitions of the execution of your script]
This is one way to achieve what you want - it isn't the most elegant of all approaches, but it is essentially due to needing to asynchronously update your page content from the server , with a request/response model.
There are other ways to achieve this, but it really depends on how inflexible your constraints are. I have heard of Direct Web Remoting (although I haven't played with it yet), might be worth taking a look at Developing Applications using Reverse-Ajax

Categories