Clean exposure of Spring beans using Servlet transport and Json module in Mule

motif

For one of my personal projects I need to expose some Spring services for a web application, but I don’t want to pollute my model and service classes with annotations, so here’s how I might use Mule ESB for this task.

First I configure my pom file with Mule’s dependencies like this:

I’m going to use the servlet transport and the json module. The servlet transport will handle the HTTP request and redirect those calls to my services, and the json module will perform the conversions between objects and json (called transformations in Mule’s idiom). So far, I create/update my Eclipse project files with:

The first step is to load Mule and Spring application contexts when your web application loads. If you have already loaded your spring application context then you can skip this step. For Spring I have added a context loader listener in the web.xml file:

And for Mule I have added its context listener which automatically composes with the existing Spring’s application context:

Also we need to expose the servlet who is going to handle the requests (e.g. under /services/ uri path) in the web.xml file:

Then you can write a minimum empty mule-config.xml file like this:

Notice that we imported Spring and servlet schemas in the previous lines.

So far so good — you can start your web application to check if everything is working fine and check that you don’t get any errors in the console. I’m using Jetty right now, so:

Before we start writing the Mule configuration, I will briefly show my Spring configuration which contains only one transactional service and a repository:

My project Service is quite simple. It only has one method called addProject which creates a Project with startDate today and returns it:

We would like to expose that method under the services URI. Let’s start with our Mule configuration; we create a model for our Project service, configuring its path (relative to the one we configure in web.xml) and the Spring bean, which is going to receive the invocations (projectService bean). Because of how the ReflectionEntryPointResolver works, it needs an array of objects to invoke the method, but we will receive an HTTP request and also we need to sort the method’s arguments (which are unsorted in the request). So, I create a general transformer which converts and sorts the map values according to its configuration.

The MapToArrayTransformer transformer receives a Map and according to its keyOrder property it creates an Array of arguments so that method invocation can successfully be done.

Also, notice that we have already configured the response transformer that will transform the response of the method invocation to a Json object. The Object to Json transformer takes an Object (in this case a Project class specified in its sourceClass property) and returns the Json string.

You can now start your application using Jetty and try the following URL:

http://localhost:8090/projectmanagement/services/project?method=addProject&name=Mule ESB

In a future post, I will explain how to make this solution a little more general.


We'd love to hear your opinion on this post