How to work with long-lasting http requests - java

I have a long-lasting http request (a lot of computation in the back-end).
Currently it's all synchronous, while the server computer, the browser doesn't see the output/result. After a while, the connection is dropped and an timeout error is displayed in the browser.
I'd like to return some info to the browser right away, and make it wait for the result. How to achieve this?
Please note, that the Java back-end is synchronous. So a solution would require some hack in the servlet/front end possibly requiring javascript requests.. ?

You probably want to use the COMET pattern. It's like the AJAX pattern, only featuring long-held HTTP requests to simulate a feed. See here for a detailed explanation.
Basically, you fire off a request, the server holds it, then replies when it has something of interest. At the point of receiving the reply, you immediately fire off another long-held request.
This time-sequence makes it feel like a feed.
In your case, it could just return "yeah, I'm working on it" immediately and then reply with "still processing 10% done dude" and so on until you get back "done".
Things like node.js are really good at implementing this kind of functionality.
Although, as you're using a synchronous Java back end, you may need some kind of indication somewhere that progress is being made. Possibly a database.

Timeout won't occure as long as you write something to output stream (it can even be spaces, don't forget to call flush()).
Such long-lasting request makes sence when you, for example, print a large report, which is shown to the user subsequently as it is generated.
In all other cases, return the waiting page to the user and use periodical AJAX requests to ask if the processing has finished. When nothing changes and the browser is showing loading, it is not a good user experience.

The best solution would be to use AJAX requests. Once an ajax request times out you can send it again by using JavaScript(you can show some button). This is probably the best practice to handle timeouts.

Related

Android: Background process for Login

I'm currently working on an Android App which calls HTTPS Requests (like Login, etc.) to a Rest API. My first approach was to use AsyncTask to do this work not on the Main Thread. Unfortunately, I need to know if the Login was successful or not in order to proceed with the code, because if you are not logged in you have only limited access to other parts of the app.
I've tried it with AsyncTask because I used it in a previous project, but I noticed the problem with the return value a little bit to late and now I don't know what technology I should use in order to:
Don't block the main UI
Wait for a response
Evaluate the response with a boolean or something similar
I would appreciate if someone could help me with choosing the best way of accomplishing my problem
Use Retrofit for API calls.
But, it will be async as well. That's something you can't avoid.
If you have to wait for call finishes, and process to the app/dashboard, there is no other way.
Practice is to show loader over the screen, send request in async task, wait for response, hide loader, process to the app.
Not sure about your implementation, but other approach could be:
set as user is not logged in
process to the app handle user as he isn't logged in yet
when login request is successful, set some global variable that he's logged in

Having a "worker" in Java

I have a REST API created in Java with the Spark framework, but right now a lot of work is being done on the request thread that is significantly slowing down requests.
I'm wanting to solve this by creating some kind of background worker/queue that will do all the needed work off of the request thread. The response from the server contains data that the client will need (it's data that will be displayed). In these examples the client is a web browser.
Here's what the current cycle looks like
API request from client to server
Server does blocking work; Response from server after several seconds/minutes
Client receives response. It has all the data it needs in the response
Here's what I would like
API request from client to server
Server does work off-thread
Client receives response from server almost instantly, but it doesn't have the data it needs. This response will contain some ID (Integer or UUID), which can be used to check the progress of the work being done
Client regularly checks the status of the work being done, the response will contain a status (like a percentage or time estimate). Once the work is done, the response will also contain the data we need
What I dislike about this approach is that it will significantly complicate my API. If I want to get any data, I will have to make two requests. One to initiate the blocking work, and another to check the status (and get the result of the blocking work). Not only will the API become more complicated, but the backend will too.
Is this efficient, or is there a better way to implement what I want to accomplish?
Neither way is more efficient than the other since the same amount and time of work will be done in either case. In the first case it will be done on the request thread, the client will not know of progress and the request will take as long as it takes to run the task. This has the client wait on the reply.
In the second case you need to add complexity, but you get progress status and possibly other advantages depending on the task. This has the client poll on the reply.
You can use async processing to perform work on non-request threads, but that probably won't make any difference if most of your requests are long running ones. So it's up to you to decide what you want, the client will have to wait the same amount anyway.

Is there a way to tell the servlet container to spawn one instance of a resource at a time?

