Creating async services relying on sync ones
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sat, 10 Dec 2016 00:44:10 +0000 (01:44 +0100)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sat, 10 Dec 2016 00:47:55 +0000 (01:47 +0100)
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/CompletableFutureBusinessLogic.java [new file with mode: 0644]
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/impl/CompletablefutureBusinessLogicImpl.java [new file with mode: 0644]
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java
SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/adapters/CompletableFutureAdapter.java

diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/CompletableFutureBusinessLogic.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/CompletableFutureBusinessLogic.java
new file mode 100644 (file)
index 0000000..dec0011
--- /dev/null
@@ -0,0 +1,19 @@
+package de.spring.webservices.rest.business.service;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import de.spring.webservices.domain.Car;
+
+
+public interface CompletableFutureBusinessLogic {
+
+       public CompletableFuture<Page<Car>> findAll(Pageable pageRequest);
+       
+       public CompletableFuture<Car> findById(long id);
+       
+       public CompletableFuture<Car> create(Car resource);
+       
+}
diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/impl/CompletablefutureBusinessLogicImpl.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/impl/CompletablefutureBusinessLogicImpl.java
new file mode 100644 (file)
index 0000000..0b5af2f
--- /dev/null
@@ -0,0 +1,38 @@
+package de.spring.webservices.rest.business.service.impl;
+
+import java.util.concurrent.CompletableFuture;
+
+import javax.inject.Inject;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import de.spring.webservices.domain.Car;
+import de.spring.webservices.rest.business.service.AwesomeBusinessLogic;
+import de.spring.webservices.rest.business.service.CompletableFutureBusinessLogic;
+
+@Service("completableFutureBusinessLogic")
+public class CompletablefutureBusinessLogicImpl implements CompletableFutureBusinessLogic {
+    private final AwesomeBusinessLogic awesomeBusinessLogic;
+    
+    @Inject
+       public CompletablefutureBusinessLogicImpl(AwesomeBusinessLogic awesomeBusinessLogic) {
+               this.awesomeBusinessLogic = awesomeBusinessLogic;
+       }
+
+       @Override
+       public CompletableFuture<Page<Car>> findAll(Pageable pageRequest) {
+       return CompletableFuture.supplyAsync(() -> awesomeBusinessLogic.findAll(pageRequest));
+       }
+
+       @Override
+       public CompletableFuture<Car> findById(long id) {
+       return CompletableFuture.supplyAsync(() -> awesomeBusinessLogic.findById(id));
+       }
+
+       @Override
+       public CompletableFuture<Car> create(Car car) {
+               return CompletableFuture.supplyAsync(() -> awesomeBusinessLogic.create(car));
+       }
+}
index ad92446..4ecc0c1 100644 (file)
@@ -3,6 +3,8 @@ 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;
@@ -24,8 +26,7 @@ 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.AwesomeBusinessLogic;
-import de.spring.webservices.rest.controller.adapters.CompletableFutureAdapter;
+import de.spring.webservices.rest.business.service.CompletableFutureBusinessLogic;
 
 @RestController
 @RequestMapping("/api/deferrable/cars/")
@@ -34,19 +35,18 @@ public class DeferrableCarController {
        private static final int PAGE = 2;
        private static final int PAGE_SIZE = 10;
        
-       private final AwesomeBusinessLogic awesomeBusinessLogic;
+       private final CompletableFutureBusinessLogic completableFutureBusinessLogic;
 
        @Inject
-    public DeferrableCarController(AwesomeBusinessLogic awesomeBusinessLogic) {
-               this.awesomeBusinessLogic = awesomeBusinessLogic;
+    public DeferrableCarController(CompletableFutureBusinessLogic completableFutureBusinessLogic) {
+               this.completableFutureBusinessLogic = completableFutureBusinessLogic;
        }
 
        @RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET)
     @ResponseStatus(HttpStatus.OK)
     public DeferredResult<Page<Car>> cars() {
-                       
-       return CompletableFutureAdapter.callAdapter(() ->
-               awesomeBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)));
+                                       
+               return deferredAdapter(completableFutureBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)));
     }
 
     @RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
@@ -74,23 +74,32 @@ public class DeferrableCarController {
                }
        }
                
-       return CompletableFutureAdapter.callAdapter(() -> awesomeBusinessLogic.findById(id));
+               return deferredAdapter(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 CompletableFutureAdapter.callAdapter(() -> createResponseCar(car));
+       
+       return deferredAdapter(createAsync(car));
     }
 
     
-    private ResponseEntity<Car> createResponseCar(Car car) {
-               Car createdCar = awesomeBusinessLogic.create(car);
-               
+    private CompletableFuture<ResponseEntity<Car>> createAsync(Car car) {
+       
+       return completableFutureBusinessLogic
+                       .create(car)
+                       .thenComposeAsync(newCar -> 
+                               CompletableFuture.supplyAsync(() -> createResponseCar(newCar))
+               
+                       );              
+    }
+    
+    private ResponseEntity<Car> createResponseCar(Car car) {           
                HttpHeaders headers = new HttpHeaders();
-           headers.add(HttpHeaders.LOCATION, "/api/cars/" + createdCar.getId());
-           return new ResponseEntity<>(createdCar, headers, HttpStatus.CREATED);
+           headers.add(HttpHeaders.LOCATION, "/api/cars/" + car.getId());
+           return new ResponseEntity<>(car, headers, HttpStatus.CREATED);
     }
 }
index 094d5f0..f2ddd5c 100644 (file)
@@ -27,21 +27,20 @@ public class CompletableFutureAdapter {
                public T doCall();
        }
        
-       
-       public static final <T> DeferredResult<T> callAdapter(DeferredCall<T> deferredCall) {
+       public static final <T> DeferredResult<T> deferredAdapter(CompletableFuture<T> completableFuture) {
                
        DeferredResult<T> deferredResult = new DeferredResult<>(ASYNC_TIMEOUT);
-       CompletableFuture
-               .supplyAsync(deferredCall::doCall)
+
+       completableFuture
                .thenAcceptAsync(deferredResult::setResult)
-               .exceptionally(exception -> {
-                       
-                       LOGGER.error("findById error: ", exception);
-                       
-                       deferredResult.setErrorResult(exception);
-                       
-                       return null;
-               });
+               .exceptionally(exception -> {
+                               
+                               LOGGER.error("error: ", exception);
+                               
+                               deferredResult.setErrorResult(exception);
+                               
+                               return null;
+                       });
        
         return deferredResult; 
        }