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 2.1 Reloaded @ Devoxx

12,961 views

Published on

JAX-RS 2.1 presentation at Devoxx US 2017.

Published in: Software
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

JAX-RS 2.1 Reloaded @ Devoxx

  1. 1. #DevoxxUS JAX-RS 2.1 Reloaded Santiago Pericas-Geertsen JAX-RS Co-Spec Lead #jax-rs @spericas
  2. 2. #DevoxxUS Agenda •  Reactive Extensions •  Server-Sent Events •  Non-Blocking IO #jax-rs @spericas
  3. 3. #DevoxxUS Reactive Extensions #jax-rs @spericas
  4. 4. #DevoxxUS Asynchronous Processing in 2.0 Server side: •  Using @Suspended and AsyncResponse •  Resume execution on a different thread Client side: •  Future<T> •  InvocationCallback<T> 4
  5. 5. #DevoxxUS Example Using Future<T> 5 What’s the problem here? Client client = ClientBuilder.newClient(); WebTarget target = client.target(“http://…”); Future<String> f = target.request().async().get(String.class); // some time later … String user = f.get();
  6. 6. #DevoxxUS Example using InvocationCallback<T> 6 WebTarget target = client.target(“http://…”); target.request().async().get( new InvocationCallback<String>() { @Override public void completed(String user) { // do something } @Override public void failed(Throwable t) { // do something } });
  7. 7. #DevoxxUS Example using InvocationCallback<T> 7 target1.request().async().get(new InvocationCallback<String>() { public void completed(String user) { target2.request().header(“user”, user).async().get( new InvocationCallback<String>() { public void completed(String quote) { System.out.println(quote); } public void failed(Throwable t) { // do something } }); } public void failed(Throwable t) { // do something }}));
  8. 8. #DevoxxUS Some use cases for Async Computations •  Compose two or more asynchronous tasks •  Combine the output of two or more asynchronous tasks •  Consume value of asynchronous task •  Wait for all tasks in a collection to complete •  Wait for any of the tasks in a collection to complete And many more …
  9. 9. #DevoxxUS Meet CompletionStage<T> in JAX-RS 9 CompletionStage<String> cs1 = target1.request().rx().get(String.class); CompletionStage<String> cs2 = cs1.thenCompose(user -> target2.request().header(“user”, user) .rx().get(String.class)); cs2.thenAccept(quote -> System.out.println(quote));
  10. 10. #DevoxxUS What about other Rx libraries? 10 Client client = client.register(ObservableRxInvokerProvider.class);
 
 Observable<String> of = 
 client.target("forecast/{destination}”) .resolveTemplate("destination", "mars”) .request() .rx(ObservableRxInvoker.class) .get(String.class); of.subscribe(System.out::println); Register a Provider Override default Invoker
  11. 11. #DevoxxUS Server-Sent Events Summary •  New invoker to support Rx •  Default support for CompletionStage •  Extension mechanism for other Rx libraries 11
  12. 12. #DevoxxUS Server-Sent Events #jax-rs @spericas
  13. 13. #DevoxxUS Server-Sent Events •  Originally W3C (HTML5), now maintainted by WHATWG •  HTTP-based protocol for one-way server to client messaging •  Special media type text/event-stream 13
  14. 14. #DevoxxUS Client API 14 try (SseEventSource source = SseEventSource.target(“http://…”).build()) { source.subscribe(System.out::println); source.open();
 Thread.sleep(500); 
 } catch (InterruptedException e) {
 // falls through
 } Publisher
  15. 15. #DevoxxUS Server API 15 @GET
 @Produces(“text/event-stream”)
 public void eventStream( @Context SseEventSink eventSink,
 @Context Sse sse) { executor.execute(() -> { try (SseEventSink sink = eventSink) {
 eventSink.onNext(sse.newEvent("event1")); eventSink.onNext(sse.newEvent("event2")); eventSink.close(); } catch (IOException e) {
 // handle exception
 } });} Subscriber
  16. 16. #DevoxxUS Broadcasting (1 of 2) 16 @Path("/")
 @Singleton public class SseResource { private final Sse sse; private final SseBroadcaster sseBroadcaster; public SseResource(@Context Sse sse) { this.sse = sse; this.sseBroadcaster = sse.newBroadcaster(); }
 … One Publisher Lifecycle controlled by App
  17. 17. #DevoxxUS Broadcasting (2 of 2) 17 @GET @Path(“subscribe”) @Produces(MediaType.SERVER_SENT_EVENTS) public void subscribe(@Context SseEventSink eventSink) { eventSink.onNext(sse.newEvent("welcome!")); sseBroadcaster.subscribe(eventSink); }
 @POST @Path(“broadcast”) @Consumes(MediaType.MULTIPART_FORM_DATA) public void broadcast(@FormParam("event") String event) {
 sseBroadcaster.broadcast(sse.newEvent(event)); } … } Many Subscribers
  18. 18. #DevoxxUS Reactive Extensions Summary •  New types SseEventSink, SseEventSource, Sse and SseBroadcaster •  Sse and SseEventSink’s lifecycle controlled by runtime •  Singleton scope useful for broadcasting 18
  19. 19. #DevoxxUS Non-Blocking IO #jax-rs @spericas
  20. 20. #DevoxxUS Motivation •  Certain apps need more control over IO •  Higher throughput is hard with blocking IO •  Precedence with StreamingOutput 20
  21. 21. #DevoxxUS StreamingOutput in JAX-RS 21 @GET public Response get() { return Response.ok(new StreamingOutput() { @Override public void write(OutputStream out) throws … { out.write(…); } }).build(); } Direct access to stream Still blocking!
  22. 22. #DevoxxUS First NIO Proposal 22 return Response.ok().entity(
 out -> {
 try {
 final int n = in.read(buffer);
 if (n >= 0) {
 out.write(buffer, 0, n);
 return true; // more to write
 }
 in.close();
 return false; // we're done
 } catch (IOException e) { … }
 }).build(); Write handler
  23. 23. #DevoxxUS First Proposal Limitations •  Byte streams are not sufficient in JAX-RS •  We want POJOs! •  What about JAX-RS readers, writers and interceptors? •  Poor integration with other third-party libraries and APIs 23
  24. 24. #DevoxxUS Current Proposal: Flows •  Standardized in Java 9 •  Originaly appeared in Reactive Streams •  Not just bytes, POJOs too •  Possibility of integration with third-party libraries and APIs 24
  25. 25. #DevoxxUS Simple Concepts 25 Publisher Subscriber Processor Publisher Subscriber 0 N Processor
  26. 26. #DevoxxUS Why and when to NIO? •  Non-blocking code tends to be more involved •  Beneficial for large payloads •  Large payloads often involve collections •  In Flow terms, a collection of Pojos is a Publisher<Pojo> 26
  27. 27. #DevoxxUS Processing a collection 27 @POST @Consumes(“application/json”) void process(Publisher<Pojo> pojos, @Suspended AsyncResponse response) { pojos.subscribe(new Subscriber<Pojo> { public onNext(Pojo pojo) { // process single pojo } public onComplete() { return response.ok().build(); } … } } Asynchronous by nature
  28. 28. #DevoxxUS MessageBodyReader for Pojo? •  MessageBodyReader for Pojo or Publisher<Pojo>? •  We need a new type of Reader: NioBodyReader •  Knows how to process a collection of Pojos •  May use MessageBodyReader for each Pojo •  (Ditto for MessageBodyWriters …) 28
  29. 29. #DevoxxUS Pojo Processor in REST 29 @POST @Consumes(“application/json”) @Produces(“application/json”) Publisher<Pojo> process(Publisher<Pojo> pojos, @Suspended AsyncResponse response) { Processor<Pojo> pp = new MyProcessor(response); pojos.subscribe(pp); return pp; } Processors are publishers!
  30. 30. #DevoxxUS Third-party Libraries 30 @GET @Produces(“application/json”) Publisher<Pojo> process( @QueryParam(“predicate”) String predicate) { return DB.get(Pojo.class).filter(predicate); } Third-party Library
  31. 31. #DevoxxUS What about Filters and Interceptors? •  Need special support for NIO •  For example, additional methods and contexts •  Discussion still ongoing •  May impact how NioBodyReader/NioBodyWriter are defined 31
  32. 32. #DevoxxUS And NIO Clients? •  Will be supported as well •  Need re-usability of readers and writers for NIO •  Likely using a new client Invoker 32
  33. 33. #DevoxxUS NIO Client 33 WebTarget resource = target(“…”).path(“pojos”); Publisher<Pojo> pojos = resource.request().nio().get(Pojo.class); pojos.subscribe(new Subscriber<Pojo> { public onNext(Pojo pojo) { // process single pojo } … }); NioBodyReader
  34. 34. #DevoxxUS Tentative Vocabulary •  Publisher = Source •  Subscriber = Sink •  Does this ring a bell? 34
  35. 35. #DevoxxUS SSE is a special case of Flow! •  Where what flows are SSE protocol messages •  Initial SSE proposal may be impacted •  Return a Source instead of injecting a Sink 35
  36. 36. #DevoxxUS Non-Blocking IO Summary •  Based on Flows •  New readers/writers for collections •  Support for Flows without depending on Java 9 •  Support for Pojos, not just byte streams •  Publisher<Pojo> and Publisher<ByteArray> 36
  37. 37. #DevoxxUS Public Release In Progress •  Support for NIO and Flows •  Some minor changes to SSE possible •  Stay tuned! 37

×