The folloing example configures a OrderManager bean that receives Orders via different endpoints, processes them, then sends the result to a processed.queue. The example assumes you have read the [Mule Events in Spring] introduction.
We want our OrderManager to receive orders over -
- Jms on an orders.queue
- Email on orders@myrestaurant.com
- Soap, acting as a web service
To enable a spring bean to receive Mule Events it needs to implement a MuleEventListener or MuleSubscriptionEventListener. Lets start with the code for our OrderManager and then describe what its doing.
The OrderManager service exposes a single method for processing orders.
public interface OrderManager
{
public String processOrder(Order order);
}
Our OrderManagerBean implements both OrderManager and MuleSubscriptionEventListener.
public class OrderManagerBean implements MuleSubscriptionEventListener, OrderManager
{
private String[] subscriptions;
public void onApplicationEvent(ApplicationEvent orderEvent)
{
Order order = (Order) orderEvent.getSource();
String result = processOrder(order);
MuleApplicationEvent muleEvent = (MuleApplicationEvent) orderEvent;
MuleApplicationEvent returnEvent = new MuleApplicationEvent(
result, "jms:);
muleEvent.getApplicationContext().publishEvent(returnEvent);
}
public String processOrder(Order order)
{
return "Order '" + order.getOrder() + "' Processed";
}
public String[] getSubscriptions()
{
return subscriptions;
}
public void setSubscriptions(String[] subscriptions)
{
this.subscriptions = subscriptions;
}
}
Notice the get and set scubscription methods, these are part of the MuleSubscriptionEventListener interface and they determine what events the OrderManager will receive.
<bean id="orderManager" class="org.mule.extras.spring.events.OrderManagerBean">
<property name="subscriptions">
<list>
<value>
jms://orders.queue
</value>
<value>
pop3://orders:secret@mail.myrestaurant.com?transformers=EmailMessageToString,StringToOrder
</value>
<value>
glue:http://localhost:44444/mule/OrderManager
</value>
</list>
</property>
</bean>
This bean will now receive email messages sent to orders@myrestaurant.com and jms messages sent to order.queue. The third soap subscription may not be so obvious. When used as a subscription the mule soap provider will automatically expose the OrderManager as a web service! Soap clients can invoke the OrderManagerBean as a web service over http.
 | MuleClient as a soap client
To test the OrderManager webservice you can use the [MULEUSER:Mule Client] for example -
MuleClient client = new MuleClient();
Order order = new Order("Sausage and Mash");
String endpoint = "glue:http:;
UMOMessage result = client.send(endpoint, order, null);
|
Configuring Mule and Spring
To hook Mule into the Spring event mechanism you need to declare the MuleEventMulticaster bean in the application Context. This will now be used to send and receive events in Spring.
<bean id="applicationEventMulticaster" class="org.mule.extras.spring.events.MuleEventMulticaster"/>
<property name="asynchronous"><value>false</value></property>
</bean>
 | Bean definition name
The bean definition name for MuleEventMulticaster has to be applicationEventMulticaster. |
 | Mule manager instance not required
This configuration does not need a Mule manager instance configured separately. If the bean definition name for MuleEventMulticaster is set correctly a Mule manager instance will be started and configured for you. |
 | Running Asynchronously
The MuleEventMulticaster can run asynchronously. In this case Mule will create a threadpool for each listener. This can really help performance if there is a high volume of events coming through or if event processing takes a long time. You can also configure a threadingProfile to control how thread pooling behaves, but I will leave this out of this article. |
See the Xml configuration for the Spring events example test case for an example of how to configure your Mule instance.
Handling Transformations
So far we have configured the OrderManagerBean to receive events over jms, pop3 and soap, but we haven't determined how we get an Order object from each of these transports; this is done with Mule transformers. Lets look at each transport individlually.
Jms
By default, Mule will handle transformations to and from Jms Message automatically using [standard Jms transformers], these can be overridden, but for many cases the defaults are fine.
Pop3
There has to be some custom transformation to turn the message body into an Order object. You can see on the pop3 endpoint that there is a transfromers parameter. This references a comma-separated list of transformers to apply to the email message when it is received. The transformer names refer to the name of transformer beans in the application context. So we need to add two new beans, one of reach transfromer -
<bean id="EmailMessageToString" class="org.mule.providers.email.transformers.EmailMessageToString"/>
<bean id="StringToOrder" class="org.mule.extras.spring.events.StringToOrder">
<property name="returnClass"><value>org.mule.extras.spring.events.Order</value></property>
</bean>
Soap
All type conversion is handled by the underlying soap server. Mule configures the servers to use automatic type mapping where possible. For more information see the Mule [MULEUSER:Soap Provider].
Receiving Events
When the OrderManagerbean receives events over jms or pop3 the onApplicationEvent will get invoked with an Order source object; Mule transforms the events before your beans receive them. If the the OrderManagerBean is invoked as a web service the processOrder method will get called directly as this is the method exposed by the OrderManager interface.
Publishing Events
You can see from the code for the OrderManagerBean that MuleApplicationEvents are published via the application context. This means that at any point you beans can publish Mule events over any Mule transport using a [Mule Endpoint]. This provides a very convenient way for your objects to tal over http, tcp, jms, soap, etc.
In the example we get the Spring application context from the event, while this is convenient, it is not mandatory. Your bean could implement ApplicationContextAware and send mule events that way without having to receive an event first.