Spring can already work with CompletableFuture
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 11 Dec 2016 22:04:57 +0000 (23:04 +0100)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 11 Dec 2016 22:04:57 +0000 (23:04 +0100)
No need of creating my own adapter :)
See: org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler.CompletionStageAdapter

SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/CompletableFutureCarController.java
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/adapters/CompletableFutureAdapter.java [deleted file]

index 9b199f0..4e1ea8c 100644 (file)
@@ -3,8 +3,6 @@ package de.spring.webservices.rest.controller;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 
-import static de.spring.webservices.rest.controller.adapters.CompletableFutureAdapter.deferredAdapter;
-
 import javax.inject.Inject;
 
 import org.slf4j.Logger;
@@ -23,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.context.request.async.DeferredResult;
 
 import de.spring.webservices.domain.Car;
 import de.spring.webservices.rest.business.service.CompletableFutureBusinessLogic;
@@ -44,14 +41,14 @@ public class CompletableFutureCarController {
 
        @RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET)
     @ResponseStatus(HttpStatus.OK)
-    public DeferredResult<Page<Car>> cars() {
+    public CompletableFuture<Page<Car>> cars() {
                                        
-               return deferredAdapter(completableFutureBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)));
+               return completableFutureBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE));
     }
 
     @RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
     @ResponseStatus(HttpStatus.OK)
-    public DeferredResult<Car> car(@RequestHeader(value = "MY_HEADER", required = false) String specialHeader,
+    public CompletableFuture<Car> car(@RequestHeader(value = "MY_HEADER", required = false) String specialHeader,
                        @PathVariable("id") long id,
                        @RequestParam Map<String, String> params,
                        @RequestParam(value = "wheel", required = false) String[] wheelParams) {
@@ -74,27 +71,21 @@ public class CompletableFutureCarController {
                }
        }
                
-               return deferredAdapter(completableFutureBusinessLogic.findById(id));
+               return completableFutureBusinessLogic.findById(id);
 
     }
     
     @RequestMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
                produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST)
        @ResponseStatus(HttpStatus.CREATED)
-    public DeferredResult<ResponseEntity<Car>> create(@RequestBody Car car) {
-       
-       return deferredAdapter(createAsync(car));
-    }
-
-    
-    private CompletableFuture<ResponseEntity<Car>> createAsync(Car car) {
+    public CompletableFuture<ResponseEntity<Car>> create(@RequestBody Car car) {
        
        return completableFutureBusinessLogic
                        .createThrowable(car)
                        .thenComposeAsync(newCar -> 
                                CompletableFuture.supplyAsync(() -> createResponseCar(newCar))
                
-                       );              
+                       );
     }
     
     private ResponseEntity<Car> createResponseCar(Car car) {           
diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/adapters/CompletableFutureAdapter.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/adapters/CompletableFutureAdapter.java
deleted file mode 100644 (file)
index c451bfb..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-package de.spring.webservices.rest.controller.adapters;
-
-import java.util.concurrent.CompletableFuture;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.context.request.async.DeferredResult;
-
-public class CompletableFutureAdapter {
-       private static final Logger LOGGER = LoggerFactory.getLogger(CompletableFutureAdapter.class);
-
-       // With no value, we depend on the Tomcat/Jboss/Jetty/etc timeout value for asynchronous requests.
-       // Spring will answer after 60 secs with an empty response (by default) and HTTP 503 status (by default) when timeout.
-       private static final long ASYNC_TIMEOUT = 60000;  /* milliseconds */
-       
-       
-       public static final <T> DeferredResult<T> deferredAdapter(CompletableFuture<T> completableFuture) {
-
-       DeferredResult<T> deferredResult = new DeferredResult<>(ASYNC_TIMEOUT);
-
-       completableFuture
-               .thenAcceptAsync(deferredResult::setResult)
-               .exceptionally(exception -> {
-                       Throwable realException = launderException(exception);
-
-                               LOGGER.error("error: ", realException);
-
-                               deferredResult.setErrorResult(exception);
-                               return null;
-                       });
-
-        return deferredResult; 
-       }
-       
-       private static final Throwable launderException(Throwable exception) {
-               return exception.getCause() != null
-                          ? exception.getCause()
-                          : exception;
-       }
-}