Cache loading refers to the process whereby a cache transparently (lazy) load or create values for requested key(s).
This technique can often be more efficient then requiring a user to fill up the cache in advance. A cache loader might load data from an external site, a databases or just a plain text-based file. Data can also be created on the fly, for example, as a result of some calculation.
Overview
The loading service is located in the org.coconut.cache.service.loading package. It consists of the following 7 classes
Class |
Description |
|---|---|
AbstractCacheLoader |
An abstract implementation of CacheLoader, used as basis for simple implementations of CacheLoader. |
CacheLoader |
User-provided class responsible for loading values from a specified request. |
CacheLoaderCallback |
Used in complex CacheLoader's to support asynchronously loading of values. |
CacheLoaders |
Contains various utility classes and functions. |
CacheLoadingConfiguration |
This class is used to configure the loading service prior to usage. |
CacheLoadingMXBean |
If JMX management is enabled for the cache. An instance of this class can be accessed by a JMX client. |
CacheLoadingService |
This class is used to control the loading service at runtime. |
The CacheLoader
A CacheLoader implementation is responsible for loading or creating the data that should be inserted into the cache from some specified key.
The load method takes a single key and an AttributeMap. The key should contain enough information to allow the CacheLoader to retrieve the matching value. The AttributeMap can be be used by the cache to specify additional properties or the CacheLoader can return metadata about the loaded value back to the Cache. For example, the size of the value or the cost of retrieving the value.
If you are defining a simple cache loader you will most likely not have any need for AttributeMap parameter, in this case it can just be ignored. The loadAll method takes a collection of callbacks containing the keys that should be loaded and a method for setting the values once they have been loaded. This method is primarily useful for cache loaders that can take advantage of bulk loading. If this is not the case, the cache loader can extend org.coconut.cache.service.loading.AbstractCacheLoader which only requires the load method to be implemented.
The following example shows a cache loader (extending AbstractCacheLoader) which takes a String formatted as an url and retrieves the corresponding content as a String:
To configure the cache to use this cache loader, we use:
Now when we call cache.get("http://www.google.com") the first time, it will use SimpleUrlLoader to retrieve the web page. However, the second time we call cache.get() the cache will return the cached content instead of retrieving the web page again.
Prefetching and updating values in the cache
Prefetching is the process of getting a value from some external location into the cache well before it will need it. An immediate example is prefetching the second page of a result set whenever a query is submitted by a user. In this way the cache can return the second page without any delay.
The CacheLoadingService interface supports a two groups of methods for doing this. A number of methods starting with *load*, for example, load(K key), which will load the value if it is not already present in the cache or if it expired. The other group of methods starts with forceLoad* and will always load a new value even if valid one is already present in the cache. Unless otherwise specified the cache will load the values asynchronously.
Examples of various loading calls:
Refreshing entries
It is often useful to be able to refresh cache entries before they expire. Consider, for example, an entry that is only valid for exactly 1 hour. When the entry is accessed after it has expired. The cache suffers a cache miss and will need to fetch an updated entry from the configured cache loader. Instead, we would want the cache to refresh the entry 5 minutes before it expires, in order to avoid paying the cost for a cache miss. By setting a cache-wide refresh value we can force the cache to refresh cache entries before they expire.
The following example, shows how a cache can be configured to support this: ([full src|http://svn.codehaus.org/coconut/trunk/coconut-cache/coconut-cache-examples/src/main/java/org/coconut/cache/examples/expiration/RefreshEntryExample.java])
Hard condition=expiration, soft condition=refreshing
Checking of Refresh status is only mandatory for the loadAll method, however a cache is free to make additional checks.
It is also possible to create more elaborate refresh mechanism by using a developing a refresh Filter much like the Custom Expiration filter.
The following shows a refresh filter that will refresh entries that have not been updated in the last 1 hour: ([full src|http://svn.codehaus.org/coconut/trunk/coconut-cache/coconut-cache-examples/src/main/java/org/coconut/cache/examples/expiration/RefreshFilterExample.java])
