Spring Service Layer caching

warning: realpath(): open_basedir restriction in effect. File(/tmp) is not within the allowed path(s): (/var/www/aliabdelaziz.org/data:.) in /var/www/aliabdelaziz.org/data/www/aliabdelaziz.org/includes/file.inc on line 287.

sometimes you may want to cache some information to enhance the performance by minimizing repeated hits to the database.

there are two ways you can take any one of them or take them both:

  1. Service Layer caching (Spring).

  2. Ob­ject-Relational Mapping (ORM) caching (Hibernate).

in this post I will take about enabling cache in the service layer using spring and ehcache.

  • Lets configure the ehcache.xml
    by adjusting the defaultCache as shown below, also adding three entries for the three business methods (getSecureLink, getUserDetails, getUserRoles) that I wanna cache its data as there are many calls to this methods, so its better to cache them so minimize database hits.

    ­

    ­

    ­­­

    <e­hcache>     <!-- Sets the path to the directory where cache .data files are created.          If the path is a Java System Property it is replaced by          its value in the running VM.          The following properties are translated:          user.home - User's home directory          user.dir - User's current working directory          java.io.tmpdir - Default temp file path -->     <diskStore path="java.io.tmpdir"/>     <!--Default Cache configuration. These will applied to caches programmatically created

      through the CacheManager.

            The following attributes are required for defaultCache:         maxInMemory       - Sets the maximum number of objects that will be created in memory         eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element                             is never expired.         timeToIdleSeconds - Sets the time to idle for an element before it expires.                             i.e. The maximum amount of time between accesses before an element expires                             Is only used if the element is not eternal.                             Optional attribute. A value of 0 means that an Element can idle for infinity         timeToLiveSeconds - Sets the time to live for an element before it expires.                             i.e. The maximum time between creation time and when an element expires.                             Is only used if the element is not eternal.         overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache                             has reached the maxInMemory limit.         -->     <defaultCache maxElementsInMemory="10000"         eternal="false"         timeToIdleSeconds="120"         timeToLiveSeconds="120"         overflowToDisk="true" />     <!--  TimeToIdleSeconds is used to determine when an object is set expire after a period of time in which it       is not used or idle.           You don't care how long your objects are idle before they expire, you care about the overall time to live.       The timeToLiveSeconds attribute expires an object after the set period of time—no matter how active or       inactive the cache has become. This service's requirements state that the cache           should expire after 24 hours or 86400 seconds every day.           should expire after 7 hours or 25200 seconds every day.     -->     <cache name="getSecureLink" maxElementsInMemory="50" eternal="false"            overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="25200" />     <cache name="getUserDetails" maxElementsInMemory="50" eternal="false"            overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="25200" />     <cache name="getUserRoles" maxElementsInMemory="50" eternal="false"            overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="25200" /> </ehcache>

    ­

  • then we have to an instance of the CacheManager class. by adding the the following Spring beans to the applicationContext.xml .

    ­   ­­­<bean id="appCacheManager" class="net.sf.ehcache.CacheManager">
            <constructor-arg index="0" type="java.net.URL"
                             value="classpath:ehcache.xml" />
       </bean>

    ­   <bean id="methodCachingInterceptor"          class="org.aliabdelaziz.business.caching.interceptor.MethodCachingInterceptor">         <property name="cacheManager" ref="appCacheManager" />     </bean>

  • Now one last step wich is implementing the method MethodCachingInterceptor and registering it as service Interceptors for the services that contains the method we wanna intercept (securityService)
       ­ <!-- SecurityService Service Proxy with inner SecurityService Service Implementation -->  
        <bean id="securityService" class="org.springframework.aop.framework.ProxyFactoryBean">  
            <property name="target">  
                <bean class="org.aliabdelaziz.b­usiness.service.SecurityServiceImpl">
            <!-- sessionFactory being injected by Ali Abdel-Aziz -->
            <property name="sessionFactory"><ref bean="sessionFactory"/></property>
                    <property name="userDao"><ref bean="userDao"/></property>
                    <property name="linkDao"><ref bean="linkDao"/></property>
                    <property name="singleSignOnDao"><ref bean="singleSignOnDao"/></property>
                    <property name="userRoleDao"><ref bean="userRoleDao"/></property>
                    <property name="userSessionDao"><ref bean="userSessionDao"/></property>  
                    <!-- SecurityService service property merge-point -->  
                </bean>  
            </property>
      
            <property name="proxyInterfaces">
                <value>ae.dxbpolice.eps.business.service.SecurityService</value>
            </property>
      
            <property name="interceptorNames">  
                <list>  
                    <value>methodCachingInterceptor</value>  
                    <value>serviceSecurityInterceptor</value>  
                    <value>serviceTransactionInterceptor</value>  
                    <value>hibernateInterceptor</value>  
                </list>
            </property>  
        </bean>
  • and the following is the MethodCachingInterceptor implementation
    ­­­package org.aliabdelaziz.business.caching.interceptor;
    
    import java.io.Serializable;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    import org.apache.log4j.Logger;
    
    public class MethodCachingInterceptor implements MethodInterceptor {
    
        private CacheManager cacheManager;
        
        /** logger for MethodCachingInterceptor */
        static Logger log = Logger.getLogger(MethodCachingInterceptor.class);
        
        private final String CACHE_DATA_KEY = "CACHE_DATA";
        
        /** array of the methods that is allowed to be cached */
        static final String[] CACHED_METHODS = {"getSecureLink",  "getUserDetails", "getUserRoles"};
        
        /**
         * check if the passed targetMethodName is one of the cached methods found
         * in the CACHED_METHODS array or not.
         * 
         * @return true if and only if the passed targetMethodName is one of the cached methods found
         *         in the CACHED_METHODS, false otherwise.
         * @param targetMethodName
         */
        private boolean isCachedMethod(String targetMethodName) {
            for(int i=0; i<CACHED_METHODS.length; i++) {
                if(CACHED_METHODS[i].equalsIgnoreCase(targetMethodName))
                    return true;
            }
            return false;
        }
        
        public Object invoke(final MethodInvocation methodInvocation)
            throws Throwable {
            final String targetMethodName = methodInvocation.getMethod().getName();
            
            if(!this.isCachedMethod(targetMethodName)) {
                return methodInvocation.proceed();
            }
            
            if (log.isInfoEnabled()) {
                log.info("Attempting cacheManager.getCache first run (no args lookup).");
            }
            
            final Cache templateCache = cacheManager.getCache(targetMethodName);
            Cache cache = null; 
            final StringBuffer cacheNameBuffer = new StringBuffer(targetMethodName);
            String cacheName = targetMethodName.toString();
            // the following two lines commented to keep match the exact method with its parameteres values
            //cacheManager.getCache(targetMethodName);    
    //        if (cache == null) 
    
            { // Lets try with args now.
                if (log.isInfoEnabled()) {
                    log.info("No cache found in no args lookup.");
                }
                final Object[] methodArgs = methodInvocation.getArguments();
                if (methodArgs != null) {
                    if (log.isInfoEnabled()) {
                        log.info("Args on method attempting args cache lookup config.");
                    }
                    cacheNameBuffer.append("(");
                    for (int i = 0; i < methodArgs.length; i++) {
                        cacheNameBuffer.append(methodArgs[i].toString());
                        if (i + 1 != methodArgs.length) {
                            cacheNameBuffer.append(",");
                        }
                    }
                    cacheNameBuffer.append(")");
                    if (log.isInfoEnabled()) {
                        log.info("Attempting cacheManager.getCache with args lookup:" + cacheNameBuffer);
                    }
                    //replace "/" with "_" so that it can be inserted into cache
                    cacheName = cacheNameBuffer.toString().replaceAll("/", "_");
                    cache = cacheManager.getCache(cacheName);
                }
            }
            
            if(cache == null) {
                if(cacheName != null) {
                  cache = new Cache(cacheName, templateCache.getMaxElementsInMemory(), 
                                    templateCache.isOverflowToDisk(), templateCache.isEternal(), 
                                    templateCache.getTimeToLiveSeconds(), templateCache.getTimeToIdleSeconds());
                  
                  cacheManager.addCache(cache);
                }
            }
    
            boolean methodInvocationProceed = false;
            boolean methodInvocationCache = false;
        
            Object methodReturn = null;
        
          if (cache != null) {
            if (log.isInfoEnabled()) {
              log.info("Cache Config. Found: " + cache.getName());
            }
            final Element cacheElement = cache.get(CACHE_DATA_KEY);
            if (cacheElement == null) {
              methodInvocationProceed = true;
            } else {
              methodInvocationProceed = false;
              if (log.isInfoEnabled()) {
                log.info("Cache Element Found");
              }
              methodReturn = cacheElement.getValue();
              if (log.isInfoEnabled()) {
                log.info("Using Cached Element for methodReturn.");
              }
            }
            methodInvocationCache = true;
          }
        
          if (cache == null || methodInvocationProceed) {
            methodReturn = methodInvocation.proceed();
            if (methodInvocationCache) {
              final Element newCacheElement = new Element(CACHE_DATA_KEY, (Serializable) methodReturn);
              cache.put(newCacheElement);
              if (log.isInfoEnabled()) {
                log.info("Created new CacheElement entry and stored in cache.");
              }
            }
          }
        
          return methodReturn;
        }
        
        /**
         * @return the cacheManager
         */
        public CacheManager getCacheManager() {
            return cacheManager;
        }
        
        /**
         * @param cacheManager
         *          the cacheManager to set
         */
        public void setCacheManager(CacheManager cacheManager) {
            this.cacheManager = cacheManager;
        }
    
    }
    
    

    References:

      • http://javaboutique.internet.com/tutorials/ehcache/index-3.html
      • http://www.javaworld.com/javaworld/jw-10-2007/jw-10-acegi2.html?page=6

My aim is always to

My aim is always to certainly search for the theory while doing so and in addition functional knowledge sorts some other articles for dinner. Appreciate it for you personally dealing with

Interesting content material. i adore the theory solely. many thanks
regarded this particular website added in throughout and as well rather
definitely preferred just what We exploration. block phishing

A fresh entirely

A fresh entirely manufacturer spanking fresh substantial traits internal making relating to considerably enhanced designed gold and silver that in turn frequently consists of inclinations to help you problems a number of us long term getting final result substantial power physics. trustone

You have an exceptionally

You have an exceptionally amazing written work style. Much obliged for offering.

purchase soundcloud followers

that is to say the

that is to say the http://www.simply-fone.com/feed.php
wholesalers are dead.

Powered by Drupal - Design by artinet