Imagine you want to build a synchronous HTTP service that fetches the data for its response over a JMS queue. Or from a directory whose path is dependent on the incoming request. If this sounds familiar then congratulations, you’ve been dealing with dynamic requesting before!
Because it is a pretty popular subject on the user’s forum, I though it would be relevant to present in this post a quick review of the different approaches for dynamic requesting in Mule.
So, what is requesting again? And more importantly, how does it relate to other types of endpoint interactions? Here is a quick review of the four main types of interactions that are supported by Mule transports:
- Receiving, where a payload is received when a particular event occurs, be it an incoming request (synchronous or not) or the result of a resource polling. This happens in inbound endpoints.
- Dispatching, where a payload is asynchronously delivered and no response is gathered. This usually happens in asynchronous outbound endpoints.
- Sending, where the delivery is synchronous and a response is returned. This is usually done with synchronous outbound endpoints.
- Requesting, where no payload is delivered but data is retrieved from the accessed resource. This is usually done by components, either existing ones bundled with Mule or custom-built ones.
When interacting with Mule through its API, only dispatching, sending and requesting are available operations. It makes sense when you consider the fact that receiving is event-driven, i.e. triggered by something external to the Mule instance.
Let’s first take a look at the usage of Mule’s API for requesting payloads, then we’ll look at a couple of alternatives.
Notice how we rely on the time-out value of the current event while performing the request. Doing so guarantees that the JMS interaction will not last for longer than the time-out defined on the inbound endpoint.
In this example, we fetch the first message available in the JMS queue. The same would happen if we would request content from a file directory. But it is oftentimes needed to be more accurate and request a particular resource. Depending on the transport you use, this will be achieved differently. For example, with the file transport, you will build a URI that targets a file name instead of a directory.
Let’s take a look at how this can be done with JMS. For this we will refactor our example and, instead of using a dynamic queue name, we will use a selector expression that will be built at runtime based on a property named ‘userId’:
As you can see it, we configure the selector expression as a URI parameter (we would use the same technique to target a particular JMS connector, should we have more than one defined in our Mule instance). Also look closely at the way we access the ‘userId’ message property: it is directly available as a bound variable in the execution context of the Groovy script. Hence the very neat and compact scriptlet.
For some transports, the way to request a precise resource is done by using a filter. This is the case for the FTP transport. As the following configuration snippet shows it, selecting a single file over FTP (defined by three message properties: ftpHost, ftpDirectory and ftpFileName), requires more fiddling with Mule’s API:
We’re done with our programmatic incursion in the territory of Mule dynamic requesting. To conclude, let’s have a look at some specialized artifacts you could use to perform requesting in specific contexts.
If the resource you want to request is exposed over HTTP, you can be interested to leverage the REST service component, whose usage is demonstrated here after:
In this example, we retrieve the URL to request from the payload of the message sent to the Mule service (thanks to usage of an expression). A similar approach is possible for web services, by using the wrapper component specific to the SOAP transport you’re using (CXF or AXIS).
Finally, if you are exposing the requested resource over HTTP and are using the Servlet transport for that matter, then you need to take a look at the MuleRESTReceiverServlet. This well hidden gem of a servlet performs endpoint requests when it receives HTTP GET requests.
To use this feature, simply configure the MuleRESTReceiverServlet in your web.xml and create a global endpoint you would like to request from, for example:
Supposing you have bound the MuleRESTReceiverServlet under the /rest path, HTTP GETting /rest/files will request the first file in the directory designated by the file endpoint. The matching is performed by name: the last part of the HTTP URL is used to locate the endpoint to request from by its name.
We’re done with this short tour of the wonderful world of requesting in Mule. Do you have any favorite technique or alternative approach you would like to share with all of us? Then, feel free to comment on this post.