blob: 56b53cb934012cf7f6a6f358d5f62989592ea908 [file] [log] [blame]
[//]: # " Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved. "
[//]: # " "
[//]: # " This program and the accompanying materials are made available under the "
[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at "
[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. "
[//]: # " "
[//]: # " SPDX-License-Identifier: BSD-3-Clause "
Reactive Clients Jersey Reactive Client Extensions Example
==========================================================
This example demonstrates how data from multiple resources and in
various formats (json, xml) can be combined into a form suitable to ones
requirements. The example show and compares usage of standard JAX-RS
sync client, JAX-RS async client, Jersey's Observable (RxJava) client
extension, Jersey's CompletionStage (Java 8) client extension and
Jersey's ListenableFuture (Guava) client extension.
The application consists of two parts:
- **"Remote"**, that can be considered to be deployed on a
remote machine. In fact each resource from
`org.glassfish.jersey.examples.rx.remote` package can be deployed on
a separate remote machine as every resource represents a service of
it's own.
- **Note:** `DestinationResource` returns response entities as `JSON`
while `CalculationResource` and `ForecastResource` as `XML`.
- **"Agent"**, which is a synchronization/orchestration layer. This
layer, also deployed as a server application, fetches data from all
needed resources (using JAX-RS Client API) and combine
them together. The combined result is then sent to the client that
invoked the original request on the orchestration layer.
Every "agent" resource (package `org.glassfish.jersey.examples.rx.agent`)
invokes the following requests to the "remote" resource:
- Obtain **visited** destinations for a user. (User identification is
propagated via request header and basically everything about a user
maximally simplified since it's out of scope of this example)
- Obtain **recommended** destinations for a user. Requests obtaining
**visited** and **recommended** destinations are independent and can
be run in parallel.
- Obtain weather **forecasts** for recommended destinations. New
client request is invoked for every recommended destination.
Obtaining weather **forecasts** depend on actual
**recommended** destinations.
- Obtain trip **calculations** (prices) for recommended destinations.
New client request is invoked for every recommended destination.
Obtaining trip **calculations** depend on actual
**recommended** destinations. **forecast** and **calculation**
requests are independent on each other and can be invoked
in parallel.
Contents
--------
> Please note that the example is not fully implemented right now.
>
> Available "agent" resources are _/rx/agent/sync_, _/rx/agent/async_ and _/rx/agent/completion_.
The mapping of the URI path space is presented in the following table:
URI path | Resource class | HTTP methods | Allowed values
-------------------------------------------------- | ------------------------------- | -------------- | ------------------------------------------------------------------------------
**_/rx/agent/sync_** | SyncAgentResource | GET | returns JSON
**_/rx/agent/async_** | AsyncAgentResource | GET | returns JSON
**_/rx/agent/observable_** **(temporarily n/a)** | ObservableAgentResource | GET | returns JSON
**_/rx/agent/completion_** | CompletionStageAgentResource | GET | returns JSON
**_/rx/agent/listenable_** **(temporarily n/a)** | ListenableFutureAgentResource | GET | returns JSON
**_/rx/remote/destination/visited_** | DestinationResource | GET | returns JSON
**_/rx/remote/destination/recommended_** | DestinationResource | GET | returns JSON
**_/rx/remote/forecast/{destination}_** | ForecastResource | GET | destination - name of a country; returns XML (random value)
**_/rx/remote/calculation/from/{from}/to/{to}_** | CalculationResource | GET | from - name of a country, to - name of a country; returns XML (random value)
Application is Servlet 3 based, web.xml-less. Everything needed (resources/providers) is registered in `RxApplication`.
Sample Response
---------------
Agent responses look similar to the following one:
```javascript
{
"visited" : [ {
"destination" : "Antigua & Barbuda"
}, {
"destination" : "Guinea"
}, {
"destination" : "Malta"
}, {
"destination" : "Denmark"
}, {
"destination" : "Tajikistan"
} ],
"recommended" : [ {
"destination" : "Bolivia",
"forecast" : "Showers",
"price" : 1359
}, {
"destination" : "Yemen",
"forecast" : "Haze",
"price" : 8032
}, {
"destination" : "Dominican Republic",
"forecast" : "Cloudy",
"price" : 1141
}, {
"destination" : "Korea South",
"forecast" : "Mostly Sunny",
"price" : 9853
}, {
"destination" : "Saudi Arabia",
"forecast" : "Fog",
"price" : 9063
} ],
"processingTime" : 877
}
```
As can be seen the response entity contains 3 main elements: **visited**
(list of visited destinations), **recommended** (list of recommended
destinations + weather forecast and price calculation) and
**processingTime** (describing how long it took to obtain previous two
elements).
Running the Example
-------------------
Run the example as follows:
> mvn clean package jetty:run
This deploys current example using Jetty. You can access the application at:
- <http://localhost:8080/rx/agent/sync>
- <http://localhost:8080/rx/agent/async>
- <http://localhost:8080/rx/agent/listenable> **(temporarily n/a)**
- <http://localhost:8080/rx/agent/observable> **(temporarily n/a)**
- <http://localhost:8080/rx/agent/completion>
Resources
---------
This examples is using the following (3-rd party) libraries:
**RxJava** by Netflix
- [GitHub](https://github.com/ReactiveX/RxJava)
- [GitHub.Wiki](https://github.com/ReactiveX/RxJava/wiki)
- [JavaDoc](http://reactivex.io/RxJava/javadoc/)
**Guava** by Google
- [Homepage](https://code.google.com/p/guava-libraries/)
- [ListenableFuture
Explained](https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained)
- [JavaDoc](http://docs.guava-libraries.googlecode.com/git/javadoc/index.html?overview-summary.html)