Service Composition
This is an advanced example and not necessarily intended to be a "getting started" example.
This example is meant to resemble a somewhat realistic application from a control flow and serialization perspective while demonstrating how ServiceTalk’s API variations enable users to choose their preferred programming model.
Note this example also contains "backend" services which simulate databases and keep the example self contained. These backend services do show more usage of ServiceTalk APIs but are not the focus of the example.
How to run the example?
This example has two distinct bootstrap locations:
-
GatewayServer is a main class and starts only the gateway server with all the endpoints. This server is started on port
8080
. -
BackendsStarter is a main class that starts the other services, viz.,
Recommendation
,Metadata
,User
andRating
service.
Usecase
Gateway Service
A service that composes multiple downstream service results into an externally consumable result.
Result
The result is a complex object FullRecommendation as follows:
public final class FullRecommendation {
private Metadata entity;
private User recommendedBy;
private Rating overallRating;
// Getters and setters removed for brevity
}
Each component of this data is fetched from different backends as described below.
Recommendation Backend
A backend service that provides recommendation (entities) for a particular user. Each recommended entity contains:
-
Recommended entity ID.
-
User ID who recommended this entity to this user.
This backend provides a two endpoints:
-
Streaming: An push based endpoint which keeps pushing new recommendations when available. To simulate real life scenarios, we push a recommendation periodically.
-
Aggregated: An aggregated endpoint that sends all currently available recommendations as a list of entities.
Since a recommendation returned by this backend is not externally consumable (only contains IDs), this incomplete information is materialized using the following backends:
Metadata Backend
A backend service
that provides details about the entity given an entityId
.
User Backend
A backend service
that provides details about a user given a userId
.
Rating Backend
A backend service
that provides ratings of an entity given an entityId
.
Objective
The objective is to demonstrate what will be the different ways in which these service calls can be composed to provide the final materialized result.
Gateway Endpoints
In this example we provide three different endpoints on the gateway server to also demonstrate how different programming paradigms can co-exist in a single HTTP server.
Asynchronous streaming
This is an endpoint
that streams FullRecommendation
JSON.
This is a simulation of a push based API that streams data back to the user as and when it is available.
It queries the streaming recommendation endpoint of the recommendation backend described above.
This endpoint is implemented as a fully asynchronous HttpService
and can be queried using the following URI:
http://localhost:8080/recommendations/streaming?userId=1
Asynchronous aggregated
This is an endpoint
that creates a single JSON array containing one or more
FullRecommendation
s. Although the result is a single JSON array, the elements of the array are still fetched from the
other services asynchronously.
This endpoint can be queried using the following endpoint:
http://localhost:8080/recommendations/aggregated?userId=1
Error Handling
This example also demonstrates checking the response status, and handling unexpected status codes. Making a request
with with the simulateError
query parameter will trigger a 500 Internal Server Error
response from the appropriate backend
service for the following values:
- recommendation-service
- metadata-service
- user-service
- rating-service
eg.
http://localhost:8080/recommendations/aggregated?userId=1&simulateError=metadata-service
The Gateway services implement a "fallback" for the Rating service only, which can be seen as -1
ratings in the
response.