Skip to Main Content U.S. Department of Energy

Comparison of MIF vs Mule API

As we described in our FAQ entry titled “why not just use Mule,” we adopted mule because of its flexibility and speed. We found that many of our developers preferred a Java API over editing an XML configuration file. We decided to offer a Java API, but found that the Mule API was too verbose for our needs, so we implemented our own API, called MIF, on top of Mule. We were able to simplify the code significantly, in part because MIF does not offer the full range of features that Mule offers. For example, we have hidden many complex features which are not needed for our applications such as: generalized routers, interceptors, and transformers.

As a result, the number of lines of code needed to create a MIF pipeline are significantly less than those needed to create the corresponding pipeline in Mule. It may be argued that this is not a fair comparison since the Mule API is not intended to be used directly by end users and that is what the XML configuration files are used for. While this is true, the examples below demonstrate that MIF imposes a simplified pipeline model on top of Mule that is reflected in its API.

Hello world in MIF API:

  /**
   * Demonstrate a basic 2 module pipeline which takes an input String
   * from stdin, passes the string to one component, then the other,
   * then writes to stdout.
   */
  public class HelloMif {
    public static void main(String[] args) {
      MifPipeline pipeline = new MifPipeline();
      pipeline.addMifModule(BasicTestProcessor.class, "stdio://stdin?promptMessage=enter something: ", "vm://queue-1");
      pipeline.addMifModule(BasicTestProcessor.class, "vm://queue-1", "stdio://stdout");
      pipeline.start();
    }
  }

The same hello world example in the Mule2 API:

/**
 * Demonstrate implementing a 2 service pipeline programmatically in mule.
 */
public class HelloMule2 extends AbstractConfigurationBuilder {
 
  public static void main(String[] args) throws Exception {
    MuleContext context = new DefaultMuleContextFactory().createMuleContext(new HelloMule2());
    context.start();
  }
 
  protected void doConfigure(MuleContext muleContext) throws Exception {
    // ------ Set up mule context
 
    new DefaultsConfigurationBuilder().configure(muleContext);
    SedaModel model = new SedaModel();
    model.setMuleContext(muleContext);
    muleContext.getLifecycleManager().applyCompletedPhases(model);
    MuleRegistry registry = muleContext.getRegistry();
 
    // ------ create 1st service (a service is a component + endpoints)
 
    // create component, set it on the service, register it with mule
    SedaService service1 = new SedaService();
    service1.setName("service1");
    PrototypeObjectFactory objectFactory = new PrototypeObjectFactory(MyCallableComponent.class.getName());
    objectFactory.initialise();
    DefaultJavaComponent component1 = new DefaultJavaComponent(objectFactory);
    service1.setModel(model);
    service1.setComponent(component1);
    registry.registerService(service1);
 
    // create inbound router and endpoint for service1
    InboundRouterCollection inRouterCollection = new DefaultInboundRouterCollection();
    EndpointBuilder inEpBuilder1 = new EndpointURIEndpointBuilder(new URIBuilder("stdio://stdin?promptMessage=enter something: "), muleContext);
    registry.registerEndpointBuilder("inEp1", inEpBuilder1);
    InboundEndpoint inEp1 = inEpBuilder1.buildInboundEndpoint();
    inRouterCollection.addEndpoint(inEp1);   
    service1.setInboundRouter(inRouterCollection);
 
    // create outbound router and endpoint for service1
    OutboundRouterCollection outRouterCollection = new DefaultOutboundRouterCollection();
    List<OutboundRouter> outRouterList = new ArrayList<OutboundRouter>();
    OutboundRouter outRouter = new OutboundPassThroughRouter();
    EndpointBuilder outEpBuilder1 = new EndpointURIEndpointBuilder(new URIBuilder("vm://q1"), muleContext);
    registry.registerEndpointBuilder("outEp1", outEpBuilder1);
    OutboundEndpoint outEp1 = outEpBuilder1.buildOutboundEndpoint();
    outRouter.addEndpoint(outEp1);
    outRouterList.add(outRouter);
    outRouterCollection.setRouters(outRouterList);
    service1.setOutboundRouter(outRouterCollection);
 
    // -------- create 2nd service
 
    // create component
    SedaService service2 = new SedaService();
    service2.setName("service2");
    PrototypeObjectFactory objectFactory2 = new PrototypeObjectFactory(MyPojoComponent.class.getName());
    objectFactory.initialise();
    DefaultJavaComponent component2 = new DefaultJavaComponent(objectFactory2);
    service2.setModel(model);
    service2.setComponent(component2);
    registry.registerService(service2);
 
    // create inbound router and ep for service2
    InboundRouterCollection inRouterCollection2 = new DefaultInboundRouterCollection();
    EndpointBuilder inEpBuilder2 = new EndpointURIEndpointBuilder(new URIBuilder("vm://q1"), muleContext);
    registry.registerEndpointBuilder("inEp2", inEpBuilder2);
    InboundEndpoint inEp2 = inEpBuilder2.buildInboundEndpoint();
    inRouterCollection2.addEndpoint(inEp2);   
    service2.setInboundRouter(inRouterCollection2);
 
    // create outbound for service2
    OutboundRouterCollection outRouterCollection2 = new DefaultOutboundRouterCollection();
    List<OutboundRouter> outRouterList2 = new ArrayList<OutboundRouter>();
    OutboundRouter outRouter2 = new OutboundPassThroughRouter();
    EndpointBuilder outEpBuilder2 = new EndpointURIEndpointBuilder(new URIBuilder("stdio://stdout"), muleContext);
    registry.registerEndpointBuilder("outEp2", outEpBuilder2);
    OutboundEndpoint outEp2 = outEpBuilder2.buildOutboundEndpoint();
    outRouter2.addEndpoint(outEp2);
    outRouterList2.add(outRouter2);
    outRouterCollection2.setRouters(outRouterList2);
    service2.setOutboundRouter(outRouterCollection2);   
  }
 
