0

I am building Mobile backend API using Java EE - JAX-RS 2.0 technology.

Since most of mobile client consumes are asynchronous http calls

so my question is: Should I use asynchronous feature for all JAX-RS resources? And the reason if not?

The below is the template Mobile Async API

@Path("/async_api")
public class AsyncResource {

    @GET
    @Path("/loadUsers")
    @Produces(MediaType.APPLICATION_JSON)
    public void loadUsers(@Suspended AsyncResponse asyncResponse) {

        //TODO: ManagedExecutorService

        new Thread(new Runnable() {

            @Override
            public void run() {
                List users = loadBigUsers();
                asyncResponse.resume(users);
            }

            private List loadBigUsers() {
                return null; // Return big list
            }

        }).start();
    }
}

Thank you!

LHA
  • 9,398
  • 8
  • 46
  • 85
  • 1
    No. Asynchronous at the client doesn't imply asynchronous at the server, and *vice versa.* Make your own decision at each end independently. – user207421 Mar 25 '16 at 04:52
  • 2
    You should use async on the server for long running tasks so it doesn't hold up the container threads. – Paul Samsotha Mar 25 '16 at 05:06

1 Answers1

5

In JAX-RS the @Suspendannotation and AsyncResponse are needed only in certain typical scenarios. The first scenario was already identified in your code example. It is long running tasks. In this case the AsyncResponse can be used to execute long running code in a background thread. While this would not make sense at the first glance we need to think about how an application server / container handles its requests. Usually there is a pool of threads that accepts and handles client requests. If you implement expensive operations inline in your JAX-RS service methods one of the threads in the pool is blocked for the entire runtime. With the AsyncResponse the executor thread gets returned to the pool and other requests can be served in parallel.

@Path("/users")
public class UserRestService {

    @GET
    public void getAllUsers(@Suspend final AsyncResponse asyncResponse) {
        new Thread(new Runnable(
            @Override
            public void run() {
                List<Users> users = UserDAO.loadAllUsers();
                asyncResponse.resume(users);
            }
        ) {}).start();
    }
}

The second application scenario for AsyncResponse is the often seen pattern of producer consumer patterns. Assuming you have a queue bound to the URL https://yourservice.at/queue/next then a @GET method can be used for a blocking take() on lets say a LinkedBlockingQueue. On the same URL you could bind a @POST method which adds data to the queue. In this case you would wrap up the functionality with the take() operation in an AsyncResponse.

@Path("/queue/next")
public class MessageQueueService {

    private static final LinkedBlockingQueue<AsyncResponse> suspendedResponses = new LinkedBlockingQueue<AsyncResponse>();

    @GET
    public void getNextMessage(@Suspend final AsyncResponse asyncResponse) {
        MessageQueueService.suspendedResponses.put(asyncResponse);
    }

    @POST
    public void putNewMessage(final String message) throws InterruptedException {
        AsyncResponse asyncResponse = suspendedResponses.take(); // note how this could also block a thread
        asyncResponse.resume(message);
    }
}

From these explanations you can also see, that the JAX-RS @Suspended mechanism is used to create an asynchronous server side task. Whether or not the same request is also executed in an asynchronous manner on the client is a whole different story.

renal
  • 39
  • 4
Matthias Steinbauer
  • 1,786
  • 11
  • 24