I needed Mule to determine the outbound endpoint based on the content of properties in my custom XML message. Although this might look as common functionality I couldn't find a complete example for this on the net. This one was close, but didn't match completely with my situation:
I receive an XML message that is conform my own custom format. Based on the content of several fields in this XML message I determine what the next endpoint must be to process the message. Then my message is forwarded to that endpoint.
The 'mule-config' for this looks like:

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
  3.       xmlns:jms="http://www.mulesource.org/schema/mule/jms/2.2"
  4.       xmlns:spring="http://www.springframework.org/schema/beans"
  5.       xmlns:stdio="http://www.mulesource.org/schema/mule/stdio/2.2"
  6.       xmlns:test="http://www.mulesource.org/schema/mule/test/2.2"
  7.       xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2"
  8.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  9.       xsi:schemaLocation="
  10.       http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
  11.       http://www.mulesource.org/schema/mule/test/2.2 http://www.mulesource.org/schema/mule/test/2.2/mule-test.xsd
  12.       http://www.mulesource.org/schema/mule/jms/2.2 http://www.mulesource.org/schema/mule/jms/2.2/mule-jms.xsd
  13.       http://www.mulesource.org/schema/mule/stdio/2.2 http://www.mulesource.org/schema/mule/stdio/2.2/mule-stdio.xsd
  14.       http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd
  15.       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  16.  
  17.     <spring:bean id="routingComponent" class="nl.redstream.components.RoutingComponent" />
  18.    
  19.     <custom-transformer name="JaxbXmlToCdmObject" class="nl.redstream.transformers.XmlToObjectJaxbTransformer">
  20.         <spring:property name="jaxbContextPackage" value="nl.redstream.message.v01_0"/>
  21.     </custom-transformer>
  22.     <custom-transformer name="JaxbObjectToCdmXml" class="nl.redstream.transformers.ObjectToXmlJaxbTransformer">
  23.         <spring:property name="jaxbContextPackage" value="nl.redstream.message.v01_0"/>
  24.     </custom-transformer>
  25.  
  26.     <jms:activemq-connector name="JMSConnector" specification="1.1" dynamicNotification="true"
  27.                 brokerURL="failover:(vm://localhost?broker.persistent=true&amp;broker.useJmx=false)"
  28.                 acknowledgementMode="AUTO_ACKNOWLEDGE"
  29.                 maxRedelivery="3"
  30.                 disableTemporaryReplyToDestinations="true"
  31.                 persistentDelivery="true"
  32.                 username="user"
  33.                 password="password" />
  34.        
  35.     <vm:endpoint name="test_vm" path="test-path" synchronous="true" />
  36.     <jms:endpoint name="test_queue" queue="test-queue" connector-ref="JMSConnector" synchronous="false" />
  37.  
  38.     <model name="mule-event-processing" inherit="false">
  39.         <service name="start-event-processor">
  40.             <inbound>
  41.                 <vm:inbound-endpoint address="vm://event-processor" synchronous="false" transformer-refs="JaxbXmlToCdmObject" />
  42.             </inbound>
  43.  
  44.             <component>
  45.                 <spring-object bean="routingComponent" />
  46.             </component>
  47.  
  48.             <outbound>
  49.                 <custom-outbound-router class="nl.redstream.router.DynamicRouter" transformer-refs="JaxbObjectToCdmXml">
  50.                     <spring:property name="evaluator" value="custom" />
  51.                     <spring:property name="customEvaluator" value="cdm-msg-property" />
  52.                     <spring:property name="expression" value="ADDRESS_LIST" />
  53.                 </custom-outbound-router>
  54.             </outbound>
  55.         </service>
  56.  
  57.         <service name="TEST">
  58.             <inbound>
  59.                 <vm:inbound-endpoint ref="test_vm" />
  60.             </inbound>
  61.             <echo-component/>
  62.             <outbound>
  63.                 <pass-through-router>
  64.                     <jms:outbound-endpoint ref="test_queue" />
  65.                 </pass-through-router>
  66.             </outbound>
  67.         </service>
  68.     </model>
  69. </mule>

This is what happens with this configuration: the message is received on the inbound endpoint of the 'start-event-processor' service. The endpoint forwards the mesage to the component 'RoutingComponent'. In this component the next inbound endpoint is determined and added as a property to the XML message. The code for the component looks like:

