tisdag 18 juni 2013

Enterprise caching with Mule ESB Community Edition

I want to share with you a way to do generic enterprise type caching with Mule ESB community edition.

In Mule ESB you have the possibility to use the Cache Scope with various strategies and options to enable caching of the payload for any element in your integration flow. This feature is however only available in the Enterprise or CloudHub version of Mule.

Inspired by an integration blueprint I found in Mule In Action by David Dossot and John D'Emic, I managed to setup a solution that uses the excellent Open Source edition of  EHCache to achieve very similar behaviors as the one found in Mule's Enterprise only features.

Just follow these easy steps and remember Cache is King!

If you are using Maven you need to setup a dependency for EHCache

 <dependency>  
   <groupId>net.sf.ehcache</groupId>  
   <artifactId>ehcache</artifactId>  
   <version>2.7.0</version>  
   <scope>provided</scope>  
 </dependency>  

Otherwise you will need to attach the EHCache .jar depencies in your project.

To use EHCache in our integration flows we need to set it up as a Spring bean configuration in our XML like this. Note that by doing this we expose every config available on EHCache directly to our Mule configuration. We can even setup several different caches with different settings regarding disk persistence , memory eviction policy's time to live etc.

 <spring:beans>  
     <spring:bean id="MyCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
       <spring:property name="cacheName" value="MyCache"/>  
       <spring:property name="diskPersistent" value="false"/>  
       <spring:property name="overflowToDisk" value="false"/>  
       <spring:property name="maxElementsInMemory" value="100000"/>  
       <spring:property name="eternal" value="false"/>  
       <spring:property name="memoryStoreEvictionPolicy" value="LRU"/>  
       <spring:property name="timeToIdle" value="60"/>  
       <spring:property name="timeToLive" value="60"/>  
     </spring:bean>  
 </spring:beans>  


Now in your Mule configuration flow's XML you will need to add the Custom interceptor component and reference it to a cache configuration (Note that you do not have any graphical component in the component palette of Mule Studio for it.

 <custom-interceptor doc:name="PayloadCache"    class="se.redpill.mulecomponents.cache.PayloadCache">  
          <spring:property name="cache" ref="MyCache"/>  
 </custom-interceptor>  

Since this is an interceptor rather than a scope , you should think of it as something that happens before the flow element you put it in front of (Note that you can write this component as an EnvelopeInterceptor as well and then getting "before" and "after" methods with a surrounding behavior instead).

This particular example just uses the payload from the element in the flow before where you put the component as a key in the cache and it uses the result from the element after as cached value.
So if you send in a payload that does not already exist as key in the cache the execution of the flow execution will go on and a new value will be set in the cache before it is returned, otherwise the cached value for the payload key is immediately returned.

Of course you could modify this behavior as you like and for example provide more <spring:property/> elements to your Custom interceptor and handle them properly for example with behaviors to be able to select parts of the payload as key or parts of the returning payload as value using MEL.

The Custom interceptor is implemented simply by making a class implement the org.mule.api.interceptor.Interceptor interface.

 package se.redpill.mulecomponents.cache;  
 import net.sf.ehcache.Ehcache;  
 import net.sf.ehcache.Element;  
 import org.mule.DefaultMuleEvent;  
 import org.mule.DefaultMuleMessage;  
 import org.mule.api.MuleEvent;  
 import org.mule.api.MuleException;  
 import org.mule.api.MuleMessage;  
 import org.mule.api.interceptor.Interceptor;  
 import org.mule.api.processor.MessageProcessor;  
 /**  
  * A mule interceptor acting as a ehCache component.  
  * Based on the Cache interceptor blueprint from Mule In Action by David Dossot and John D'Emic,  
  *   
  */  
 public class PayloadCache implements Interceptor   
 {       
        private MessageProcessor next;  
        private Ehcache cache;  
        public void setListener(MessageProcessor listener)  
        {  
          next = listener;  
        }  
        public void setCache(final Ehcache cache)  
        {  
          this.cache = cache;  
        }  
        public MuleEvent process(MuleEvent event) throws MuleException  
        {  
          final MuleMessage currentMessage = event.getMessage();  
          final Object key = currentMessage.getPayload();  
          final Element cachedElement = cache.get(key);  
          if (cachedElement != null)  
          {  
            return new DefaultMuleEvent(new DefaultMuleMessage(cachedElement.getObjectValue(),  
              currentMessage, event.getMuleContext()), event);  
          }  
          final MuleEvent result = next.process(event);  
          cache.put(new Element(key, result.getMessage().getPayload()));  
          return result;  
        }  
 }  

That's it! You know have a very flexible and professional Open Source caching solution for your Mule ESB CE.



     

6 kommentarer:

  1. I see this error messge if i try your example: org.mule.module.launcher.DeploymentInitException: ClassNotFoundException: net.sf.ehcache.Ehcache

    SvaraRadera
  2. Nice blog . Had more information to leverage the integration tool.

    SvaraRadera
  3. This article is really helpful

    SvaraRadera
  4. the blog is good and Interactive it is about Mulesoft Developer it is useful for students and Mulesoft Developers for more updates on Mulesoft mulesoft Online training

    SvaraRadera