Routing API requests - department-of-veterans-affairs/abd-vro GitHub Wiki
This page describes how API requests are routed to a microservice and an API response is sent back to the client, leveraging Apache Camel to provide most of the glue code and common Enterprise Integration Pattern (EIP) implementations.
Synchronous API request
Referring to the code version after PR #71 was merged.
To run the code, see Development process and open http://localhost:8110/swagger in a browser to see the API spec, including the "Demo API" provided by the DemoController mentioned below.
- In the
appDocker container, when aControllerclass receives an API request, it converts the requests into a model, feeds that model as a message into a Camel route, and converts the result of the last route endpoint into an API response object for sending back to the client -- seeDemoControllerfor an example. - The
DemoControllerusesCamelEntranceto inject messages into a Camel endpoint for Camel routing. - Camel routes are defined by
RouteBuildersubclasses, likePrimaryRoutesandClaimProcessorRoute. For example,DemoController.assess_health_datacallsCamelEntrance.assess_health_data_demo- to inject an
AssessHealthDatamessage into thedirect:assess_health_data_demoendpoint, - which is defined in
PrimaryRoutesas a route that goes torabbitmq:assess_health_data?routingKey=health_data_assessor(thehealth_data_assessorqueue in RabbitMQ'sassess_health_datadirect exchange -- RabbitMQ/AMQP concepts).
- In a separate
service-rubyDocker container, a Ruby microservice is subscribed to RabbitMQ'shealth_data_assessorqueue (using RabbitSubscriberservice-ruby/src/lib/rabbit_subscriber.rb). As configured inmicroservices.rb, when a message is popped out of that queue,HealthDataAssessorwill process the message and return a result, which is sent as a reply RabbitMQ message.- It is intended that communication with microservices use RabbitMQ, typically via a direct exchange and routing key to the queue. The message should be a JSON string (automatically encoded as
byte[]) -- this will facilitate replacing RabbitMQ with other messaging systems (like AWS SQS) if needed.
- It is intended that communication with microservices use RabbitMQ, typically via a direct exchange and routing key to the queue. The message should be a JSON string (automatically encoded as
- The reply message is received back on the Camel route in the
appDocker container. When the last endpoint on the route is completed, the last message is converted to the return object ofCamelEntrance.assess_health_data_demo, which will be mapped to the API response object inDemoController.
"Asynchronous" API request
When an API request takes more than 30 seconds to complete, consider sending an immediate API response that includes a URL for the client to check on the status and/or to poll for the result. For an example, check out the POST claim API in the CamelApp, where a claim is processed asynchronously in the background and the claim's status is updated to reflect processing completion.
To achieve this, we leverage the recipientList EIP to send the POSTed claim to multiple endpoints. Since all the endpoints are configured to be asynchronous, we do not wait for any of the results and move on to the next endpoint of the Camel route (using the same message that was sent to the recipientList).
Dynamic Routing
When the route of a claim (a.k.a., a Camel message) is determined dynamically (e.g., based on the claim characteristics or the processing logic), we use a dynamicRouter EIP. For example the DynamicClaimRouter class routes a claim to an endpoint depending on claim's contentionType attribute. A more complete example is provided in the CamelApp.