  protected void applyLifecycle(LifecycleManager lifecycleManager) throws Exception {
    // nothing to do
  }
}

MIF pipelines can also be serialized to a form of XML called XML Metadata Interchance (XMI). This is because Mule's pipeline model is implemented using the Eclipse Modeling Framework (EMF), which – among other things – provides a way to automatically convert between EMF model, Java, and XML. This means that any pipeline written in the MIF API will be automatically converted to XML.

The example XML code below is of the same hello world pipeline as referenced above. Here is the MIF version:

<?xml version="1.0" encoding="ASCII"?>
<Pipeline xmi:version="2.0"  xmlns:xmi="http://www.omg.org/XMI" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xmlns="http://mif/core/3.0">
 
  <modules xsi:type="MifModule" name="basicModule1" implementationClass="gov.pnnl.mif.test.processor.BasicTestProcessor">
    <inboundEndpoints uri="stdio://stin?promptMessage=enter something: "/>
    <outboundEndpoints uri="vm://q1"/>
  </modules>
  <modules xsi:type="MifModule" name="basicModule2" implementationClass="gov.pnnl.mif.test.processor.BasicTestProcessor">
    <inboundEndpoints uri="vm://q1"/>
    <outboundEndpoints uri="stdio://stdout"/>
  </modules>
</Pipeline>

And here is the Mule XML pipeline

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:spring="http://www.springframework.org/schema/beans"
       xmlns:stdio="http://www.mulesource.org/schema/mule/stdio/2.2"
       xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2"
       xsi:schemaLocation="
               http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
               http://www.mulesource.org/schema/mule/stdio/2.2 http://www.mulesource.org/schema/mule/stdio/2.2/mule-stdio.xsd
               http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd">
 
    <model name="helloSample">
        <service name="service1">
            <inbound>
            	<stdio:inbound-endpoint system="IN">
            		<property key="promptMessage" value="Type something: "/>
            	</stdio:inbound-endpoint>
            </inbound>
            <component class="gov.pnnl.mif.test.manual.hello.MyCallableComponent"/>
            <outbound>
                <pass-through-router>
                    <vm:outbound-endpoint path="q1"/>
                </pass-through-router>
            </outbound>
        </service>
        <service name="service2">
            <inbound>
            	<vm:inbound-endpoint path="q1"/>
            </inbound>
            <component class="gov.pnnl.mif.test.manual.hello.MyCallableComponent"/>
            <outbound>
                <pass-through-router>
                    <stdio:outbound-endpoint system="OUT"/>
                </pass-through-router>
            </outbound>
        </service>        
    </model>
</mule>
 
comparison_of_mif_and_mule_apis.txt · Last modified: 2010/09/21 13:21 by adamw