In this 4 part blog series, I describe in detail how one might go about modernizing a functional, but legacy Supplier Relationship Management (SRM) application without redeveloping (or even touching) it. Why? The release cycle for the legacy app is too long and it doesn’t scale in a way that will meet the needs of newly required mobile application.
Additionally, an aspect of SOLID software design is the Open/Closed Principle which in our case can be applied as we are extending and providing functionality without actually modifying the core application. The architectural pattern we apply is Command Query Responsibility Segregation (CQRS) as we expect a high amount of queries to our data and the result formats (views) should be highly tailored to multiple channels and independent from the SRM application.
- Part 1 of the series explains goals, vision and application requirements in more detail
- Part 2 walks through building a Mule application responsible for answering queries in a seamless and highly performant way. We also used Neo4j’s graph database.
- Part 3 (this post) will show how to wrap the legacy database with an API that will then be used with our CQRS application handling commands.
- Part 4 (next post) will finalize the use case showing how to keep a MySQL DB and Neo4j in sync.
Part 3 agenda
Here are the final steps required to complete the front end implementation:
- Wrap the SRM application’s DB with a RAML based REST API
- Publish the Query and Write applications API into Anypoint Exchange to empower ease of use and reuse
- Design an API using RAML that merges and exposes Query and Command capabilities
- Implement this API where Queries are handled synchronously and Commands are performed asynchronously
- Publish the CQRS API on API Portal and Anypoint Exchange
RESTful wrapping the Database
Just as you might wrap a gift before giving it to someone, let’s wrap our database with a clean API. RAML (the RESTful API Markup Language) provides a clean, easy-to-understand way to define these APIs . RAML also lets you describe exactly what you want to build and iterate on it. Due to its resource oriented and YAML-based nature, it is readable by everyone who can use a browser. If you come along with a coffee, even the functional expert might give it a review. To keep things simple and prove the point, you will just implement a price update of a specific part and adding a new supplier. Review the RAML gist for more details.
Once you designed the specification using RAML you can start implementing it in Anypoint Studio. Anypoint Studio is MuleSoft’s Eclipse based IDE for implementing Enterprise Application Integration (EAI) solutions, batch oriented applications and API-led Connectivity projects.
Here is a screenshot of the PUT implementation to update your parts prices:
- The request’s XML is converted into a Java Object Map for property access
- The incoming parts price might be of any currency, e.g. Pounds, Swiss Francs, … which we convert into a Euro and USD price, as demanded by the legacy DB (you use a Message Enricher pattern)
- The converted price and the new part information are updated in the legacy DB
Publishing the Command and Query APIs
Anypoint Exchange is the central place for all your integration templates, examples, How To’s and even APIs. Exchange is browser based and also integrated with and explorable within Studio. So as soon as you publish the Command and Query APIs into Exchange it is available to any developer interested in it. Note that the developer doesn’t need to know where (URL) the API is hosted or which data types is supports, as all of this is auto-configured.
Anypoint API Portal allows developers to request access to your published APIs and provides documentation. Once API access is requested you grant (manually or automatically) access for the developer and s/he will be provisioned with her client key and client secret.
Design your Business Case – CQRS API
To combine aspects of the Query and Command API and implement them to fulfill your requirements feeding a mobile prototype UI at hand you need to:
- List part instance resources
- Update prices of parts
- List suppliers
- Create a new supplier
The RAML gist specifying the requirements above can be found on GitHub.
A logical implementation overview looks like this:
Implementing the CQRS API
The implementation of your CQRS API is easily supported as you just configure the HTTP endpoints to the backend systems with the information that was added into Anypoint Exchange, all from Anypoint Studio.
Asynchronous Command Requests
Make the request to the Parts Command API asynchronous by transacting the incoming request onto a queue. As the persistence to the queue can be transacted a reliability pattern is implemented, so the initial client request will fail when the queue can’t consume the message.
Once you start extending functionality with public and/or cloud-based APIs, you can use Anypoint MQ as a fully fledged broker in the cloud to implement asynchronous behaviour. This provides future-proof flexibility as you scale your application either in the cloud and on-premises.
Synchronous Query Requests
Querying data from your underlying Neo4j database is already fast and is simply proxied. In certain cases data could be enriched or optimized for specific channels.
Finally the CQRS API treats Commands and Queries differently, depending on the requirements. There is no limitation to include Event Sourcing mechanisms here.
The CQRS API source code is available on GitHub.
Publish the CQRS API
As with the Query and Command API, add the tailored CQRS API you just built to Anypoint Exchange to make it available for discovery and reuse by other developers so they can build new capabilities on top of it.
With the front end implementation of your mobile experience API now finalized, your mobile developers can finalize their implementation. The next and final post of this series will cover the more traditional Enterprise Application Integration aspects required to deliver this scenario and describe how Mule is used to keep Neo4j and the SRM application’s database in sync.