Weitere ähnliche Inhalte
Ähnlich wie JAX RS and CDI bike the reactive bridge (20)
Mehr von José Paumard (20)
Kürzlich hochgeladen (20)
JAX RS and CDI bike the reactive bridge
- 2. 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
- 3. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | 3
@delabassee
- 4. 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
- 6. 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
- 7. 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
- 9. 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
- 10. 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
- 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. 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);
- 13. 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();
- 14. 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) {
// …
}
- 15. 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();
- 16. 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
- 17. 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
- 18. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
The Travel Service
18
- 19. 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
- 20. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
The Travel Service
Asynchronous
20
730 ms
- 21. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
The Travel Service
21
- 22. 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();
}
- 23. 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 }
});
// ...
- 24. 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();
- 25. 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
- 26. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
CompletionStage Pipeline
26
CS1 CS21
CS22
CS31 CS41
CS32
- 27. 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));
- 28. 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();
- 29. 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);
- 30. 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());
}
- 31. 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;
}
- 32. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
Exception Handling
32
CS1 CS21
CS22
CS31 CS41
CS32
- 33. 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));
- 34. 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));
- 35. 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));
- 36. 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);
- 37. 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
}
}
- 38. 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
- 39. 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
- 41. 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
- 42. 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
}
- 43. 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);
}
- 44. 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);
}
- 45. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
Wrap-up
45
- 46. 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