15

I have a REST service implemented with JAX-RS. Some of the operations take a long time to complete, potentially 15-30 minutes. For these cases, my inclination is to dispatch a background thread to process the long running operation and then respond immediately with HTTP status 202 ACCEPTED. The response would contain a location header with a url that clients can use to poll for progress.

This approach requires the creation of threads to handle long running operations, such that 202 ACCEPTED can be returned immediately. I also know that that creating your own threads in a Java EE container is generally bad practice!

My questions are as follows:

  1. Do folks agree that this is a correct approach?
  2. Assuming it is correct, Can folks recommend a 'good practice' solution that enables me to dispatch a long running operation in the background and return immediately?

Also, to avoid managing my own threads, I looked into the JAX-RS asynchronous server api. Unfortunately, although this improves server throughput, it will not allow me to respond immediately with ACCEPTED.

Jersey states the following:

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.

Any help is appreciated. Thanks!

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
cmd
  • 11,622
  • 7
  • 51
  • 61

3 Answers3

5

I also know that that creating your own threads in a Java EE container is generally bad practice!

Although the above is true in most cases, in this one you don't have a choice. At least don't create your Thread instances yourself. Let an ExecutorService do it for you. If anything, make this ExecutorService have a big enough pool and share it with all your components.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Thanks. I agree something blessed like ExecutorService should be used to manage the threads. I do still have a queasy feeling about dispatching them. Also, I am using EJBs and the EJB spec states: • The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups. Can my runnables be Stateful session beans? Perhaps yes? Can the class that uses ExecutorService to dispatch the thread be a Stateless Singleton? No? – cmd Sep 13 '13 at 18:02
  • 1
    @cmd With `EJB`, perhaps look at [this](http://stackoverflow.com/questions/13932083/jboss-java-ee-container-and-an-executorservice) – Sotirios Delimanolis Sep 13 '13 at 18:08
  • Thanks this quite close to I'm going for. – cmd Sep 13 '13 at 22:09
  • @SotiriosDelimanolis Please see this and help. Thanks for your time. http://stackoverflow.com/questions/19706788/jersey-rest-web-service-with-activemq-middleware-integration – Kumar Nov 06 '13 at 06:17
2

I think that Jersey Async docs exhaust the topic quite well. Here is a brief snippet:

@Path("/async/longRunning")
public class MyResource {

   @GET
   public void longRunningOp(@Suspended final AsyncResponse ar) {
       executor.submit(
            new Runnable() {
                public void run() {
                    executeLongRunningOp();
                    ar.resume("Hello async world!");
                } });
  }
}

When it comes to the following quotation from the docs:

Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client.(...)

I thing you have misunderstood it a bit. What the author of the docs tried to express here is that asynchroneous processing will not speed up things just by itself. But the response can be returned immediately using for instance the following:

return Response.status(Status.ACCEPTED).build();
Wojciech Owczarczyk
  • 5,595
  • 2
  • 33
  • 55
0

I would make a method which immediately returns response with process id and time when it will be completed. A calculation starts in background and it is cached for some time after completion. Then client tries to retrieve information with specific id and gets related response.

Justinas Jakavonis
  • 8,220
  • 10
  • 69
  • 114