Cancelling a request in Tomcat - java

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");

Related

How to check if the DELETE API has been called

I have a task to implement a distributed Queuing System something like the Amazon SQS.
If there is GET Request, I have to deliver the message to the user from the main queue and put the message in the invisible queue. And immediately a DELETE Request should come and I should delete the message from the invisible queue.
In case there is no DELETE Request, I am supposed to increase the redelivery count and send the message back to the main queue. This will happen till the redelivery count becomes 5 after which I will delete the message permanently.
Now my doubt is, how do I know that there has been no DELETE request which means that I should send the message back to the main queue?
My program works for the case where the DELETE Request follows the GET Request. I am using java for this implementation.
First of all, at the design level, the get and delete should be done in one action. Notice that in the JDK, the pull() operation of Queue will do get and delete. if you insist on separate actions, at the very least you should support an optional get-and-delete request type.
now, there is a problem when you want to detect an action that did not happen because it can forever "maybe happen in the future". So you need to set a window of time after which you decide that the expected action did not happen.
what is usually done is that you attach a "received" timestamp to the request (and also re-deliver count) before putting it in the invisible queue (a better name would be "pending delete requests" queue) you can wrap the request in a custom java class that adds the properties.
actually, I don't think a queue is a good choice for a collection. when a delete request does come, you need random access to the request. so perhaps a hash map is a better choice.
you will need to implement a Timer that invokes tasks every x seconds. the tasks will scan the pendingDeleteRequests map for requests that did not recevie delete in the allowed window of time and remove from the map.
last note: some messaging systems have "dead letter" feature, which is a destination where notices of failed deliveries are sent. this will help in debugging of problems.

Struts 1.x action is being called multiple times

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.

Stop server thread after browser stop loading

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.

How to implement a lock on data currently being viewed by a user

Morning gurus,
I am trying to implement a solution for allowing only one user of our web app be able to see the data they are interested in until they move away from the page.
So when a user clicks on the page they are presented with all the routes they have permission to see and no one else who has permission to see them is currently looking at.
I have partially implemented this by making an Application Scoped bean which stores a map of the routes being viewed by users keyed on their session id.
The Application Scoped bean is updated when the page's backing bean gets the routes from the database.
I have written a Filter which removes the viewed routes from the Application Scoped bean when the user leaves the page.
This all works fine :-)
But if the user leaves the page by either closing the browser tab / closing the browser or the session expiring my clean up code is bypassed.
Does anyone have suggestions how
I can get my clean up code to run before the tab/browser closes/session expires.
I can access the sessions for all users in my application scope bean (so I can iterate over them and build the watched routes map every time it is requested)
An idea of a better solution.
I'm working with JSF / Icefaces 2.
Thanks for your time.
First, and most importantly, you need to decide on the acceptable delay between a user closing the browser and releasing the locks on the held objects.
If you can handle having locks persist until the session is destroyed, add an HttpSessionListener and perform cleanup when the session is destroyed.
If you can handle delays in the 10s of seconds, add a periodic request on the web page (either via AJAX/JS, or via an invisible IFRAME that reloads a specific page from your server), and have a Filter that timestamps the last access from the browser in the users session or the Application Scpoed bean you already have. A separate thread wakes up every N seconds, scans for sessions with locked objects that are older than M seconds and unlocks them.
If you need immediate notification, install an onbeforeunload event handler that notifies the server. Also, you could do it with a persistent connection or WebSocket.
In any case, you will need at least one of the first two, because the third may be unreliable.
Use a cronjob or something which runs periodically and indentifies closed connections etc.; you can save the last action from each user and remove the lock if this times is greater than some time.
You could add a periodic (once a minute for example) AJAX call on your page, which keeps the lock alive.

Multithreading a jsp?

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).

Categories

Resources