Data Caching
Scooter provides a few server-side data caching stores.
- Data caching within the same request thread
- Data caching across requests: second-level cache
- Cache properties
- Cache provider plugins
- Convenient cache classes
- CurrentThreadCache class: caching made easy
- NamedCurrentThreadCache class: caching made easy
- DefaultCacheStore class: second-level caching made easy
Data caching within the same request thread
By default, data accessing using ActiveRecord will have data cached in the same request thread. This option is set by the useRequestCache property in environment.properties file.
useRequestCache=true
Therefore if your code calls Post.findById(100) multiple times, only the first time this method retrieves data from the underlying database, the rest of times it just returns data from the cache.
The useRequestCache property is set for all ActiveRecord model classes. If for some reason you don't want to cache data for a specific method, you just tun it off by listing it in localUseCacheExceptions property. For example:
localUseCacheExceptions=com.blog.model.Post.findAll, com.blog.model.Post.findFirst
The above setting simply says do not cache the result of findAll and findFirst in Post model.
Data caching across requests: second-level cache
Second-level cache allows applications to cache data across requests.
By default, second-level cache is not turned on. To turn it on, just set these in environment.properties file. For example:
useSecondLevelCache=true default.cache.provider.name=blog_development plugin.cache.provider.blog_development=\ plugin_class=plugin.ehcache.EhCacheCacheProvider,\ configFile=ehcache.xml
This tells Scooter to use EhCache plugin for second-level cache and use ehcache.xml as its configuration file.
The file ehcache.xml is the ehcache configuration file. It can be put under blog/WEB-INF/config directory, or you can modify the one under scooter/plugins/ehcache/src. You can even specify an absolute path for the file in the configFile property. The plugin will find it out.
Cache properties
Properties for Cache setting:
Property | Description | Default | Example |
---|---|---|---|
useRequestCache | Cache data in request thread | true | |
useSecondLevelCache | Cache data in second-level cache | false | |
allowCacheAssociatedObjects | Cache data of assoicated objects | false | |
flushCacheOnChange | Flush cache when change (update/create/delete) happens | true | |
localUseCacheExceptions | Comma deliminated full method names to turn off cache setting for the listed methods | Empty | This will not cache result of findAll and findFirst methods: localUseCacheExceptions = com.blog.model.Post.findAll, com.blog.model.Post.findFirst |
localFlushCacheExceptions | Comma deliminated full method names to turn off flush setting for the listed methods | Empty | This will keep result of findAll and findFirst forever which is good for read-only application: localFlushCacheExceptions = com.blog.model.Post.findAll, com.blog.model.Post.findFirst |
Cache provider plugins
Config a plugin
Configuration of cache providers follows the style of configuring database connections. Scooter automatically provides default configuration for DEVELOPMENT, TEST and PRODUCTION environments at project creation time. You can then modify them in environment.properties file. If you do not need them, just keep them commented or removed from the property file.
Here are the standard parameters you can configure for a cache-provider plugin:
Property | Description | Required? |
---|---|---|
plugin_class | Plug-in class name | Y |
namespace | Namespace of a memcached store | N |
urls | memcached server urls. Multiple urls can be listed here separated by space | Y |
expiresInSeconds | specifies how long should the object stay in cache | N |
requestTimeoutInSeconds | specifies how long should a request waits for response from cache server | N |
You can also add your own parameters as follows:
plugin.cache.provider.jpetstore=\ plugin_class=com.example.MyCacheProvider,\ namespace=jpetstore,\ urls=localhost:11211,\ myproperty1=value1,\ myproperty2=value2
Here are generated definitions of cache-provider plugins:
plugin.cache.provider.blog_development=\ plugin_class=plugin.ehcache.EhCacheCacheProvider,\ configFile=ehcache.xml,\ useSerialization=true plugin.cache.provider.blog_test=\ plugin_class=plugin.spymemcached.SpyMemcachedCacheProvider,\ namespace=blog,\ urls=localhost:11211,\ expiresInSeconds=3600,\ requestTimeoutInSeconds=60 plugin.cache.provider.blog_production=\ plugin_class=plugin.spymemcached.SpyMemcachedCacheProvider,\ namespace=blog,\ urls=localhost:11211 localhost:11212,\ expiresInSeconds=3600,\ requestTimeoutInSeconds=60
You can create and use your own cache-provider plugin too by following the way the included memcached plugin, e.g. plugin.ehcache.EhCacheCacheProvider, is implemented.
Scooter provides a pluggable second-level caching mechanism. It includes the following plugins for second-level cache:
EhCache Plugin
Scooter supports EhCache with a EhCache plugin.
plugin.cache.provider.blog_development=\ plugin_class=plugin.ehcache.EhCacheCacheProvider,\ configFile=ehcache.xml, \ useSerialization=true, \ useDefaultCacheNameIfAbsent=true, \ defaultCacheName=MyAppName
Besides the properties mentioned above for all plugins, Scooter also provides the following properties for EhCache:
Property | Description | Default | Example |
---|---|---|---|
useSerialization | Data stored are serialized. If you want to prevent multiple users to update the same instance, set this property to true. |
false | |
useDefaultCacheNameIfAbsent | If true, a default cache name is used. In this way, you do not need to define all caches for all models. |
false | |
defaultCacheName | Default cache name | Application Name |
Memcached Plugins
Scooter supports Danga's memcached.
Currently two memcached clients are included as cache-provider plugins: spymemcached and xmemcached. You can find them in the plugins directory.
Note: In order to test memcached-backed Mem Cache, you need to start a memcached server--just like starting up MySQL or Oracle database server when testing database applications. North Scale labs provides a build of memcached for Windows.
Convenient cache classes
A few classes allow you to cache data within the same request thread.
1. CurrentThreadCache class
CurrentThreadCache class allows caching data for the same request thread. It provides convenient static methods for caching:
public static Object get(String key); public static void set(String key, Object value); public static void clear(String key); public static void clear();
By using CurrentThreadCache class, you can pass data obtained in controller class to model class without declaring the data type in the model class' API.
CurrentThreadCache is created when server receives a request and destroyed when the server sends a response. If you'd like to store data that can be used in more than one request, you should use CacheStore.
2. NamedCurrentThreadCache class
NamedCurrentThreadCache class allows caching data for the same request. It takes a name for the cache. In this way, you can save data to a cache with a specific name. For example:
Cache modelCache = new NamedCurrentThreadCache(ModelClass.getName());;
3. DefaultCacheStore class: second-level caching made easy
You can choose one cache provider as a default cache provider and use DefaultCacheStore class' static methods to access it.
For example, add the following line in environment.properties file, where blog_development is a cache provider named plugin.cache.provider.blog_development defined in the example above.
default.cache.provider.name=blog_development
Then you can use convenient static methods provided by DefaultCacheStore class:
public static Object get(Object key); public static boolean put(Object key, Object obj); public static boolean remove(Object key); public static void clear();