We have been talking about the way to make the async server. Through from being separated with the servlet thread and the worker thread to the way to construct the async server using the DeferredResult and ListenableFuture, Java has allowed the high availablity to us. Especially, the combination with DeferredResult and the ListenableFuture has been very amazing. In the pase, before revealing the DeferredResult and the ListenableFuture, in order to use the callback function in the Future Class, we needed to make the our custmized framework. (I mentioned about this one in Thrid Article before). By the way, after launching the DeferredResult and the ListenableFuture, We have used the callback function in Future Class more safely than before. However, there still exists the things we have to imporve. Look at the code below. This is almost like the code I shared before. However, there are some issues we have to improve(Some people have called about this code as ‘the callback hell’). Like this code, the more requests are needed, the more complexity is increased. Particularly, when we debug in code, this would be more highlighted. So, how can we solve this problem? From the Java8, they have given us the solution which is CompletableFuture which has basically been constructed on based the functional programming(or it could be called like chaining). In this article, I will focus on the way to apply the CompletableFuture to the code I wrote last time than talking about the basic things about the CompletableFuture. The below code is basic form about the CompletableFuture we will use.
CompletableFuture
.supplyAsync(() -> "") // .runAsync(() -> {})
.thenApply(s -> s)
.thenApply(s -> s)
.thenApply(s -> s)
.thenAccept(s -> {})
.exceptionally(e -> {
return null;
});
At first, the CompleatbleFutre is based on the functional programming, so the stability of the data is assured more safely in the multi-threading, so when we make the code about the multi-thread, it helps us to make the codes in the multi-thread easier.(Actually, depending on the people’s point of the view, it may not be called the functional programming.) In addition, the thing we note in here is that it helps us to escape from the callback hell, and debug the code more easily.
- supplyAsync(() -> “”): This is the method when we make the first task using the async, and which should return the data. In contrast with this, runAsync(() -> {}) don’t return the data. They are similar them such as Callable and Runnable.
- thenApply(s -> s): This code allows us to run the next step like callback.
- thenAccept(s -> {}): This is the last function. If you need something after finishing all tasking, it could have a role as the last function.
- exceptionally(e -> null): This is the function for handling about the error. while runnging the tasks, if we are faced on the error, this function could deal with the task about the error. But, please note that this function is requested the return data which is the null.
And, It’s time to adapt the CompletableFuture to the code which I wrote in AsyncServer.java last time, and we are going to test the same scenario.
(Note this link: The Async Of The Spring For High Availability)
And, a code which has a role as the client is that we wrote last time. After that, they will allow us the similar results. (It is never not that I don’t show the results because I am a hassle :) Actually, in the java9 and spring5, they provide us with the more powerful function which is based on the functional programming, and are made using reactive-stream. What I have shared util now would be the base knowledge studying spring5. In the future, I am going to talk the two stories about the design pattern for making the back-end server framework like spring framework and studying the Reactive-programming.