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.
Related
EJB Spec says you shouldn't manage threads. I have seen Bean code that sends remote requests and loops with a Thread.sleep waiting for a response to reduce CPU usage. From what I understand this breaks spec. Does simply calling the logic from a separate POJO or library that is instantiated then referenced in the EJB's method fix this? Does simply removing Thread.sleep fix the issue at the cost of additional CPU consumption? How should external synchronous requests be coded in EJBs?
That depends on the business case. EJB spec provides plenty of resources for async/sync processing without boilerplate code using Thread, Runnable or any other mechanism.
To execute a piece or code asynchronously (that is, the caller won't wait for the response, but carry on), use #Asynchronous, and Future<T> if you want to listen for responses afterwords.
A synchronous call, as you called, is a call that waits for the response, so "How should external synchronous requests be coded in EJBs" is something that doesn't need any kind of asynchronous/background execution. You just make the call and the code itself wait for the response (otherwise it would be asynchronous), being the tipical case a Web Service (either REST or SOAP).
Web Services calls can actually be synchronous or asynchronous, that depends on the business case, but they are usualy synchronous, you make the call and receive a response with the data. In cases of business logic that takes a while to execute, the Web Service receives the resquest and may launch the business logic asynchronously (with an #Asynchronous for instance) and respond immediately with a plain HTTP 202 - Accepted, which basically means "Hey! The request you just sent me is gonna take a while, so I'll do it in the backround".
In that case, may be you have another web service that you need to check to see how that long lasting process is going. That is the only case I can think of in which someone will want that Thread.sleep(...) in a loop, checking the Web Service until it tells you that the process have finished.
Luckily, EJB also provides a solution for that business case:
You can use #Schedule methods in case you need to check/do something indefenately, in specific intervals: something to do every day at 02:00, or every first day of month, or even every 2 seconds.
Or TimerService and #Timeout, in case you want to programatically schedule a single task. This last fits better in the business case we are talking.
So you call the TimerService with the timespan you want to wait for the next check. When time comes the #Timeout method is fired, in which you can check whatever you need, and shcedule another execution in case you need it, even with a new timespan.
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.
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?
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.
Is there any way to check if an async ServletRequest is completed from an AsyncContext? I saw that spring has some kind of wrapper that supports this but googling around I couldn't find anything in the standard library. That is what I was hoping for.
I am using Tomcat 7.
Sounds like one of the two - you either need a listener that will be called upon a asynchronous request completion or you don't need to use an asynchronous call.
Your question is a bit too general.
Talking generally - asynchronous calls are used when the caller is not interested in immediate result of the call.
If the caller is interested to know the result of the call immediately then synchronous calls should be used.
If the caller is not interested to know the result immediately (for example it has secondary priority, like logging in some business applications), but some action should be performed upon the end of execution of asynchronous calls you should use some sort of a listener.
What you need for asynchronous call is some listener (of class javax.servlet.AsyncListener).
In the listener you will know for sure that the asynchronous call is over (onComplete method) and may perform some action to finalize/complement the asynchronous call.
Again, if you see that the caller of the request needs to know the result upon completion immediately, there probably is a mistake in your architecture. You should use a synchronous call - just wait until the call is done and you will have the result of it. Using an asynchronous call is wrong in this situation.
I saw how people use some sort of a loop to check from time to time the result of a asynchronous call, but it looks like in 99.99% of cases such approach is the result of some architectural mistake.
You can register AsyncListener which can implement onComplete() method.
The AsyncListener needs to be added to the AsyncContext.