Reactive Client Extension WebApp 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

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` | ObservableAgentResource | GET | returns JSON
`/rx/agent/completion` | CompletionStageAgentResource | GET | returns JSON
`/rx/agent/listenable` | 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:

    {
      "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
- http://localhost:8080/rx/agent/observable
- http://localhost:8080/rx/agent/completion

## Resources

This examples is using the following (3-rd party) libraries:

RxJava by Netflix

- GitHub
- GitHub.Wiki
- JavaDoc

Guava by Google

- Homepage
- ListenableFuture Explained
- JavaDoc