Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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.

Table of Contents
maxLevel3

Required modules

The functionality for caching arbitrary objects is provided by at least two modules.

Things to note about arbitrary object caching

Speed up services

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. 

Info

Configuration differs depending on which version of Ehcache you use. 

Ehcache

This is an example of how to configure a cache using Ehcache 2. Here you will find documentation of all configuration options. 

Extend the default factory and override the persistence strategy with none. This persistence strategy allows to cache non-serializable objects.

Advanced Tables - Table Plus
heading0
multiplefalse
enableHeadingAttributesfalse
enableSortingfalse
classm5-configuration-tree
enableHighlightingfalse
Node nameValue

Mgnl f
modules


Mgnl f
cache


Mgnl f
config


Mgnl n
cacheFactory


Mgnl n
caches


Mgnl n
default


Mgnl n
fooBarCache


Mgnl p
extends

../default

Mgnl p
timeToLiveSeconds

300

Mgnl n
persistence


Mgnl p
strategy

none

(warning) 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. Here 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.

Advanced Tables - Table Plus
heading0
multiplefalse
enableHeadingAttributesfalse
enableSortingfalse
classm5-configuration-tree
enableHighlightingfalse
Node nameValue

Mgnl f
modules


Mgnl f
cache


Mgnl f
config


Mgnl n
cacheFactory


Mgnl n
delegateFactories


Mgnl n
default


Mgnl n
fooBarCache


Mgnl n
resourcePoolsBuilder


Mgnl n
 pools


Mgnl n
 disk


Mgnl p
persistent

false

Mgnl p
extends

../default

Mgnl p
timeToLiveSeconds

300

(warning) 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 

Javadoc resource link
0info.magnolia.module.cache.Cache
classNameinfo.magnolia.module.cache.Cache
renderTypeasynchronous
.  This is your cache to operate on. Give it a name which must be unique within the system.

Example:

Code Block
languagejava
linenumberstrue
import javax.inject.Inject;
import javax.inject.Provider;
 
import info.magnolia.module.cache.Cache;
import info.magnolia.module.cache.inject.CacheFactoryProvider;

public class MyClass {
    private final Provider<CacheFactoryProvider> cacheFactoryProvider;

    @Inject
    public MyClass(Provider<CacheFactoryProvider> cacheFactoryProvider){
        this.cacheFactoryProvider = cacheFactoryProvider;
    }
    public void fooBar(){
        Cache cache = cacheFactoryProvider.get().get().getCache("fooBarCache"); 
    }
}
  • Lines 2, 4-6: Inject 
    Javadoc resource link
    0info.magnolia.module.cache.inject.CacheFactoryProvider
    classNameinfo.magnolia.module.cache.inject.CacheFactoryProvider
    renderTypeasynchronous
     and keep it as a final member of your class.
  • Line 9: Fetch the
    Javadoc resource link
    0info.magnolia.module.cache.Cache
    classNameinfo.magnolia.module.cache.Cache
    renderTypeasynchronous
     with its name. The cache provider will always return the same instance once it has been created.

All subsequent actions - adding, reading and removing objects - are applied on this Cache object.

Cache Interface

Code Pro
titleinfo.magnolia.module.cache.Cache
sections%%(public interface)%% -
urlhttps://git.magnolia-cms.com/projects/MODULES/repos/cache/browse/magnolia-cache-core/src/main/java/info/magnolia/module/cache/Cache.java?at=master&raw

Put to cache

Javadoc resource link
0info.magnolia.module.cache.Cache
classNameinfo.magnolia.module.cache.Cache
renderTypeasynchronous
 knows two methods to append objects.

Code Block
languagejava
void put(Object key, Object value);
 
void put(Object key, Object value, int timeToLiveInSeconds);

Arguments:

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).

Example:

Code Block
languagejava
public class MyClass {
    public Object put(Object key, Object value){
        Cache cache = cacheFactoryProvider.get().get().getCache("fooBarCache");
        cache.put(key, value);
        return value;
    }
    public Object put(Object key, Object value, int timeToLiveInSeconds){
        Cache cache = cacheFactoryProvider.get().get().getCache("fooBarCache");
        cache.put(key, value, timeToLiveInSeconds);
        return value;
    }
} 

Retrieve from cache

There are two methods to retrieve an object from cache. 

Code Block
languagejava
Object get(Object key);

Object getQuiet(Object key);

get

Returns an object from the cache and blocks all the requests for the same key. 

Example:

Code Block
languagejava
linenumberstrue
public JsonNode getData(String productId) throws Exception {
    Cache cache = cacheFactoryProvider.get().get().getCache(CACHEKEY);
    try {
        JsonNode jsonNode = (JsonNode) cache.get(productId);
        if (jsonNode != null) {
            return jsonNode;
        } else {
            jsonNode = readJson(productId);
            cache.put(productId, jsonNode);
            return jsonNode;
        }
    } catch (Exception e) {
        cache.put(productId, null); //unblock cache!
        throw e;
    }
}
Info

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. 

Info

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:

Code Block
languagejava
linenumberstrue
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;
}

Line 8: Uses #getQuiet 

Delete from cache

Remove a single item

Code Block
languagejava
Cache cache = cacheFactoryProvider.get().get().getCache("fooBarCache");
cache.remove("fb-90270240-xyz");

Clear complete cache

#clear deletes all items of a specific 

Javadoc resource link
0info.magnolia.module.cache.Cache
classNameinfo.magnolia.module.cache.Cache
renderTypeasynchronous
 which is identified by its "name"

Code Block
languagejava
cacheFactoryProvider.get().get().getCache("fooBarCache").clear()