In this exercise you will learn how to develop reactive endpoints with standard Java functionality via CompletionStage and CompletableFuture.
The service that will be created is an easier implementation of the 'Web-API' service as described earlier. In this exercise the service only returns some dummy data and doesn't invoke other services.
Step 1: Create Quarkus Project
Let's start by creating a new Quarkus project with a synchronous REST endpoint. Invoke the following command the Cloud Shell.
Open a second terminal in the Cloud Shell and invoke the following command.
curlhttp://localhost:8080/fruits
You should see the following response.
The implementation of the synchronous endpoint is in the class FruitResource.java. The annotations @Path, @Get and @Produces are used to define the endpoint via JAX-RS. To learn more about synchronous endpoints, check out the Quarkus guide.
The key difference is the return type. Rather than returning a Response object, a CompletionStage with a Response object is returned.
The CompletionStage is returned immediately, so that the thread is not blocked. Only when it's completed, a callback is invoked which contains the actual response.
To demonstrate this behavior better, a [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) instance is created and returned. CompletableFuture is an implementation of the CompletionStage instance. Once the asynchronous code has been completed, a method 'complete' is invoked on the CompletableFuture object.
The static method 'CompletableFuture.supplyAsync()'` returns a list of sample articles asynchronously for demo purposes. In this case only one sample article is returned.
The CompletionStage interface has several methods. Most of them return CompletionStages again. This allows chaining method invocations as done in the sample code. As input parameters functions are passed in via [Java Lambda](https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html).
The method 'whenComplete' is triggered after the asynchronous methods have been completed.
Another method of CompletionStage is 'thenApply'. This method is invoked after the previous asynchronous methods have been completed. The method can be used, for example, to convert data. In the sample code the list of articles is converted in two steps. First the list of article is converted into a JSON array and then the array is converted into a Response object.
The methods 'stream' and 'map' are only used for the conversion and not related to reactive programming.
In the same way exceptions and errors can occur for synchronous code, they can happen for asychronous code as well.
However the way to handle them is quite different. When invoking asynchronous methods exceptions cannot be handled via 'catch' as usual. Instead the method 'exceptionally' of the interface CompletionStage is used.