I have a resource, say a #POST method serving the clients. It doesn't run on any external parameters, not even the caller URL (we're leaving that to the firewall) or the user authentication.
However, we don't want to handle user requests simultaneously. When a request1 is being processed and the method hasn't just yet returned, a request2 coming in should receive a response of status 309 (or whatever status code applies) and shouldn't get served.
Is there a way of doing this without getting into anything on the server back-end side like multithreading?
I'm using Tomcat 8. The application will be deployed on JBoss, however this wouldn't effect the outcome(?) I used Jersey 1.19 for coding the resource.
This is a Q relevant to How to ignore multiple clicks from an impatient user?.
TIA.
Depending on what you want to achieve, yes, it is possible to reject additional requests while a service is "in use." I don't know if it's possible at the servlet level; servlets are designed to spin up processes for as many requests as possible so that, say, if one user requests something simple and another requests something difficult, the simple request can get handled while the difficult request is processing.
The primary reason you would probably NOT want to return an HTTP error code simply because a service is in use is that the service didn't error; it was simply in use. Imagine trying to use a restroom that someone else was using and instead of "in use" the restroom said "out of order."
Another reason to think twice about a service that rejects requests while it is processing any other request is that it will not scale. Period. You will have some users have their requests accepted and others have their requests rejected, seemingly at random, and the ratio will tilt toward more rejections the more users the service has. Think of calling into the radio station to try to be the 9th caller, getting a busy tone, and then calling back again and again until you get through. This works for trying to win free tickets to a concert, but would not work well for a business you were a customer of.
That said, here are some ways I might approach handling expensive, possibly duplicate, requests.
If you're trying to avoid multiple identical/simultaneous requests from an impatient user, you most likely have a UX problem (e.g. a web button doesn't seem to respond when clicked because of processing lag). I'd implement a loading mask or something similar to prevent multiple clicks and to communicate that the user's request has been received and is processing. Loading/processing masks have the added benefit of giving users an abstract feeling of ease and confidence that the service is indeed working as expected.
If there is some reason out of your control why multiple identical requests might get triggered coming from the same source, I'd opt for a cache that returns the processed result to all requests, but only processes the first request (and retrieves the response from the cache for all other requests).
If you really really want to return errors, implement a singleton service that remembers a cache of some number of requests, detects duplicates, and handles them appropriately.
Remember that if your use case is indeed multiple clicks from a browser, you likely want to respond to the last request sent, not the first. If a user has clicked twice, the browser will register the error response first (it will come back immediately as a response to the last click). This can further undermine the UX: a single click results in a delay, but two clicks results in an error.
But before implementing a service that returns an error condsider the following: what if two different users request the same resource at the same time? Should one really get an error response? What if the quantity of requests increases during certain times? Do you really want to return errors to what amounts to a random selection of consumers of the service?

Is it in anyway possible to stop a REST call?

From Javascript, I am calling a REST method which is computationally intensive. Would it be possible to stop that REST call, if you are no longer interested in what it returns.
I understand, it is possible to abort a request in JS. But it won't stop the thread which gets triggered due to the REST call. This is how I am aborting the ajax call in JS.
Abort Ajax requests using jQuery
The REST interface is written in Java. And internally this thread may create multiple threads also.
I would like to stop a Java thread. But from the caller. From JS, where I have triggered it.
How to properly stop the Thread in Java?
As Chris mentioned in the comments above, REST calls should be quick, definitely not an hour long. If the server needs to do a lot of work which takes considerably amount of time, you should modify your design to async. Either provide a callback that the server will use once it's done (also called push approach), or pull every few minutes, by sending a new request to the server to see if it's done.
In order to implement it you'll need the server to return a unique-id for each request in order to be able to identify in the callback/check-call what's the status of that specific request.
The unique-id should be implemented on the server-side in order to avoid two clients send the same ID - overriding each other.
In the link that I posted above you can see an example of how to implement a "stop thread" mechanism which can be implemented on the server-side and called by the client whenever is needed.
You could send a unique identifier along with your request, and then make another request that instructs the server to abort the operation started for that ID.

How To Terminate Thread When Jsp Page close that call it JSP?

I am calling a thread in JSP page and that thread keeps on running. I want this thread to terminate when I close the JSP page. Wow would that be possible ?
my code put it in body tag JSP:
<%
Thread Ping=new PingThread();
Ping.Start();
%>
Thanks in Advance
You mean close it when the user closes the window? There is no event fired for that, so you can't do it. You could do that via JavaScript by making an Ajax call when the user closes the window, but it's probably not going to work anyway.
The doubt that comes to mind is: why would you do such an horrible thing as starting a thead in a JSP page? By spamming the F5 button someone could obtain the easiest DOS attack of the history! Rethink your application to avoid such a solution (launching threads blindly on request, not just the fact that you do it from a JSP).
If you start a thread from a JSP, it is to impossible to guarantee that the thread will be stopped when the user exits the page.
No notification is sent from the client to server when the user closes or moves away from a plain HTML page. None whatsoever.
You could include some javascript in a web page to perform an AJAX call to your server when the user closes the window or moves to a different page. However, there are scenarios where call won't get made; e.g.
the user's machine dies,
the user's browser crashes,
the user has javascript turned off,
the user sets a breakpoint in your code,
etcetera.
And even if the call is made, there's no guarantee that it won't get lost due to some transient networking problem.
The end result will be that your server has an orphaned thread that will keeping doing whatever it is doing (in this case, pounding some other machine with ICMP packets) until you kill your web container.
That's a really, really bad idea.
You can use the Javascript beforeunload or unload events to determine that the window is being closed, though which one you use and how depends on precisely what it is you want to do.
As Anthony Grist's answer says (sort of), you can embed javascript in your web page to be executed when the browser detects that the current browser window is being closed. Refer to this page for more details about DOM Events and their handling.
Notes:
This stuff works whether or not the page is a JSP. (For instance ... it would work if the page was plain HTML ... provided that there was something on the server end to deal with the notification.)
This event handling is performed in the users web browser.
The server side doesn't get told about the window closing, unless the event handlers send an (AJAX) request to the server to tell it.
As I said in an answer to a previous question, there event handling can be disabled on the client side by the user.
As I said in an answer to a previous question, there is no guarantee that the AJAX request will actually make it back to the server.
All of this adds up to the fact that any server side handling of the window close event is unreliable. And there's no solution to that. Not in theory, and not in practice.
you could enclose the above in another loop which is set to true by the jsp page throuh ajax call on a time to time basis. if the jsp page is not setting the value to true then you can safely assume that the browser is closed. But you would need an identifier for your thread like say session id or ip of the user.

Categories