Tuesday, September 4, 2012

Plugging in Ehcache into iBATIS


As you probably know that Ehcache is the Hibernate’s default 2nd level cache. Integrating Ehcache into iBATIS is relatively easy using iBATIS’s CacheController interface. Using the CacheController interface you can plugin your own custom caching solution or plug in any third party caching solution. The javadoc for CacheController is here. In order to plugin Ehcache, you must implement the CacheController interface as follows.

Implementing the CacheController:

import java.io.File;
import java.net.URL;
import java.util.Properties;

import net.sf.ehcache.Element;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ibatis.sqlmap.engine.cache.CacheModel;
import com.ibatis.sqlmap.engine.cache.CacheController;


public class EhcacheIbatisCacheController implements CacheController {
    final private static Logger logger = LoggerFactory.getLogger(EhcacheIbatisCacheController.class);
    
    /** EhCache CacheManager. */
    private CacheManager cacheManager;

    /**
     * Flush a cache model.
     * @param cacheModel - the model to flush.
     */
    public void flush(CacheModel cacheModel) {
        getCache(cacheModel).removeAll();
    }

    /**
     * Get an object from a cache model.
     * @param cacheModel - the model.
     * @param key        - the key to the object.
     * @return the object if in the cache.
     */
    public Object getObject(CacheModel cacheModel, Object key) {
        Object result = null;
        try {
            Element element = getCache(cacheModel).get(key.toString());
            if (element != null) {
                result = element.getObjectValue();
            }
        }
        catch(Exception e) {
            logger.debug("cache miss, will check in db");
        }
        return result;

    }

    /**
     * Put an object into a cache model.
     * @param cacheModel - the model to add the object to.
     * @param key        - the key to the object.
     * @param object     - the value to add.
     */
    public void putObject(CacheModel cacheModel, Object key, Object object) {
        getCache(cacheModel).put(new Element(key.toString(), object));
    }

    /**
     * Remove an object from a cache model.
     * @param cacheModel - the model to remove the object from.
     * @param key        - the key to the object.
     * @return the removed object.
     */
    public Object removeObject(CacheModel cacheModel, Object key) {
        Object result = this.getObject(cacheModel, key.toString());
        getCache(cacheModel).remove(key.toString());
        return result;
    }

    /**
     * Configure a cache controller. Initialize the Cache Manager of Ehcache
     * @param props - the properties object containing configuration information.
     */
    public void setProperties(Properties props) {

        String configFile = props.getProperty("configFile");
        File file = new File(configFile);
        if(file.exists()) {
            cacheManager = CacheManager.create(file.getAbsolutePath());
        }
        else {
            URL url = getClass().getResource(configFile);
            cacheManager = CacheManager.create(url);
        }
    }

    /**
     * Gets a ehcache based on an iBatis cache Model.
     * @param cacheModel - the cache model.
     * @return the Cache.
     */
    private Cache getCache(CacheModel cacheModel) {
        String cacheName = cacheModel.getId();
        return cacheManager.getCache(cacheName);
    }

}

Each method provides access to the CacheModel that controls the cache so you can access parameters in the CacheModel when required.

Registering EhcacheIbatisController with iBATIS: 


CacheModels and CacheControllers must be registered in the ibatis xml. 1st create an alias for the Ehcache controller as follows:


Now we need to apply the Cache controller to a CacheModel definition in the xml.