Mule is typically used on the receiving end of service requests. Mule flows, for instance, are generally initiated by external events like a JMS message being sent to a queue, a POSTed HTTP request, or the firing of a Quartz trigger. Since Mule is usually deployed as a server this behavior should be expected. What isn’t so obvious, however, is using Mule as a client of these services. We’ll see in this blog post how MuleClient can be embedded in a non-Mule application to send and consume messages as a client.
Configuring MuleClient with Spring
For the purposes of this blog post I’ll assume we have a fairly simple Spring MVC application that deals with product data. We’ll start off by modifying a Spring MVC controller to use MuleClient to asynchronously dispatch a Product object to a JMS queue. We’ll then see how we can modify that call to elicit a response from a temporary queue, taking advantage of Mule’s support for synchronous JMS. Finally we’ll see how we can do a “local” integration and call it from the Spring MVC application using MuleClient.
Before we can do any of this, however, we need to wire-up a MuleClient instance in our Spring MVC application. We’ll start by creating a mule-config.xml file in the Spring application’s ./src/main/resources/META-INF directory. We’ll create a directory called “mule” and place the following mule-config.xml in it.
This configuration configures the JMS connector we’ll reference from the Spring controller. Now let’s wire MuleClient up in Spring. For this case I’ll add the following lines to my applicationContext.xml file.
We’re now able to inject the MuleClient singleton to the controller class, ProductController, like this:
Sending JMS messages
MuleClient is ready to go at this point. Let’s modify the save() method to dispatch a JMS message containing the product data.
We’re calling MuleClient’s dispatch() method to asynchronously place the Product object on a JMS queue called “products”.
Its hopefully obvious how straightforward this is. Implementing the same behavior with the native JMS libraries, or even Spring’s JmsTemplate, would take significantly more work. This is further demonstrated if we modify the code to wait for a response on a temporary queue. Assuming the “remote” side of this queue is a Mule JMS inbound-endpoint with a request-reply exchange-pattern then we just need to do the following.
Changing “dispatch” to “send” causes MuleClient to wait for a response. In this case it will wait for the Product to be returned on a temporary queue, presumably modified in some way (i.e., its ID field populated with a database identifier.) If a response isn’t received in 2 seconds or a null response is returned then we throw an exception. Otherwise the modified Product is returned to the web-browser or API consumer.
Auditing Product Data
Let’s assume that we need to perform auditing of the products data sent to the JMS queue, perhaps posting it to a remote API. This could be somewhat convoluted to do in code, particularly in a controller, but is trivial to implement with a Mule flow, as illustrated below.
Assuming the above flow is added to the mule-config.xml configured at the beginning of this post, we just need to modify the MuleClient code in ProductController to dispatch to the VM queue rather then JMS as follows.
You may have already been aware of MuleClient, particularly in the context of writing functional tests (where it is indispensable.) This post illustrates that MuleClient has a role in the client side of your applications as well. We saw how to use MuleClient to dispatch and synchronously consume messages off JMS queues. We also saw how MuleClient facilitates adhoc integrations while embedded in a non-Mule application. These techniques will hopefully let you use Mule to simplify not just your server side integrations, but your client side ones as well.