From 29fb87d1b55b9752aaca5ec9f0784460e0a85ae2 Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Sat, 10 Dec 2016 01:44:10 +0100 Subject: [PATCH] Creating async services relying on sync ones --- .../service/CompletableFutureBusinessLogic.java | 19 ++++++++++ .../impl/CompletablefutureBusinessLogicImpl.java | 38 ++++++++++++++++++++ .../rest/controller/DeferrableCarController.java | 41 +++++++++++++--------- .../adapters/CompletableFutureAdapter.java | 23 ++++++------ 4 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/CompletableFutureBusinessLogic.java create mode 100644 SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/impl/CompletablefutureBusinessLogicImpl.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 index 0000000..dec0011 --- /dev/null +++ b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/CompletableFutureBusinessLogic.java @@ -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> findAll(Pageable pageRequest); + + public CompletableFuture findById(long id); + + public CompletableFuture 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 index 0000000..0b5af2f --- /dev/null +++ b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/business/service/impl/CompletablefutureBusinessLogicImpl.java @@ -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> findAll(Pageable pageRequest) { + return CompletableFuture.supplyAsync(() -> awesomeBusinessLogic.findAll(pageRequest)); + } + + @Override + public CompletableFuture findById(long id) { + return CompletableFuture.supplyAsync(() -> awesomeBusinessLogic.findById(id)); + } + + @Override + public CompletableFuture create(Car car) { + return CompletableFuture.supplyAsync(() -> awesomeBusinessLogic.create(car)); + } +} diff --git a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java index ad92446..4ecc0c1 100644 --- a/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java +++ b/SpringJava/RxJava/web-services-spring-rxjava-server/src/main/java/de/spring/webservices/rest/controller/DeferrableCarController.java @@ -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> 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> create(@RequestBody Car car) { - - return CompletableFutureAdapter.callAdapter(() -> createResponseCar(car)); + + return deferredAdapter(createAsync(car)); } - private ResponseEntity createResponseCar(Car car) { - Car createdCar = awesomeBusinessLogic.create(car); - + private CompletableFuture> createAsync(Car car) { + + return completableFutureBusinessLogic + .create(car) + .thenComposeAsync(newCar -> + CompletableFuture.supplyAsync(() -> createResponseCar(newCar)) + + ); + } + + private ResponseEntity 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); } } 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 index 094d5f0..f2ddd5c 100644 --- 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 @@ -27,21 +27,20 @@ public class CompletableFutureAdapter { public T doCall(); } - - public static final DeferredResult callAdapter(DeferredCall deferredCall) { + public static final DeferredResult deferredAdapter(CompletableFuture completableFuture) { DeferredResult 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; } -- 2.1.4