Fabiano Taioli
Fabiano Taioli

Reputation: 5540

ehcache session scoped in grails

I want to user in a grails service a ehcache session scoped.

I managed to have a cache bean from this definition in config/resources.groovy

myCache(org.springframework.cache.ehcache.EhCacheFactoryBean) {
      timeToIdle = 5000 // life span in seconds
      timeToLive = 5000 // life span in seconds
      }

But the object obtained from the factory is singleton scoped.

What is the best way to have a session scoped ehcache in a session scoped service?

Thank you

Upvotes: 1

Views: 1023

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75671

You can't do it with Ehcache since the cache manager maintains the caches by name and there can only be one cache per name. You would need to use another cache implementation that either doesn't enforce unique names or doesn't use the name as the "key" in the cache manager.

EDIT: This approach works, but doesn't use the factory bean:

import java.util.concurrent.atomic.AtomicInteger

import net.sf.ehcache.Cache
import net.sf.ehcache.CacheManager
import net.sf.ehcache.store.MemoryStoreEvictionPolicy

import org.springframework.beans.factory.DisposableBean
import org.springframework.beans.factory.InitializingBean

class MyService implements InitializingBean, DisposableBean {

   private static AtomicInteger counter = new AtomicInteger()

   private Cache cache
   private String cacheName

   static scope = 'session'

   void afterPropertiesSet() {

      int maxElementsInMemory = 10000
      int maxElementsOnDisk = 10000000
      MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = MemoryStoreEvictionPolicy.LRU
      boolean overflowToDisk = true
      boolean eternal = false
      int timeToLive = 5000 // 120
      int timeToIdle = 5000 // 120
      boolean diskPersistent = false
      int diskExpiryThreadIntervalSeconds = 120
      int diskSpoolBufferSize = 0

      cacheName = 'myservice-cache-' + counter.incrementAndGet()

      cache = new Cache(cacheName, maxElementsInMemory, memoryStoreEvictionPolicy,
                  overflowToDisk, null, eternal, timeToLive, timeToIdle,
                  diskPersistent, diskExpiryThreadIntervalSeconds, null,
                  null, maxElementsOnDisk, diskSpoolBufferSize)

      CacheManager.getInstance().addCache cache
   }

   void destroy() {
      cache.removeAll()
      CacheManager.getInstance().removeCache(cacheName)
   }
}

Since the service is session-scoped the cache doesn't have to be since it's controlled entirely by the service. By implementing InitializingBean you can create the cache when the session starts, and remove it when the session ends by implementing DisposableBean. Feel free to use a different cache name approach; this one just guarantees that they're unique. Also I've enumerated the cache constructor values based on the defaults in EhCacheFactoryBean but those could be inlined.

Upvotes: 2

Related Questions