I've found an
interesting problem on Stack Overflow. I've answered the question but want to elaborate it a little bit.
The problem
You got two web services.
Service A and
Service B. The services are independent from each others. You need to create a REST web service that calls the latter services, aggregates the results and returns them to the client.
Some terminology
What we want to achieve here is an example of simple
orchestration i.e. coordination of calling of multiple services on the
ESB. Orchestration of the services (not necessarily web ones) has been repeatedly raped by many commercial tools and solutions. One of the most prominent example of orchestration's torturer is
BPEL.
When we use ESB as a proxy between services we refer to it as
Pure ESB. Pure ESB doesn't contain heavyweight processing logic - it only serves as a mediation router.
ServiceMix and
Camel are excellent tools for creating lightweight orchestration based on the pure ESB concept.
Aggregation of two or more services can be referred as
Aggregating Service,
Facade Service or
Proxy Service.
Aggregating web services in Camel
We want to call
Service A and
Service B in parallel (since they are independent), then aggregate the incoming results into a single answer.
The following Camel route is responsible for collecting results from the sub-services (
A and
B) and aggregating them into single message.
from("direct:serviceAggregator")
.multicast(new GroupedExchangeAggregationStrategy()).parallelProcessing()
.enrich("http://servicea.com").enrich("http://serviceb.com")
.end();
We use
multicast pattern to concurrently call two web services. Then multicast uses message
enricher pattern to add data from the external services to the original message. When Camel finally finishes aggregation of the results of A and B services' calls, it attaches the latter results to the original message passed to the
direct:serviceFacade endpoint. The messages fetched from the A and B services will be stored as exchange property identified by
Exchange.GROUPED_EXCHANGE key.
To expose our facade service F on the ESB we will use Camel's Jetty component.
from("jetty:http://0.0.0.0:8080/myapp/myComplexService").enrich("direct:serviceFacade").setBody(property(Exchange.GROUPED_EXCHANGE));
We use enricher again - this time each message passed to the Jetty HTTP connector will be enriched by our aggregating route (
direct:serviceAggregator). In practice that means that all request to the HTTP connector exposed as our service will be injected with two additional messages from
A and
B services. In this particular example we extract data from the received messages and render them as HTTP response to the client.