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.
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
.
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).
Run the example as follows:
mvn clean package jetty:run
This deploys current example using Jetty. You can access the application at:
This examples is using the following (3-rd party) libraries:
RxJava by Netflix
Guava by Google