Bana
Bana

Reputation: 117

Async API design client

Lets say I create an async REST API in Spring MVC with Java 8's Completeable.

How is this called in the client? If its non blocking, does the endpoint return something before processing? Ie

@RequestMapping("/")  //GET method
public CompletableFuture<String> meth(){
   thread.sleep(10000);  
   String result = "lol";
   return CompletableFuture.completedFuture(result);
}

How does this exactly work? (This code above is just a randomly made code I just thought of).

When I send a GET request from say google chrome @ localhost:3000/ then what happens? I'm a newbie to async APIs, would like some help.

Upvotes: 3

Views: 1164

Answers (3)

slim
slim

Reputation: 41271

In this version it's pointless, because CompletableFuture.completedFuture() creates a completed Future immediately.

However in a more complex piece of code, you might return a Future that is not yet complete. Spring will not send the response body until some other thread calls complete() on this Future.

Why not just use a new thread? Well, you could - but in some situations it might be more efficient not to. For example you might put a task into an Executor to be handled by a small pool of threads.

Or you might fire off a JMS message asking for the request to be handled by a completely separate machine. A different part of your program will respond to incoming JMS messages, find the corresponding Future and complete it. There is no need for a thread dedicated to this HTTP request to be alive while the work is being done on another system.

Very simple example:

 @RequestMapping("/employeenames/{id}") 
 public CompletableFuture<String> getName(@PathVariable String id){
     CompletableFuture<String> future = new CompletableFuture<>();

     database.asyncSelect(
         name -> future.complete(name),
         "select name from employees where id = ?",
         id
     );

     return future;
  }

I've invented a plausible-ish API for an asynchronous database client here: asyncSelect(Consumer<String> callback, String preparedstatement, String... parameters). The point is that it fires off the query, then does not block the tread waiting for the DB to respond. Instead it leaves a callback (name -> future.complete(name)) for the DB client to invoke when it can.

This is not about improving API response times -- we do not send an HTTP response until we have a payload to provide. This is about using the resources on the server more efficiently, so that while we're waiting for the database to respond it can do other things.


There is a related, but different concept, of asynch REST, in which the server responds with 202 Accepted and a header like Location: /queue/12345, allowing the client to poll for the result. But this isn't what the code you asked about does.

Upvotes: 2

DivyaMaheswaran
DivyaMaheswaran

Reputation: 934

CompletableFuture was introduced by Java to make handling complex asynchronous programming. It lets the programmer combine and cascade async calls, and offers the static utility methods runAsync and supplyAsync to abstract away the manual creation of threads.

These methods dispatch tasks to Java’s common thread pool by default or a custom thread pool if provided as an optional argument.

If a CompletableFuture is returned by an endpoint method and #complete is never called, the request will hang until it times out.

Upvotes: 0

Kayaman
Kayaman

Reputation: 73578

No, the client doesn't know it's asynchronous. It'll have to wait for the result normally. It's just the server side that benefits from freeing up a worker thread to handle other requests.

Upvotes: 3

Related Questions