--- /dev/null
+package de.spring.webservices.rest.business.service.impl;
+
+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.RxJavaBusinessLogic;
+import rx.Observable;
+
+/**
+ *
+ *
+ * TODO: WHAT ABOUT EXCEPTIONS FROM awesomeBusinessLogic? RuntimeExceptions for example
+ * I guess they will be caught by my adapter in controller layer but I must try it.
+ *
+ */
+
+
+@Service("rxJavaBusinessLogic")
+public class RxJavaBusinessLogicImpl implements RxJavaBusinessLogic {
+ private final AwesomeBusinessLogic awesomeBusinessLogic;
+
+ @Inject
+ public RxJavaBusinessLogicImpl(AwesomeBusinessLogic awesomeBusinessLogic) {
+ this.awesomeBusinessLogic = awesomeBusinessLogic;
+ }
+
+ @Override
+ public Observable<Page<Car>> findAll(Pageable pageRequest) {
+ return Observable.create(observer -> observer.onNext( awesomeBusinessLogic.findAll(pageRequest)));
+
+ }
+
+ @Override
+ public Observable<Car> findById(long id) {
+ return Observable.create(observer -> observer.onNext( awesomeBusinessLogic.findById(id)));
+ }
+
+ @Override
+ public Observable<Car> create(Car car) {
+ return Observable.create(observer -> observer.onNext(awesomeBusinessLogic.create(car)));
+ }
+}
package de.spring.webservices.rest.controller;
+import static de.spring.webservices.rest.controller.adapters.RxJavaAdapter.deferredAdapter;
+
import java.util.Map;
-import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
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.business.service.RxJavaBusinessLogic;
+import rx.Observable;
@RestController
@RequestMapping("/api/rxjava/cars/")
private static final Logger LOGGER = LoggerFactory.getLogger(RxJavaCarController.class);
private static final int PAGE = 2;
private static final int PAGE_SIZE = 10;
-
- // 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 */
-
- /**
- *
- * WHEN EXCEPTION IN setErrorResult, Spring WILL TRIGGER THE Spring Exception Handler AS YOU KNOW IT (I HOPE)
- * SO, YOU COULD HOOK UP THE HANDLER AND RETURN YOUR CUSTOM MESSAGESS (as usual)
- *
- */
-
- private final AwesomeBusinessLogic awesomeBusinessLogic;
+
+ private final RxJavaBusinessLogic rxJavaBusinessLogic;
@Inject
- public RxJavaCarController(AwesomeBusinessLogic awesomeBusinessLogic) {
- this.awesomeBusinessLogic = awesomeBusinessLogic;
+ public RxJavaCarController(RxJavaBusinessLogic completableFutureBusinessLogic) {
+ this.rxJavaBusinessLogic = completableFutureBusinessLogic;
}
@RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public DeferredResult<Page<Car>> cars() {
-
- // THIS CODE (I GUESS) SHOULD BE LOCATED IN Service layer. Anyhow this is just an example.
- DeferredResult<Page<Car>> deferredResult = new DeferredResult<>(ASYNC_TIMEOUT);
- CompletableFuture
- .supplyAsync(() -> awesomeBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)))
- .thenAcceptAsync(car -> deferredResult.setResult(car))
- .exceptionally(exception -> {
- LOGGER.error("findAll error: ", exception);
-
- // DO NOT FORGET THE EXCEPTIONS.
- // It will trigger the Spring Exception Handler as you know it :)
- deferredResult.setErrorResult(exception);
-
- return null;
- });
-
- return deferredResult;
+
+ return deferredAdapter(rxJavaBusinessLogic.findAll(new PageRequest(PAGE, PAGE_SIZE)));
}
@RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
LOGGER.info(wheel);
}
}
-
- // THIS CODE (I GUESS) SHOULD BE LOCATED IN Service layer. Anyhow this is just an example.
- DeferredResult<Car> deferredResult = new DeferredResult<>(ASYNC_TIMEOUT);
- CompletableFuture
- .supplyAsync(() -> awesomeBusinessLogic.findById(id))
- .thenAcceptAsync(car -> deferredResult.setResult(car))
- .exceptionally(exception -> {
-
- LOGGER.error("findById error: ", exception);
-
- // DO NOT FORGET THE EXCEPTIONS.
- // It will trigger the Spring Exception Handler as you know it :)
- deferredResult.setErrorResult(exception);
-
- return null;
- });
-
- return deferredResult;
+
+ return deferredAdapter(rxJavaBusinessLogic.findById(id));
+
}
@RequestMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
@ResponseStatus(HttpStatus.CREATED)
public DeferredResult<ResponseEntity<Car>> create(@RequestBody Car car) {
- // THIS CODE (I GUESS) SHOULD BE LOCATED IN Service layer. Anyhow this is just an example.
- DeferredResult<ResponseEntity<Car>> deferredResult = new DeferredResult<>(ASYNC_TIMEOUT);
- CompletableFuture
- .supplyAsync(() -> {
- Car createdCar = awesomeBusinessLogic.create(car);
-
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.LOCATION, "/api/cars/" + createdCar.getId());
- return new ResponseEntity<>(createdCar, headers, HttpStatus.CREATED);
- })
- .thenAcceptAsync(response -> deferredResult.setResult(response))
- .exceptionally(exception -> {
-
- LOGGER.error("create error: ", exception);
-
- // DO NOT FORGET THE EXCEPTIONS.
- // It will trigger the Spring Exception Handler as you know it :)
- deferredResult.setErrorResult(exception);
-
- return null;
- });
-
- return deferredResult;
+ return deferredAdapter(createAsync(car));
}
+
+ private Observable<ResponseEntity<Car>> createAsync(Car car) {
+
+ return rxJavaBusinessLogic
+ .create(car)
+ .map(this::createResponseCar);
+ }
+
+ private ResponseEntity<Car> createResponseCar(Car car) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(HttpHeaders.LOCATION, "/api/cars/" + car.getId());
+ return new ResponseEntity<>(car, headers, HttpStatus.CREATED);
+ }
}
--- /dev/null
+package de.spring.webservices.rest.controller.adapters;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import rx.Observable;
+import rx.schedulers.Schedulers;
+
+public class RxJavaAdapter {
+ private static final Logger LOGGER = LoggerFactory.getLogger(RxJavaAdapter.class);
+
+ /**
+ *
+ * WHEN EXCEPTION IN setErrorResult, Spring WILL TRIGGER THE Spring Exception Handler AS YOU KNOW IT (I HOPE)
+ * SO, YOU COULD HOOK UP THE HANDLER AND RETURN YOUR CUSTOM MESSAGESS (as usual)
+ *
+ */
+
+ // 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 */
+
+
+ @FunctionalInterface
+ public interface DeferredCall<T> {
+
+ public T doCall();
+ }
+
+ public static final <T> DeferredResult<T> deferredAdapter(Observable<T> observable) {
+
+ DeferredResult<T> deferredResult = new DeferredResult<>(ASYNC_TIMEOUT);
+
+ observable
+ .subscribeOn(Schedulers.io())
+ .subscribe(deferredResult::setResult, exception -> LOGGER.error("error: ", exception));
+
+ return deferredResult;
+ }
+
+}