This page explains how to cache arbitrary objects in Magnolia. You can
cache basically every object. This takes caching well beyond
page and
page fragment caching.
Required modules
The functionality for caching arbitrary objects is provided by at least
two modules.
A second module which implements the API. Magnolia provides two
implementations based on established third-party libraries for the
low-level functions.
The main reason to cache objects is to serve data faster and to save
resources (cpu, memory, network load, etc.). For instance, use object
caching when there is heavy request on a Magnolia service which must
provide data from a remote source.
Assure data validity
When delivering cached data you will probably need a mechanism to ensure
cached data is valid and not outdated! How to handle this depends on the
use case.
Restrict the lifetime of cached objects
When putting objects to the cache you can restrict
their lifetime. In this case, instead of checking the validity of cached
objects, you can simply let them expire over time.
Configure the cache
Magnolia allows to configure a cache factory specifically for each
cache. For example you could have a specific configuration for
fooBarCache. When no specific configuration is defined, the default
factory configuration is used.
Configuration differs depending on which version of Ehcache you use.
Ehcache
This is an example of how to configure a cache using Ehcache 2.
Extend the default factory and override the persistence strategy with
none. This persistence strategy allows to cache non-serializable
objects.
The /modules/cache/config/cacheFactory/caches/fooBarCache
node defines the cache name. fooBarCache is the name of the cache
which was also used above when acquiring the Cache
object within Java code.
Ehcache3
This is an example of how to configure a cache using Ehcache 3.
On the Ehcache 3 module page you will find documentation of all configuration options.
Extend the default factory and override the persistence strategy for
disk set to the value false. This persistence strategy allows to
cache non-serializable objects.
The
/modules/cache/config/cacheFactory/delegateFactories/fooBarCache node
defines the cache name. fooBarCache is the name of the cache which
was also used above when acquiring the Cache object
within Java code.
Get the cache
Achieve an instance of info.magnolia.module.cache.Cache.
This is your cache to operate on. Give it a name which must be unique
within the system.
It is up to client components to decide what they use as keys and values.
Put to cache
info.magnolia.module.cache.Cache knows two methods to append objects.
voidput(Object key, Object value);
voidput(Object key, Object value, int timeToLiveInSeconds);Copy
Argument
Notes
key
required
The identifier of the object to cache
value
required
The object to cache
timeToLiveInSeconds
optional
The lifetime of the cached object in seconds.
Tip: The lifetime also can be configured globally, and you can configure
a flush policy to clear the cache when some condition is met, or you may
want to delete cached objects programmatically (see
#remove and
#clear below).
Use #get when you are unsure whether the desired object is already
cached. If the object is not yet cached, you should acquire it by other
means and add it to the cache.
It is good practice to call #get and #put within the same associated
try-catch-finally block for the same cache key.
If there is no object for a key, add null to the cache anyway. This
way you can ensure that the service doesn’t try to read data for a key
without an existing value more than one time
getQuiet
Returns an object from the cache but does NOT block requests for the
same key.
Use #getQuiet to acquire objects which are already cached.
This method is used more to observe or manage cached objects than to
fetch a specific object. The Magnolia
Cache Browser app is using #getQuiet,
for instance.
Example:
public List getCachedObjects(){
List<Object> cachedObjects = new ArrayList<>();
Cache cache = cacheFactoryProvider.get().get().getCache(NAME_OF_CACHE);
Collection<Object> keys = cache.getKeys();
for (Object key : keys) {
Object value = cache.getQuiet(key);
if (value != null) {
cachedObjects.add(value);
}
}
return cachedObjects;
}Copy