DSL for server-side composition of content from different microservices using RxJava
A DSL for reactive composition of content from different microservices using RxJava.
Work in Progress
Release: 1.0.0.M1
de.otto.rx-composer:composer-core:1.0.0.M1
de.otto.rx-composer:composer-thymeleaf:1.0.0.M1
Snapshot: 1.0.0.M2-SNAPSHOT
de.otto.rx-composer:composer-core:1.0.0.M2-SNAPSHOT
de.otto.rx-composer:composer-thymeleaf:1.0.0.M2-SNAPSHOT
Microservice architectures for web applications are currently at the top of the hype cycle. One of the most
interesting (and complicated) questions is how to integrate microservices in the frontend. The following options
are already well understood:
The latter solution requires a frontend microservice to gather content from multiple backend microservices.
The more fine-grained you are cutting your microservices, the more important it gets to use asynchronous
communication and retrieve content in parallel, whenever possible. Especially in Java, implementing this in
a tradition way is a non-trivial task.
In addition to this, you would have to deal with unavailable backend services, slow service, and so on: you have
to implement resiliency against failures into your frontend service(s). This is also a non-trivial task…
Rx-Composer is meant to solve such kind of problems. It provides you with an easy to read DSL to describe, what
content to fetch from which microservices. It is handling failures when retrieving content, and it retrieves
content in a reactive way, using RxJava in the implementation.
The general pattern for a rx-composer server is to describe the contents to be fetched, then execute the page and
process the resulting contents.
In the first example, we want to fetch two HTTP resources for fragements “X” and “Y”:
// Setup some ServiceClient:
final ServiceClient serviceClient = HttpServiceClient.singleRetryClient();
// Specify what to fetch:
final Page page = consistsOf(
fragment(
X,
withSingle(
contentFrom(serviceClient, "http://example.com/someContent", "text/html")
)
),
fragment(
Y,
withSingle(
contentFrom(serviceClient, "http://example.com/someOtherContent", "text/html")
)
)
);
// Fetch contents of the page:
final Contents result = page.fetchWith(emptyParameters());
// now we can process the results:
System.out.println("X: " + result.getBody(X);
System.out.println("Y: " + result.getBody(Y);
Both contents will be requested in parallel. The time to fetch both contents will only be a little slower than the
slowest response - instead of the sum of both response times.
Because we are using the singleRetryClient
, we already have some build-in resiliency:
Using a ServiceClient like noRetries()
or singleRetry
, it is possible to configure a fallback, if retrieving
content from the primary ContentProvider fails because of timeouts, exceptions or HTTP server errors.
final Page page = consistsOf(
fragment(X,
withSingle(
contentFrom(serviceClient, "http://example.com/someContent", TEXT_PLAIN,
fallbackTo(staticTextContent(position, "<p>Some Fallback Content</p>"))
)
)
)
);
The fallbackTo
methods accepts all kinds of ContentProviders. The following example is falling back to a different
service, using a differently configured ServiceClient:
...
contentFrom(serviceClient, "http://example.com/someContent", TEXT_PLAIN,
fallbackTo(contentFrom(fallbackClient, "http://example.com/someFallbackContent", TEXT_PLAIN))
)
...
…about how to use rx-composer
can be found in the user guide.
TODO
TODO
TODO
TODO
TODO
The docs
folder contains some documentation about the project:
Change Log: Information about the lasted changes, release notes, and so on can be found in the
change log.
Getting Started: The Getting Started guide contains information about how to include
rx-composer into your project, about build it, and so on.
Examples: A working example is also contained in this project. It consists of two Spring Boot server modules and
is described here.
User Guide: If you are looking for some deeper insights, the User Guide might be the
right place to look.
Contributing: You would like to contribute? Great! Please have a look here for
information about how to do it.