JAVA:
  1. package nl.redstream.components;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import nl.redstream.message.v01_0.Message;
  6. import nl.redstream.message.v01_0.PropertySetType;
  7. import nl.redstream.message.v01_0.PropertyType;
  8. import org.apache.log4j.Logger;
  9. import org.mule.api.transformer.TransformerException;
  10.  
  11. /**
  12. * Routes a Message to the correct Business Process by using message metadata
  13. *
  14. * @author pascal
  15. */
  16. public class RoutingComponent
  17. {
  18.     protected static Logger logger = Logger.getLogger(RoutingComponent.class);
  19.  
  20.     public Message routeMessage(Message cdmMessage) throws TransformerException {
  21.         logger.debug("routeMessage(Message cdmMessage)");
  22.  
  23.         // Determin next inbound endpoint
  24.         String nextEndpoint = getBusinessProcess(cdmMessage.getMessageHeader().
  25.                 getPropertySet());
  26.  
  27.         // Set next endpoint
  28.         setAddressList(nextEndpoint, cdmMessage);
  29.  
  30.         // Return message
  31.         return cdmMessage;
  32.     }
  33.  
  34.     private void setAddressList(String nextEndpoint, Message msg) {
  35.         List<String> addressList = new ArrayList<String>();
  36.         addressList.add(nextEndpoint);
  37.         PropertyType prop = new PropertyType();
  38.         prop.setKey("ADDRESS_LIST");
  39.         prop.setValue(nextEndpoint);
  40.         msg.getMessageHeader().getPropertySet().getProperties().add(prop);
  41.     }
  42.  
  43.     private String getBusinessProcess(PropertySetType propertySet) {
  44.         // Access some logic to determine next matching BusinessProcess
  45.         return "test_vm";
  46.     }
  47. }

In the component the method 'routeMessage' is called. In this method I determine what the next step is that has to be performed (in this example "test_vm" is hardcoded as next endpoint but this can easily be made more dynamically). Then the name of that endpoint is added as a property to the message header.
Then the message is passed to my custom-outbound-router. It is a subclass of the 'expression-recipient-list-router' and I made the method 'isMatch' always returning true so no filter has to be used. The code for the router is very simple:

JAVA:
  1. package nl.redstream.router;
  2.  
  3. import org.mule.api.MuleMessage;
  4. import org.mule.api.routing.RoutingException;
  5. import org.mule.routing.outbound.ExpressionRecipientList;
  6.  
  7. /**
  8. *
  9. * @author pascal
  10. */
  11. public class DynamicRouter extends ExpressionRecipientList {
  12.  
  13.     @Override
  14.     public boolean isMatch(MuleMessage message) throws RoutingException {
  15.         return true;
  16.     }
  17. }

The actual inbound endpoint to which the message is transfered next is determined by making use of my custom evaluator (The creation and use of the custom evaluator is described here. It also explains more about the used xml schema for my message). With this configuration in place it will use the property 'ADDRESS_LIST' in the MessageHeader to obtain the endpoint. Since the dynamic-router in this example always return 'test_vm' the message will be forwarded to that endpoint and be picked up by the 'TEST' service. Here is a test class to test this example:

JAVA:
  1. package nl.redstream.components;
  2.  
  3. import nl.redstream.utils.FileUtils;
  4. import org.mule.api.MuleMessage;
  5. import org.mule.module.client.MuleClient;
  6. import org.mule.tck.FunctionalTestCase;
  7.  
  8. /**
  9. * Checks the dynamic routing
  10. *
  11. * @author pascal
  12. */
  13. public class RoutingComponentTest extends FunctionalTestCase {
  14.  
  15.     protected final String getConfigResources() {
  16.         return "config/test-dynamic-router-config.xml";
  17.     }
  18.    
  19.     /**
  20.      * Tests the correct handling of an exception.
  21.      *
  22.      * @throws Exception
  23.      */
  24.     public void testReceivingEvent() throws Exception {
  25.         MuleMessage msg = null;
  26.         MuleClient client = new MuleClient();
  27.  
  28.         client.dispatch("vm://event-processor",
  29.                 FileUtils.getFileAsString("xml/example-msg.xml"), null);
  30.  
  31.         Thread.sleep(1500);
  32.  
  33.         msg = client.request("test_queue", 500);
  34.        
  35.         assertNotNull(msg);
  36.     }
  37. }

This class sends an example message to the event-processor. The message will be enriched with a property 'ADDRESS_LIST' in the header that has the value 'vm_test'. So I expect a message on the queue 'test_queue'. If it is not there the test fails, otherwise the router is working correctly.