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 to1
and call theapi
, it will be more obvious.Put the following line in
application.properties
and call the api:# Set Tomcat thread pool size to 1 server.tomcat.threads.max=1 server.tomcat.threads.min-spare=1
Then 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.