API-led connectivity and CQRS: Aligning business & IT with RAML

Part 2: Building a Data Query Application

In a previous blog, we talked through how you might design a solution to deliver a Command Query Responsibility Segregation (CQRS) pattern with Anypoint Platform. In this blog, we’ll discuss how an API-led connectivity approach can help you deliver this pattern (and the mobile application your business is demanding) with speed and scale while maintaining control over your critical data assets.

 

API-led connectivity and API design

api-led-connectivity-design

To deliver this mobile application successfully, you need to bring together two groups of people:

  • Your client’s Supplier Relationship Management (SRM) domain experts
  • Your developers implementing the mobile application and underlying connectivity

You discovered RAML, the RESTful API Modeling Language, to start design discussions between your client’s SRM experts and your mobile and backend developers. RAML is a language of the web and therefore can be understood and interpreted by technical and non-technical people alike. This means it’s practical for supporting cross-team communication. By iterating on the RAML specification, the team can jointly discover how to deliver great business value and accurate resource naming like “item” or “part”, “material” or “product”, etc.  Imagine the following design was agreed as sufficient for the first prototype implementation.

The power of RAML for driving Consensus

Let’s now discuss how you might have gotten the non-technical domain experts on board.

raml-design

The picture above shows the RAML design for the API you want to build.

 After some conversations with your clients, you identified the “construction-machine” API needed to be provide search for parts (/parts/search).  You also discovered that parts should be accessible via a resource id (/parts/{part_id}), and that every part has a price (/parts/{part_id}/price). Additionally, in the first iteration suppliers should also be searchable (/suppliers/search).

 With this contract in place (agreed upon by both parties), you can now begin thinking about implementation.  And while you work on implementing the API, front-end developers can begin coding against a mocked version leveraging sample data you provide with the mocking service available in API Designer.

Data Query Application Implementation

data-query-application-integration
The first step in building the Data Query Mule application is to load the mutually agreed RAML specification into Anypoint Studio, which then creates a stub implementation of your API. This application by itself is now runnable and can be deployed on any Mule runtime, either in the cloud or on-premises.

The second step in building the application is to add a Mule XML configuration file to host your Neo4j graph database functionality. It includes Cypher query generation and reaches out to your Neo4j installation to run the query via the Neo4j REST API. 

This kind of separation gives you freedom to grow your application’s functionality in future versions of your project should you decide to move away from Neo4j.

The complete functioning solution can be reviewed here.

https://github.com/Brazo/data-query

Solution In Action

Now let’s see this implementation in action with an example. Suppose a user is querying your API from a mobile device in order to retrieve all parts that belong to your client’s Excavator Chassis (e.g. with part id = 13). The user is requesting the following resource: http://localhost:8081/api/parts/search?belongs-to=13.

  1. APIKit router validates all incoming requests from the mobile device and outgoing message formats according to your RAML specification
    apikit-router
  2. Depending on the request resource (e.g. /parts/search?belongs-to=13) the corresponding Mule flow is invoked
    <flow name=”get:/parts/search:construction-config”>
    construction-mule-flow
  3. The /parts/search flow extracts and validates the supplied query parameters
    <add-message-property key=”belongsto”
    value=”#[message.?inboundProperties[‘http.query.params’][‘belongs-to’] or -1]” />
  4. Query parameters were stored into a flow variable and used in the Choice router for correct handling
    <when expression=”#[?belongsto >= -1]”>
    <flow-ref name=”neo4j-adapter-search-parts-belongs-to”
    doc:name=”neo4j-adapter-search-parts-belongs-to” />
    </when>
  5. The given belongs-to query parameter invokes a specific flow on the Neo4j adapter implementation that generates a corresponding Cypher query
    <flow-ref name=”neo4j-adapter-search-parts-belongs-to”
    doc:name=”neo4j-adapter-search-parts-belongs-to” />
    cypher-query
  6. The Neo4j API for single transaction Cypher queries (db/data/transaction/commit) is invoked using the standard Mule HTTP connector
    <flow name=”neo4j-adapter-search-parts-belongs-to”>
    <set-payload value=”{ “statements” : [ { “statement” : “match
    (n:Part)-[:belongsTo]->(p:Part) where p.itemId=#[belongsto] return n” }
    ]}” doc:name=”Set Payload”/>
    <flow-ref name=”neo4j-adapter-call-out” doc:name=”neo4j-adapter-call-out”/>
    </flow>
    neo4j-callout
  7. Neo4j answers with a JSON response containing the query result
  8. DataMapper is used to transform the Neo4j JSON result message to your XML Schema format
    <data-mapper:transform config-ref=”JSON_To_Xml_search_result_” doc:name=”JSON To Xml search-result” />
  9. The API XML response is returned to the Caller, in this case a mobile device
    api-xml

Extending the application with business logic.

With the data query solution working smoothly, you can now move on to address the requirement of real-time currency conversion.  The goal: every item’s price can be retrieved with the current exchange rate. For that, you wrote a Currency Converter using Google Finance and Anypoint DevKit.

Once built, you can drop the custom connector into the API resource /parts/{part_id}/price flow. First, look it up in your Connectors list:

Then add it to your API implementation flow…

… and finally configure the currency conversion to be dynamic.

Now you have a functioning resource for all parts prices. Whatever Euro amount Neo4j returns is dynamically converted into the requested currency code.  Another requirement solved!

The Impact of API-led Connectivity

If we take a step back and think through the solution we just created, a few key advantages come to mind:

  • API-led Connectivity ensures alignment across business and IT at critical design-time
  • Exposable and manageable experience API hides backend complexity
  • Solution was delivered without custom code, increasing speed of delivery
  • Solution can be deployed on-premises or in the cloud, with one Mule runtime
  • Each application component acts as subdomain in Mule, nicely separated and extendable without affecting the other parts of the solution
  • The business can switch from Neo4j to another storage solution without affecting the API, it would only require you to reference the new storage adapter
  • You can refactor the Data Query Application into two single applications by using an asynchronous protocol (JMS, AMQP) to decouple them instead of a flow reference
    • That could prove very useful if the API implementation needs to scale up massively
  • Cypher is powerful but developers or API user might not want to learn it
    • You wrapped Cypher language into the Neo4j adapter
    • The API implementation part (and thus developers) don’t know about Cypher
    • The Neo4j adapter can grow separately and in-house developers can work on it using Cypher without affecting the API implementation
  • The real-time currency converter is now a reusable component built quickly with functionality available to every developer in Anypoint Studio

Ready to start your own innovation project? Get started with Anypoint Platform.  The next post will discuss how to build a write API.

 

 


We'd love to hear your opinion on this post