Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

REST in an Async World

1 713 vues

Publié le

Presented at Oracle Code Israel (July 2017)

Publié dans : Logiciels
  • Soyez le premier à commenter

REST in an Async World

  1. 1. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | David Delabassee @delabassee Oracle REST in an Async World Israel – July 2017
  2. 2. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 2
  3. 3. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 3
  4. 4. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Safe Harbor Statement The following is intended to outline our general product direcPon. It is intended for informaPon purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or funcPonality, and should not be relied upon in making purchasing decisions. The development, release, and Pming of any features or funcPonality described for Oracle’s products remains at the sole discrePon of Oracle. 4
  5. 5. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Agenda •  REST & JAX-RS •  Synchronous vs. Asynchronous •  Client-side vs. Server-side 5
  6. 6. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Client-side REST ConfidenPal – Oracle Internal/Restricted/Highly Restricted 6
  7. 7. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS •  Java API for RESTful Web Services – JAX-RS 2.0 – JSR 339 (*) – JAX-RS 2.1 – JSR 370 •  Standard based RESTful framework – Server-side and client-side – Jersey, JBoss RESTEasy, Restlet, Apache CXF, Apache Wink, IBM JAX-RS, … •  Java SE and Java EE 7
  8. 8. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 8 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
  9. 9. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API •  Client – Client side container – Customizable & tunable • E.g. executorService() (new in JAX-RS 2.1!) •  WebTarget – Target remote URI – Build from a client – path() + resolveTemplates(), queryParam(), matrixParam() javax.ws.rs.client.Client interface 9
  10. 10. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API •  Request invocaPon builder – Build from a WebTarget – acceptXXX(), cookie(), header(), cacheControl()… – HTTP methods javax.ws.rs.client.Client interface 10
  11. 11. 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>>() {});
  12. 12. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API •  Synchronous invoker •  Asynchronous invoker 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);
  13. 13. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API Asynchronous invoca.on 13 Future<String> fCity = client.target("http://locati.on/api") … .request() .async() .get(String.class); String city = future.get();
  14. 14. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API Asynchronous invoca.on 14 Future<String> fCity = client.target("http://locati.on/api") … .request() .async() .get(String.class); try { String city = future.get(4, TimeUnit.SECONDS); } catch(TimeoutException timeout) { … }
  15. 15. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API Asynchronous invoca.on 15 Future<String> future = client.target("http://locati.on/api") … .request() .async() .get(String.class); while (!future.isDone()) { // response hasn't been received yet … } String city = f.get(); … // Set ClientProperties.CONNECT_TIMEOUT & READ_TIMEOUT
  16. 16. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API •  InvocaPonCallback Interface – javax.ws.rs.client.InvocaPonCallback<RESPONSE> •  Container will receive asynchronous processing events from an invocaPon – completed(RESPONSE response) – failed(Throwable throwable) 16 Asynchronous invoca.on
  17. 17. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API 17 Invoca.onCallback … 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 given customer } @Override public void failed (Throwable throwable) { // Oops! } });
  18. 18. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 18 The Travel Service
  19. 19. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service - Synchronous •  Customer details: 150 ms •  Recommended desPnaPons: 250 ms •  Price calculaPon for a customer and desPnaPon: 170 ms (each) •  Weather forecast for a desPnaPon: 330 ms (each) 19 5 400 ms
  20. 20. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | The Travel Service - Asynchronous 20 730 ms
  21. 21. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 21 The Travel Service
  22. 22. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 22 The Travel Service 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(); }
  23. 23. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 23 JAX-RS 2.0 @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 } });
  24. 24. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 24 JAX-RS 2.1 // JAX-RS 2.1 CompletionStage<Response> csResponse = ClientBuilder.newClient() .target("http://example.com/api") .request() .rx() .get(); Future<Response> fResponse = ClientBuilder.newClient() .target("http://example.com/api") .request() .async() .get(); Response response = ClientBuilder.newClient() .target("http://example.com/api") .request() .get();
  25. 25. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | ComplePonStage interface •  “A stage of a possibly asynchronous computaPon, that performs an ac.on or computes a value” •  “On termina.on a stage may in turn trigger other dependent stages.” •  Stage execuPon triggered by complePon of – “then” - a single stage – “combine” - both of two stages – “either” - either of two stages 25
  26. 26. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | ComplePonStage interface •  ComputaPon takes an argument and returns a result? – “apply” – Func.on take result of the previous stage as argument, return a result – “accept” – Consumer only take an argument – “run” – Runnable no argument and doesn’t return a result •  How the execuPon of the computaPon is arranged? – Doesn't end with “async” – execute using the stage’s default execuPon facility – End with “async” - use the stage’s default asynchronous execuPon facility •  … 26 hsps://docs.oracle.com/javase/8/docs/api/java/uPl/concurrent/ComplePonStage.html
  27. 27. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 27 JAX-RS 2.1 CompletionStage<Number> csPrice = client.target("price/{destination}") .resolveTemplate("destination", "Paris") .request() .rx() .get(Number.class); CompletionStage<String> csForecast = client.target("forecast/{destination}") .resolveTemplate("destination", "Paris") .request() .rx() .get(String.class); csPrice.thenCombine( csForecast, (price, forecast) -> book(price, forecast) );
  28. 28. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 28 Demo The Travel Service hsps://github.com/jersey/jersey/tree/master/examples/rx-client-webapp
  29. 29. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS Client API •  REST Client Side container •  Synchronous invoker – Default invoker - javax.ws.rs.client.SyncInvoker •  Asynchronous invokers – async() invoker - javax.ws.rs.client.AsyncInvoker •  Might block -> InvocaPonCallback – ReacPve rx() invoker - javax.ws.rs.client.RxInvoker •  New in JAX-RS 2.1! •  ComplePonStage API + other ReacPve library (opt.) 29 Summary
  30. 30. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Server-side REST ConfidenPal – Oracle Internal/Restricted/Highly Restricted 30
  31. 31. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 31 Server-side @Path("/Item") public class ItemResource { @Path("{id}") @Produces(MediaType.APPLICATION_XML) public ItemResource getItemResource(@PathParam("id") String id) { return ItemResource.getInstance(id); } @POST @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) public Response createItem(@QueryParam("name") String name) { //... return Response.status(Status.OK).entity(…).build(); } }
  32. 32. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 32 Server-side Async @Path("/Async") public class ItemResource { @GET public void heavyResource(@Suspended AsyncResponse ar) { mes.execute(new Runnable() { @Override public void run() { try { // long running computation... ar.resume(Response.ok(...).build()); } catch (InterruptedException ex) { // Ooops! } } }); ...
  33. 33. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Server-side Async •  Provides means for asynchronous server side response processing – Injectable via @Suspended OR – Resource method can return a ComplePonStage<T> instance (new in JAX-RS 2.1!) •  Bound to the request – Suspend – Resume – Configure – Cancel 33 AsyncResponse interface
  34. 34. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Server-side Async 34 Client Server @Suspended AsyncResponse.resume(…) Long running operaPon… Request Response
  35. 35. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Long running REST operaPons è POST ... long running operaPon ... ç ‘201 Created’ + LocaPon 35 è POST ç ‘202 Accepted’ + Temp LocaPon è GET Temp LocaPon ç ‘200 OK’ (+ ETA) … è GET Temp LocaPon ç ‘303 See Other’ + Final LocaPon
  36. 36. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Server-sent Events •  Persistent, one-way communicaPon channel •  Text protocol, special media type "text/event-stream" •  Server can send mulPple messages (events) to a client •  Can contain id, name, comment retry interval •  Supported in all modern browsers 36
  37. 37. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS 2.1 37 SSE •  SseEvent – ID, Name, Comment, … •  OutboundSseEvent – Server-side representaPon of a Server-sent event – OutboundSseEvent.Builder() •  InboundSseEvent – Client-side representaPon of a Server-sent event
  38. 38. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS 2.1 38 SSE – Server side •  SseEventSink – Outbound Server-Sent Events stream – SseBroadcaster @GET @Path ("sse") @Produces(MediaType.SERVER_SENT_EVENTS) public void eventStream(@Context SseEventSink eventSink, @Context SSE sse) { ... eventSink.send( sse.newEvent("an event") ); eventSink.send( sse.newEvent("another event") ); ... eventSink.close(); }
  39. 39. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS 2.1 39 SSE – Client side •  SseEventSource – Client for processing incoming Server-Sent Events SseEventSource es = SseEventSource.target(SSE_target) .reconnectingEvery(5, SECONDS) .build(); es.register(System.out::println); // InboundSseEvent consumer es.register(...); // Throwable consumer es.open(); ... es.close();
  40. 40. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Wrap-up ConfidenPal – Oracle Internal/Restricted/Highly Restricted 40
  41. 41. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS •  Java API for RESTful Web Services – JAX-RS 2.0 – JSR 339 (*) – JAX-RS 2.1 – JSR 370 •  Standard based RESTful framework – Server-side and client-side – Java SE and Java EE – Jersey, JBoss RESTEasy, Restlet, Apache CXF, Apache Wink, IBM JAX-RS, … 41
  42. 42. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS – Client-side •  REST Client Side container •  Invokers – Synchronous •  javax.ws.rs.client.SyncInvoker •  Default – Asynchronous •  javax.ws.rs.client.AsyncInvoker – ReacPve •  New in JAX-RS 2.1! •  javax.ws.rs.client.AsyncInvoker 42
  43. 43. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS – Client-side 43 Sync Async RX Performance and scalability ✗✗ ✔ ✔ Easy to develop and maintain ✔ ✗ ✔ … complex workflow ✗ ✗ ✔ … error handling ✗ ✗ ✔ Leverage new Java SE feature ✗ ✗ ✔
  44. 44. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS –ReacPve Client API •  Java SE 8 ComplePon Stage – As mandated by the spec. •  Jersey – RxJava - rx.Observable – RxJava 2 - io.reacPvex.Flowable – Guava - ListenableFuture 44
  45. 45. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | JAX-RS – Server-side •  AsyncResponse – Resume execuPon on a different thread – @Suspended – Resource method returning a ComplePonStage<T> instance •  Long running operaPon pasern •  Server-sent Events 45
  46. 46. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Java EE 8 46 Bean Valida.on CDI 2.0 JSON-B 1.0 Security 1.0 Bean Valida.on 2.0 JSF 2.3 Servlet 4.0 JSON-P 1.1 JAX-RS 2.1 ReacPve client API, Server-sent events, … HTTP/2, server push, … Java <-> JSON binding Updates to JSON standards, JSON Collectors, … Async event, event priority, SE support, … Embrace Java SE 8, new constraints Improved CDI, WebSocket, SE 8 integraPon, … Standardized IdenPty Store, AuthenPcaPon, Security Context
  47. 47. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Java EE 8 •  Work in progress – Final Release - Summer 2017 (plan) •  Open Source Reference ImplementaPons – hsps://github.com/jersey – hsps://github.com/javaee •  Stay tuned… – hsps://blogs.oracle.com/theaquarium/ 47
  48. 48. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | .‫רבה‬ ‫תודה‬ ConfidenPal – Oracle Internal/Restricted/Highly Restricted 48
  49. 49. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Resources •  JAX-RS specificaPon – hsps://github.com/jax-rs/api •  Jersey – Asynchronous Services and Clients – hsps://jersey.java.net/documentaPon/latest/async.html#d0e8611 – hsps://github.com/jersey/jersey/tree/master/examples/rx-client-webapp •  ComplePonStage – hsps://docs.oracle.com/javase/8/docs/api/java/uPl/concurrent/ComplePonStage.html •  Java EE Tutorial – hsps://docs.oracle.com/javaee/7/tutorial/ 49

×