Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JAX RS and CDI bike the reactive bridge

914 views

Published on

The slides of our talk with David Delabassee about the reactive extensions introduced in JAX RS 2.2 and CDI 2.0, in Java EE 8.

Published in: Education
  • Be the first to comment

JAX RS and CDI bike the reactive bridge

  1. 1. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS and CDI Bike the (Reactive) Bridge CON2549 David Delabassée (@delabassee) - Oracle José Paumard (@josepaumard) - Consultant October, 2017 2
  2. 2. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 3 @delabassee
  3. 3. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 4 @JosePaumard @JosePaumard https://github.com/JosePaumard https://www.slideshare.net/jpaumard https://www.youtube.com/user/JPaumard
  4. 4. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 5
  5. 5. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 6
  6. 6. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 7 reactive adjective | re·ac·tive | rē-ˈak-tiv 1 :of, relating to, or marked by reaction or reactance 2 a :readily responsive to a stimulus https://www.merriam-webster.com/dictionary/reactive
  7. 7. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS 8
  8. 8. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS 2.1 • JSR 370 – Java EE 8 • Async – New Reactive Client API – New method for pausing resquest processing, etc. • Server-Sent Event support • JSON-P & JSON-B support • … Java API for RESTful Web Services 9
  9. 9. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | // JAX-RS 2.0 Client client = ClientBuilder.newClient(); WebTarget target = client.target("http://weath.er/api") .queryParam("city", "Paris"); Forecast forecast = target.request() .get(Forecast.class); // … client.close(); JAX-RS Client API 10
  10. 10. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API • Fluent API – Client Builder  Client  Web Target  Request building  Response javax.ws.rs.client.Client interface 11 List<Forecast> forecast = ClientBuilder.newClient() .target("http://weath.er/cities") .request() .accept("application/json") .header("Foo","bar") .get(new GenericType<List<Forecast>>() {});
  11. 11. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API • Synchronous invoker • Asynchronous invoker JAX-RS 2.0 Invokers 12 String city = client.target("http://locati.on/api") .queryParam("city", "Paris") .request() .get(String.class); Future<String> fCity = client.target("http://locati.on/api") .queryParam("city", "Paris") .request() .async() .get(String.class);
  12. 12. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API Asynchronous invocation 13 Future<String> fCity = client.target("http://locati.on/api") .queryParam("city", "Paris") .request() .async() .get(String.class); String city = fCity.get();
  13. 13. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API Asynchronous invocation 14 Future<String> fCity = client.target("http://locati.on/api") .queryParam("city", "Paris") .request() .async() .get(String.class); try { String city = fCity.get(5, TimeUnit.SECONDS); } catch(TimeoutException timeout) { // … }
  14. 14. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API Asynchronous invocation 15 // Set ClientProperties.CONNECT_TIMEOUT & READ_TIMEOUT Future<String> fCity = client.target("http://locati.on/api") .queryParam("city", "Paris") .request() .async() .get(String.class); while ( !fCity.isDone() ) { // response hasn't been received yet } String city = fCity.get();
  15. 15. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API • InvocationCallback Interface – javax.ws.rs.client.InvocationCallback<RESPONSE> • Container will receive async processing events from an invocation – completed(RESPONSE response) – failed(Throwable throwable) Asynchronous invocation 16
  16. 16. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API WebTarget myResource = client.target("http://examp.le/api/read"); Future<Customer> future = myResource.request(MediaType.TEXT_PLAIN) .async() .get(new InvocationCallback<Customer>() { @Override public void completed (Customer customer) { // do something with the customer } @Override public void failed (Throwable throwable) { // Oops! } }); … InvocationCallback 17
  17. 17. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 18
  18. 18. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service • Customer details: 150 ms • Recommended destinations: 250 ms • Price calculation for a customer and destination: 170 ms (each) • Weather forecast for a destination: 330 ms (each) Synchronous 19 5 400 ms
  19. 19. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service Asynchronous 20 730 ms
  20. 20. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 21
  21. 21. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 22 destination.path("recommended").request() .header("Rx-User", "Async") .async() .get(new InvocationCallback<List<Destination>>() { @Override public void completed(final List<Destination> recommended) { final CountDownLatch innerLatch = new CountDownLatch(recommended.size()); final Map<String, Forecast> forecasts = Collections.synchronizedMap(new HashMap<>()); for (final Destination dest : recommended) { forecast.resolveTemplate("dest", dest.getDestination()).request() .async() .get(new InvocationCallback<Forecast>() { @Override public void completed(final Forecast forecast) { forecasts.put(dest.getDestination(), forecast); innerLatch.countDown(); }
  22. 22. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 23 // cont. @Override public void failed(final Throwable throwable) { innerLatch.countDown(); } }); } try { if (!innerLatch.await(10, TimeUnit.SECONDS)) { // timeout } } catch (final InterruptedException e) { // Ooops, interrupted! } // Continue with processing… } @Override public void failed(final Throwable throwable) { // Recommendation error } }); // ...
  23. 23. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API New JAX-RS Reactive Invoker 24 // JAX-RS 2.0 Response response = client.target(recommandationService) .request() .get(); Future<Response> futureResponse = client.target(recommandationService) .request() .async() .get(); // JAX-RS 2.1 CompletionStage<Response> completionStageResp = client.target(recommandationService) .request() .rx() .get();
  24. 24. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | CompletionStage API • A model for a Task – That performs an action and may return a value – That can be triggered by another task – That may trigger another task – That can be executed in a different thread • A CompletionStage is an element of an asynchronous chain 25
  25. 25. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | CompletionStage Pipeline 26 CS1 CS21 CS22 CS31 CS41 CS32
  26. 26. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 27 CompletionStage<JsonObject> queryForecastCS = client.target("forecast") .queryParam("format", "json").request() .rx() .get(JsonObject.class); Function<JsonObject, Forecast> unmarshallForecast = jsonObject -> JsonBuilder.create().fromJson(jsonObject.toString(), Forecast.class); Function<Destination, CompletionStage<Void>> populateWithForecast = destination -> queryForecastCS.thenApply(unmarshallForecast) .thenAccept(forecast -> destination.setForecast(forecast)); Function<Destination, CompletionStage<Void>> populateWithQuotation = destination -> queryQuotationCS.thenApply(unmarshallQuotation) .thenAccept(quotation -> destination.setQuotation(quotation));
  27. 27. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 28 Function<Destination, CompletableFuture<Void>> populateDestination = destination -> CompletableFuture.allOf( populateWithForecast.apply(destination).toCompletableFuture(), populateWithQuotation.apply(destination).toCompletableFuture() ) .toCompletableFuture();
  28. 28. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 29 Function<Destination, CompletableFuture<Void>> populateDestination = destination -> CompletableFuture.allOf( populateWithForecast.apply(destination).toCompletableFuture(), populateWithQuotation.apply(destination).toCompletableFuture() ) .toCompletableFuture(); Function<List<Destination>, CompletableFuture<?>[]> populateDestinations = destinations -> destinations.stream().map(populateDestination) .toArray(CompletableFuture[]::new);
  29. 29. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 30 @GET public void populateDestination(@Suspended final AsyncResponse asyncResponse) { CompletionStage<List<Destination>> destinationCS = client.target("destination") .queryParam("format", "json").request() .rx() .get(/* some JSONB code */); CompletionStage<List<Destination>> updatedDestinationsCS = destinationCS.thenCompose(CompletableFuture.allOf(populateDestinations)); asyncResponse.resume(updatedDestinationsCS.toCompletableFuture().get()); }
  30. 30. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service 31 @GET public CompletionStage<Destination> populateDestination() { CompletionStage<List<Destination>> destinationCS = client.target("destination") .queryParam("format", "json").request() .rx() .get(/* some JSONB code */); CompletionStage<List<Destination>> updatedDestinationsCS = destinationCS.thenCompose(CompletableFuture.allOf(populateDestinations)); return updatedDestinationsCS; }
  31. 31. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Exception Handling 32 CS1 CS21 CS22 CS31 CS41 CS32
  32. 32. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Exception Handling Returns a new CompletionStage • That completes when the CS completes • Either with the same result (normal completion) • Or with the transformed exception 33 exceptionaly() stage.exceptionaly( // Function exception -> doSomethingNotTooStupidWith(exception));
  33. 33. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Exception Handling Returns a new CompletionStage • That completes when the CS completes • Calls the BiFunction with a null as result or exception 34 handle() stage.handle( // BiFunction (result, exception) -> doSomethingWith(result, exception));
  34. 34. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Exception Handling Returns a new CompletionStage • With the same result or exception as this stage • That executes the given action when this stage completes 35 whenComplete() stage.whenComplete( // BiConsumer + async version (result, exception) -> doSomethingWith(result, exception));
  35. 35. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Exception Handling 36 CompletionStage<Void> quotation = client.target("quotation") .request().rx().get(JsonObject.class) .thenApply(unmarshallQuotation) .exceptionnaly(throwable -> null) .thenAccept(destination::setQuotation);
  36. 36. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Exception Handling 37 CompletionStage<Void> quotation = client.target("quotation") .request().rx().get(JsonObject.class) .thenApply(unmarshallQuotation) .handle(((quotation, throwable) -> { if (throwable == null) { destination.setQuotation(quotation); } else { // try to do something smart with the exception } }
  37. 37. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Reactive Extensions • Supported on all HTTP Methods of the Client API – DELETE – GET – HEAD – OPTIONS – POST – PUT – TRACE 38
  38. 38. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Reactive Extensions • Implementations MUST support an invoker for CompletionStage • Implementations MAY support other reactive APIs • Jersey – CompletionStageRxInvoker (Default) – RxListenableFutureInvoker – Guava 39 https://github.com/jersey/jersey/tree/master/ext/rx client.register(RxFlowableInvokerProvider.class); client.target(...)... .rx(RxFlowableInvoker.class) .get(); – RxObservableInvoker – RxJava – RxFlowableInvoker – RxJava2
  39. 39. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | CDI 40
  40. 40. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | CDI 2.0 • JSR 365 – Java EE 8 • Java SE focus – Modular specification – CDI Container bootstraping • Observers Ordering • Asynchronous Events • … Context and Dependency Injection 41
  41. 41. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Asynchronous Events 42 // Producer @Inject Event<Payload> event; public void aCriticalBusinessMethod() { CompletionStage<Payload> cs = event.fireAsync(new Payload()); } // Consumer public void anOberser(@ObservesAsync Payload event) { // do something with the payload }
  42. 42. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Asynchronous Events 43 // Producer @Inject Event<Payload> event; public void aCriticalBusinessMethod() { CompletionStage<Payload> cs = event.fireAsync(new Payload(), executor); }
  43. 43. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Asynchronous Events 44 // Producer @Inject Event<Payload> event; public void aCriticalBusinessMethod() { CompletionStage<Payload> cs = event.fireAsync(new Payload(), SwingUtilities::invokeLater); }
  44. 44. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Wrap-up 45
  45. 45. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Java EE 8 – Modernization & Simplification 46 CDI 2.0 JSON-B 1.0 (*) Security 1.0 (*) Bean Validation 2.0 JSF 2.3 Servlet 4.0 JSON-P 1.1 JAX-RS 2.1 Reactive Client API, Server-Sent Events, … HTTP/2, Server Push, … Java <-> JSON binding Updates to JSON standards, JSON Collectors, … Async Event, Observers ordering, SE support, … Embrace Java SE 8, new constraints, … Improved CDI, WebSocket, SE 8 integration, … Portable Identity Store, Authentication & Security Context

×