I am trying to process some business logic after user hit a URL. There will be a heavy loop running in server side. The browser will be loading (we can see the spinning animation on top) while waiting server return the result.
We don't discuss is that correct or not to perform heavy loop in HTTP connection, my question is that, while the browser is waiting for the result, and, if user want to stop the processing, by closing the browser/tab or pressing ESCAPE or pressing the "X" cross button (at the browser bar), likely, the browser will stop to receive any data from server side. Now, my problem is, the server thread that is processing heavy loop will not stop somehow (even browser not to receive data anymore). How am I going to stop that?
I thought that, according TCP transmission, if one end of sockets is closed, another end will be notified and closed as well. I expect my server will have something like "socket close exception" thing thrown out by the Servlet. But it is not, so the loop in Servlet is still running until it finished. Any idea how can I stop it? It will lead to "Out of memory" issue if the user keep on hitting the URL and cancel the request.
Try to do something like this:
Create service for processing your heavy loop in new threads (manually created by you).
When user hits URL in browser create thread with heavy loop in new thread (by processing service) and return to user some internal id of this thread (this id may be generated by you) which will allow you to identify this thread in service from point 1.
Make some kind of pinger from client to server (for example on every 5 seconds client will ping processing service with thread id). Write last time of ping for this thread in thread-processing service.
In thread-processing service from point 1, create next thread for checking each thread if ping was in last 5 seconds. If not - interrupt thread.
Actually, you must load your page to afford javascript side bind events like closing browser window:
$(window).bind('beforeunload', function(eventObject) {...})
And in function you can generate ajax request to server side, which could serve like a marker to stop the thread.
When your page is requested you create a new thread for your heavy task and add timer to page, which polls server at some interval to see if the task is complete (also via ajax). When the task is complete you are free to choose what to do - redirect to real page or update this page to load results.
Related
My application is using Struts 1.x and it's running on WAS..
All action classes are working fine except one wherein I click on one button and one action(which is expected to complete in 1hour) is called and then it starts executing ..the issue comes when same action is called after few minutes without any button trigger or any change of code.This happens after every few minutes for n number of times...
If anyone has any idea about this please let me know.
A request that takes 1 hour to complete is not normal: you should redesign this functionality.
Briefly, you have this problem because the request takes too much time to complete. For a technical explanation of the cause of your problem see Why does the user agent resubmit a request after server does a TCP reset?
Solution: create a separate thread (or a pool of parallel threads, if possible) to handle the long-running computation and send immediately a response page saying "Request accepted". This page could also use JavaScript to send periodically an "is it completed?" request to the server. You should also provide a mechanism to inquiry for pending requests, so users that close the browser without waiting for the final "Yes, completed!" response can get the result when they want.
I have some theoretical question regarding "message loops"; particularly returning result of operations happening in a message loop that runs in a different thread. I have the situation where I'm having a TCP server listening for incoming messages. For each incoming message the server will authenticate the client who sent the message and two things may happen:
If the authenticated client has an attached handler the received message will be passed to the handler's message queue.
If the client has no handler a new one will be created and the same as above (the message will be passed to its message queue).
The handler is currently an object implementing the Callable interface so that it'll run in a different thread and its simple enough the get the result of the operation. Now for my problem: Each handler can have N amount of messages to be processed. The handler has a "message loop" like functionality that runs until a timeout occurs - a timeout in this case would be the socket's idle time reaching a predefined treshold. What I would like to know, how can I get Java to return a value from within the message loop without actually terminating the thread. Something like the following:
while (true) {
if (expired(socket))
break; // the callable will finish the call() method.
// get the first item from the queue.
message = messageQueue.poll();
result = process(message);
// I want to return the result to the caller which is in a different thread.
}
Now obviously a return statement would stop the message loop and if the messageQueue contains more messages they'll be lost. Another naive approach would be to use a callback-like mechanism, which requires an extra object + I still need to synchronize the caller with the Callable in the background thread. Something like wait & notify although I have K threads running in the background.
What would be the sophisticated way to handle this situation of returning results of operations from within a message-loop in a different thread, without terminating the thread itself?
#Edit:
I'll give a description of the whole process so that it clarifies what is happening here.
A client sends a message (xml string) to the application through tcp sockets.
The application authenticates the client, and if the client has no associated handler it'll create one.
The app will push the message to the queue of the handler.
The handler runs in a separate thread waiting for incoming messages from clients they're associated with, they MUST NOT handle messages for other clients.
When the handler picks up a message it'll transform it into a SOAP message and will forward it to another system through TCP socket.
When the handler recieves the response it needs to delegate it back to the caller without terminating its message-loop.
So the caller is something like a Dispatcher dispatching messages to the threads that are running the handlers associated with the sender of the message. It also collects the response from the handlers and sends them back to the correct clients.
Each handler, currently has their own message queue where only those messages are pushed which the particular handle has to process. When a handler starts up, it'll open a TCP socket to the target system where they'll forward the incoming messages after transformations were applied. When the handler reaches the maximal allowed idle time (The socket were opened without sending a request) the socket will be closed and the message-loop stopped. At this point the handler will finish its execution. the purpose of this, is to have a socket for each individual clients through which they can send multiple requests without the need for the target system to do another authentication.
Few options/questions come to mind:
Is there a problem to terminate the thread, check the returned result and then re-submit this task to the same thread pool? You will get a result, analyze it, and then resubmit to the pool and continue the work
As this thread runs, it can submit the statuses to a different ("external") queue which is analyzed outside this thread. An independent thread always run and check this queue
That's as far as I could think on how to...
It depends on...
If you want to return simple type you can use a thead safe result queue (global or by caller).
Propably thread pool will be more suitable in your case.
I belive that the most universal way is callback mechanism.
Im trying to do following:
Send long executing request (I use here Events.echoEvent)
Show modal dialog (Wait...) with "cancel" button
If user press "cancel", dialog is hidded and event method should not be executed.
If user don't press button and wait. event method is called and close wait dialog
How can I do that?
ZK normally does all it's work for a single request on the server in a single thread. Events.echoEvent lets you get around that by finishing the request, and then calling back to the server immediately in a brand new request (and thread). The user's interaction with the client fires off a new request, so that will be a new thread also.
So, in your example above, you will be working with three threads:
for the original request which calls echoEvent
for the new request created by the echoEvent
for the request created when the user clicks 'cancel'
Obviously, the first will be long gone by the time the last two get called, but this is what you need to be thinking about in order to solve your problem.
You'll find plenty of discussion on StackOverflow about getting two threads to interact, or more specifically, getting one thread to interrupt another.
I'll refer you to 'How to stop threads in Java?' where the accepted answer favored sharing some sort of 'stop flag' over directly calling interrupt on a thread.
In your scenario this would play out with the long running process doing it's work while periodically checking the stop flag (a simple boolean). When the user clicks 'Cancel', you just need to flip the flag to true.
You can try
Create a thread to do the long operation as Sean mentioned above
(this is an independent thread, not ZK request thread)
Create a timer to check the status of that thread periodically.
(this will create a javascript timer to send ajax request periodically at client side)
And customize the busy mask by ZK Client Side programming to add the cancel button.
(the button click perform another ajax request)
Please refer to the similar article at stackoverflow:
Override “Processing” in ZK
Edit:
There are some related articles at my blog:
ZK: Customize the mask for showBusy
ZK: Adding abort button to busy mask
ZK: Mask page manually
I have a web application deployed in Tomcat 7 and one of the transactions there is loading a text file to the application then the application will read it line by line then insert all the records to the database.
I would like to put a cancel button on the page to let the users decide if they would like to cancel the transaction especially if they're uploading big files. I'm thinking to just put a link that goes to another page to serve as cancel button. Will this work?
Would the thread continue if the client uploads a 15MB file, which takes about 10 minutes to be processed, then decides to cancel it by clicking the link I provided as a cancel button?
Once the file is uploaded to the server, start a thread to do the processing and store a reference to it somewhere (like a Hashtable) and give it a unique ID. Then render the page back to the user with the cancel button, and store the ID you used earlier to keep a reference to the thread in the page.
When the user clicks cancel, go back to the Hashtable, get the thread with the ID and send it a message to make it stop the import.
Of course, your method that will stop the thread from importing data will need to take into account current database transactions to be sure you dont leave your database in an invalid state.
I think it is not possible to stop a request that is under transmission to the server. Once you click upload you make a HTTP request, and the process begins and clicking "cancel/link u provided" at a later point, would be a different HTTP request and since HTTP is stateless, it would not know anything what happened earlier or what to stop. So as expected it is not possible implicitly. But there may be something that can be done to do this which I am unaware of now. But if you press "esc" key that would terminate the request sent to the server. And since this is the only solution till now then on UI you can write this javascript code:
$('.your_link').click(function(){
window.stop();
});
window.stop() will not work on IE. for IE you can use:
document.execCommand("Stop");
I'm new to jersey, jsp's and web application development in general so hopefully this isn't a silly question. I've got a jsp and currently when the user hits a button on it, it starts a HTTP request which takes about 5-10 minutes to return. Once it finishes they're redirected to another page.
I'm wondering, is it possible or even advisable that I multithread the application so that the heavy processing will start but the user get's redirected to the next .jsp right away. If multithreading is not possible is there another method that you would recommend for dealing with heavy processing in a web application?
A JSP is basically a Servlet (it's translated in a Java Servlet Class and compiled). Teoretically you can start a new thread in a servlet (and hence in a JSP, via scriptlet), but that's really not advised for multiple reasons.
It'd be better recommended to make an asynchronous HTTP call via ajax, then, once the call is done immediately show something else to the user, and when the call back returns display the results.
Rather than create a new thread each time it might be more efficient to have a worker thread which continually polls a shared queue. Using, for example, ArrayBlockingQueue you web request can simple add an object to the queue and return to the user, and your worker thread (or repeating scheduled job) can take care of the heavy weight processing.
Instead of waiting for process to complete in a JSP, you can create a TimerTask (or Quartz Job) and set it for immediate execution and redirect user to some other page. Have that Job store the result in some central place that can be accessed by another JSP (in case you want to pull result of Job later, may be through ajax) Doing so, you save yourself from managing threads manually (which is error prone), you get async functionality, user does not need to see the blank browser screen for around 5-10 minutes.
It is possible.
Create a thread, store its reference somewhere that is available everywhere (a static Map) and store its key (in the session, in the code of the JSP's answer).
Following calls can retrieve the thread and check its state/results.
Anyway, use with care:
a) You will need to control that old results are deleted. It is inevitable that sometimes the browser will close, so you need a Watchdog to clear data obviously no longer needed.
b) The user are not used to this kind of behavior. There is a serious risk that they will just "go back" and try to launch the thread again, and again, and again. Try to control it (ideally the id of the thread will be linked to the user, so as long as an older thread is active an user cannot launch another one).