views:

877

answers:

3

I have a spring context xml file with this

<context:property-placeholder location="classpath:cacheConfig.properties"/>

<bean id="cacheManager"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="cacheManagerName" value="cacheName"/>
    <property name="shared" value="false"/>
    <property name="configLocation" value="classpath:cacheConfig.xml"/>
</bean>

the goal is to allow the customer to edit the properties file, like this

cache.maxMemoryElements="2000"

and then in the actual cacheConfig.xml file have this

<cache name="someCacheName"
   maxElementsInMemory="${cache.maxMemoryElements}" ... />

so that items we do not want the customer to change are not exposed. Of course the above details are only partially detailed and NOT working. Currently I see this in the log file

Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Error configuring from input stream. Initial cause was null:149: Could not set attribute "maxElementsInMemory".

Thanks in advance...

+2  A: 

This is not how PropertyPlaceholderConfigurer works. It can be used to replace values within context, but not within arbitrary external files. And cacheConfig.xml is an external file - it's just being passed by Spring to EH Cache.

ChssPly76
+2  A: 

If you are using Maven or Ant, both offer the ability to do filtering of tokens in resource files.

For Maven, you could do something like

<cache name="someCacheName"
  maxElementsInMemory="${cache.maxMemoryElements}" ... />

And in a filter file, or in the POM itself, have

 cache.maxMemoryElements = 200

Resource Filtering in Maven: The Definitive Guide

With Ant, you do this with FilterSets and the <copy> task.

matt b
+1, but important thing to keep in mind here is that with both Ant and Maven property replacement occurs during **build time** as opposed to Spring's property placeholder where it happens during runtime.
ChssPly76
Yep, great point
matt b
+2  A: 

Your example uses EhCacheManagerFactoryBean to expose a reference to the CacheManager, with caches defined in the external cacheConfig.xml file. As @ChssPly76 pointed out, Spring's property resolver only works within Spring's own bean definition files.

However, you don't have to define the individual caches in the external file, you can define them right within the Spring bean definition file, using EhCacheFactoryBean:

FactoryBean that creates a named EHCache Cache instance... If the specified named cache is not configured in the cache configuration descriptor, this FactoryBean will construct an instance of a Cache with the provided name and the specified cache properties and add it to the CacheManager for later retrieval.

In other words, if you use EhCacheFactoryBean to refer to a named cache that isn't already defined in cacheConfig.xml, then Spring will create and configure a new cache instance and register it with the CacheManager at runtime. That includes specifying things like maxElementsInMemory, and because this would be specified in the Spring bean definition file, you get full support of the property resolver:

<context:property-placeholder location="classpath:cacheConfig.properties"/>

<bean id="myCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager" ref="cacheManager"/>
    <property name="maxElementsInMemory" value="${cache.maxMemoryElements}"/>
</bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="shared" value="false"/>
    <property name="configLocation" value="classpath:cacheConfig.xml"/>
</bean>
skaffman
Thanks! That gets me over the hump enough that I can get to the point that I'd like.
Dennis S
What if you want to configure something that is not a cache? For example, a property of cacheManagerPeerListenerFactory?
Emil