Saturday, May 31, 2014

End to End Example - A Mule 3.5.0 App with Domains

Recently, I've added to my gradle plugin for building mule apps the ability to build domain-based (A.K.A. mule shared resources) projects. While the plugin gains maturity and is getting ready for prime time, I've started eating my own dog food with it and as a result I've produced a sample application that uses some features of Mule 3.5.0 Community Edition. Please checkout the instructions on how to run the sample project.

The Use Case

Let's imagine that we have in our premises a database of cooking recipes, but we have the requirement of exposing a REST API so users can check available recipes and post new ones.

This is a simple use case but we have some additional requirements as well as some constraints:

  1. The Backend APP needs to have the less down time possible.
  2. We need to be able to change the API since it will evolve and gain new features.
  3. We need to be able to scale the backend so when thousands of users access it at the same time it does not become extremely unresponsive.
  4. Upon an upgrade in the backend it would be desirable that users can still post recipes. 

Implementation

For the implementation of these requirements, I've decided to divide and conquer, this is create two modules:
  1. API Module: This is responsible for receiving requests through HTTP, and adapt them in a way the backend can understand and process them. Also is responsible for representing appropriately the information provided by the back-end.
  2. Backend Module: This module is responsible for accepting requests, processing them and returning the results.
The following is a diagram of the implemented architecture:
The communication between the modules is leveraged through JMS, initially as the app has only a couple of users, we don't want to have a separate JMS Broker, so we'll leverage an embedded broker, but this is easily upgradable to an external broker without making any changes to the Modules.

Backend Implementation

For implementing the backend (source code) I've leveraged the brand new Database Module. This module allows to easily run parameterized queries. The backend module's main interface are JMS queues, and for the operations that require a response, we'll take advantage of mule's automatic reply when ReplyTo-type headers are present.

API Implementation

For implementing the front end (source code), I've used APIKit, this module allows us to easily expose a REST-like API out of a RAML file, so before starting the implementation I went to the Anypoint Platform website and created a RAML File with the API Editor.

In order to implement the requirement of accepting recipes even if the backend is missing I used a Asynchronous approach, this is the create operation returns a Task ID, and it's up to the client to check if the task has been completed, normally it is desirable that the APP itself notifies the clients when their tasks have been completed, nevertheless due to the nature of the HTTP transport, this is not possible.

There are some tasks that require a synchronous response, these are: check the list of recipes and check the status of a given task. These calls have been implemented with JMS queues as well, but leveraged mule's request-reply router for synchronizing these calls, so if a redeployment of the backend happens in a reasonable time-frame, requests from the client will last a little longer but not fail.

Conclusions

The use of Mule ESB 3.5.0 allowed me to implement this use case in a matter of a couple of hours. In particular this version with the ability of sharing the JMS connector I can easily do Inter-APP communication (which is easier in Mule Enterprise by sharing a VM connector) and still have the ability to scale, add more servers, cluster etc.