Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jersey ws 2.0 @suspended AsyncResponse, what does it do?

I am analyzing some jersey 2.0 code and i have a question on how the following method works:

@Stateless
  @Path("/mycoolstuff")
  public class MyEjbResource {
    …
    @GET
    @Asynchronous //does this mean the method executes on child thread ?
    public void longRunningOperation(@Suspended AsyncResponse ar) {
      final String result = executeLongRunningOperation();
      ar.resume(result);
    }

    private String executeLongRunningOperation() { … }
  }

Lets say im at a web browser and i type in www.mysite/mycoolstuff this will execute the method but im not understanding what the asyncResponse is used for neither the @Asynchronous annotation. From the browser how would i notice its asychnronous ? what would be the difference in removing the annotation ? Also the suspended annotation after reading the documentation i'm not clear its purpose.

is the @Asynchronous annotation simply telling the program to execute this method on a new thread ? is it a convenience method for doing "new Thread(.....)" ?

Update: this annotation relieves the server of hanging onto the request processing thread. Throughput can be better. Anyway from the official docs:

Request processing on the server works by default in a synchronous processing mode, which means that a client connection of a request is processed in a single I/O container thread. Once the thread processing the request returns to the I/O container, the container can safely assume that the request processing is finished and that the client connection can be safely released including all the resources associated with the connection. This model is typically sufficient for processing of requests for which the processing resource method execution takes a relatively short time. However, in cases where a resource method execution is known to take a long time to compute the result, server-side asynchronous processing model should be used. In this model, the association between a request processing thread and client connection is broken. I/O container that handles incoming request may no longer assume that a client connection can be safely closed when a request processing thread returns. Instead a facility for explicitly suspending, resuming and closing client connections needs to be exposed. Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client. It will however increase the throughput of the server, by releasing the initial request processing thread back to the I/O container while the request may still be waiting in a queue for processing or the processing may still be running on another dedicated thread. The released I/O container thread can be used to accept and process new incoming request connections.

like image 262
j2emanue Avatar asked May 02 '15 12:05

j2emanue


3 Answers

The @Suspended annotation is added before an AsyncResponse parameter on the resource method to tell the underlying web server not to expect this thread to return a response for the remote caller:

@POST
public void asyncPost(@Suspended final AsyncResponse ar, ... <args>) {
    someAsyncMethodInYourServer(<args>, new AsyncMethodCallback() {
        @Override
        void completed(<results>) {
            ar.complete(Response.ok(<results>).build());
        }

        @Override
        void failed(Throwable t) {
            ar.failed(t);
        }
    }
}

Rather, the AsyncResponse object is used by the thread that calls completed or failed on the callback object to return an 'ok' or throw an error to the client.

Consider using such asynchronous resources in conjunction with an async jersey client. If you're trying to implement a ReST service that exposes a fundamentally async api, these patterns allow you to project the async api through the ReST interface.

We don't create async interfaces because we have a process that takes a long time (minutes or hours) to run, but rather because we don't want our threads to ever sleep - we send the request and register a callback handler to be called later when the result is ready - from milliseconds to seconds later - in a synchronous interface, the calling thread would be sleeping during that time, rather than doing something useful. One of the fastest web servers ever written is single threaded and completely asynchronous. That thread never sleeps, and because there is only one thread, there's no context switching going on under the covers (at least within that process).

like image 186
John Calcote Avatar answered Oct 18 '22 08:10

John Calcote


The @suspend annotation makes the caller actually wait until your done work. Lets say you have a lot of work to do on another thread. when you use jersey @suspend the caller just sits there and waits (so on a web browser they just see a spinner) until your AsyncResponse object returns data to it.

Imagine you had a really long operation you had to do and you want to do it on another thread (or multiple threads). Now we can have the user wait until we are done. Don't forget in jersey you'll need to add the " true" right in the jersey servlet definition in web.xml to get it to work.

like image 29
j2emanue Avatar answered Oct 18 '22 07:10

j2emanue


@Suspended have more definite if you used it, else it not makes any difference of using it.let's talk about benefits of its.

  • @Suspended will pause/Suspend the current thread until it gets response,by default #NO_TIMEOUT no suspend timeout set. so it doesn't mean your request response thread get free and available for other.
  • Now Assume you want your service to be a response with some specific time, but the method you are calling from resource not guarantee the response time, then how will you manage your service response time.At that time you can set suspend timeout for your service using @Suspended , and even provide a fall back response when time get exceed.

Below is some sample of code for setting suspend/pause timeout

public void longRunningOperation(@Suspended AsyncResponse ar) {
 *      ar.setTimeoutHandler(customHandler);
 *      ar.setTimeout(10, TimeUnit.SECONDS);
 *      final String result = executeLongRunningOperation();
 *      ar.resume(result);
 *    }

for more details refer this

like image 25
Abhishek Mishra Avatar answered Oct 18 '22 06:10

Abhishek Mishra