3
votes

I need a quick help from you to fix a small problem.

In one of my project (using spring as core container), i am using ehcache to cache data. I am using spring ehcache annotations project (http://code.google.com/p/ehcache-spring-annotations/) for the same.

I want to have flexibility to enable and disable ehcache based on a external property. I read ehcache documentation and found that it reads system property net.sf.ehcache.disabled internally and if it set to true cache will be disabled and they recommend to pass this as -Dnet.sf.ehcache.disabled=true in the command line

I wanted to control it through externalized spring property file.

Then i thought of setting this system property in my spring application context file using MethodInvokingFactoryBean based on a externalized property.

Here is the code

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
            <property name="targetClass" value="java.lang.System"/>
            <property name="targetMethod" value="getProperties"/>
        </bean>
    </property>
    <property name="targetMethod" value="putAll"/>
    <property name="arguments">
        <util:properties>
            <prop key="net.sf.ehcache.disabled">"${ehcache.disabled}"</prop>
        </util:properties>
    </property>
</bean>

Obviously ehcache.disabled is controlled via my externalized property file.

Plumbing works great but i guess order is not coming into place. By the time Application context is setting system property, cache is initialized and when cache was being initialized there was no property net.sf.ehcache.disabled, hence cache is not getting disabled. When i run application in debug mode and try to get System.getProperty("net.sf.ehcache.disabled") after application context is initialized, it is giving me the right value. (I tried both true and false).

One more thing i want to mentioned i am using spring wrapper to initialize my cache.

<ehcache:annotation-driven self-populating-cache-scope="method"/>

<ehcache:config cache-manager="cacheManager">
    <ehcache:evict-expired-elements interval="20"/>
</ehcache:config>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
      p:configLocation="classpath:ehcache.xml"/>

I believe that disabling cache can not be that hard.

What is it that i am missing? Is there any easy way to do it in spring except command line?

3

3 Answers

2
votes

As of Spring 3.1 it is possible to use bean profiles which can read a property from a external property. You could wrap the declared bean inside a beans element:

<beans profile="cache-enabled"> 
  <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:ehcache.xml"/> 
</beans>

And then activate that using an external property as mentioned in this blog post.

2
votes

The easiest way (pre-Spring 3.1) would be to add a bean id to your MethodInvokingFactoryBean declaration, then add a depends-on relationship.

0
votes

You can return NoOpCacheManager object if your external property is not true

    @Value("${cache.enabled}")
    private Boolean cacheEnabled;
    @Bean(destroyMethod="shutdown")
    public net.sf.ehcache.CacheManager ehCacheManager() {

        net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();

        CacheConfiguration cacheConfiguration = new CacheConfiguration();
        cacheConfiguration.setName("mycache");
        cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
        cacheConfiguration.setMaxEntriesLocalHeap(1000);
        cacheConfiguration.setTimeToIdleSeconds(0);
        cacheConfiguration.setTimeToLiveSeconds(3600);
        cacheConfiguration.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.NONE));

        config.addCache(cacheConfiguration);
 cacheMaxEntriesLocalHeap, cacheEvictionPolicy);
        return net.sf.ehcache.CacheManager.newInstance(config);

    }
    @Bean
    @Override
    public CacheManager cacheManager() {
        if(cacheEnabled) {
            log.info("Cache is enabled");
            return new EhCacheCacheManager(ehCacheManager());
        }else{
            log.info("Cache is disabled");
            return new NoOpCacheManager();
        }
    }