RestController
Synchronous API
To create an API, we can do as below:
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping(value = "/hello", produces = MediaType.APPLICATION_JSON_VALUE)
public String helloWorld() {
System.out.println("Processing a request");
Thread.sleep(5000);
return "Hello, world!";
}
}
This will create an api endpoint at localhost:8080/api/hello.
The above code is synchronous which means when a thread receives a request, it cannot receive another request until it finish processing the current request.
[!Note]
By default, Tomcat supports 200 concurrent threads so this might not be obvious. However, if you limit the thread to1and call theapi, it will be more obvious.Put the following line in
application.propertiesand call the api:# Set Tomcat thread pool size to 1 server.tomcat.threads.max=1 server.tomcat.threads.min-spare=1Then you will see a delay when calling 2 GET in the same time
Asynchronous
To solve that problem, we can setup our controller asynchronously. As a result, tomcat will still take as many as possible but delegate the process of generating response to a different thread.
For example, for the code above, we could convert to
@GetMapping(value = "/hello", produces = MediaType.APPLICATION_JSON_VALUE)
public Callable<String> helloWorld() throws InterruptedException {
return () -> {
System.out.println("Processing a request");
Thread.sleep(5000);
return "Hello, world!";
};
}
By adding Callable<String> we convert this into an asynchronous call and it will be executed into a different thread.sleep
As a result, although our tomcat only takes 1 thread. It will take a request still and a different thread that's not tomcat will process this request and return Hello, world!.
On the client side, there is nothing that's need to be done, the client will just receive Hello, world doesn't matter how many time concurrently we call it.