JBoss.orgCommunity Documentation
The
Cache
interface is the primary mechanism for interacting with JBoss Cache. It is
constructed and optionally started using the
CacheFactory
. The
CacheFactory
allows you to create a
Cache
either from a
Configuration
object
or an XML file. Once you have a reference to a
Cache
, you can use it to look up
Node
objects in the tree structure, and store data in the tree.
Reviewing the javadoc for the above interfaces is the best way to learn the API. Below we cover some of the main points.
An instance of the
Cache
interface can only be created
via a
CacheFactory
. (This is unlike JBoss Cache 1.x,
where an instance of the old
TreeCache
class could
be directly instantiated.)
CacheFactory
provides a number of overloaded methods
for creating a
Cache
, but they all do the same thing:
Configuration
, either
by having one passed in as a method parameter, or by parsing XML
content and constructing one. The XML content can come from a
provided input stream or from a classpath or filesystem location.
See the
chapter on Configuration
for
more on obtaining a
Configuration
.
Cache
and provide
it with a reference to the
Configuration
.
create()
and
start()
methods.
An example of the simplest mechanism for creating and starting a cache, using the default configuration values:
CacheFactory factory = new DefaultCacheFactory();
Cache cache = factory.createCache();
Here we tell the
CacheFactory
to find and
parse a configuration file on the classpath:
CacheFactory factory = new DefaultCacheFactory();
Cache cache = factory.createCache("cache-configuration.xml");
Here we configure the cache from a file, but want to programatically change a configuration element. So, we tell the factory not to start the cache, and instead do it ourselves:
CacheFactory factory = new DefaultCacheFactory();
Cache cache = factory.createCache("cache-configuration.xml", false);
Configuration config = cache.getConfiguration();
config.setClusterName(this.getClusterName());
// Have to create and start cache before using it
cache.create();
cache.start();
Next, let's use the
Cache
API to access
a
Node
in the cache and then do some
simple reads and writes to that node.
// Let's get ahold of the root node.
Node rootNode = cache.getRoot();
// Remember, JBoss Cache stores data in a tree structure.
// All nodes in the tree structure are identified by Fqn objects.
Fqn peterGriffinFqn = Fqn.fromString("/griffin/peter");
// Create a new Node
Node peterGriffin = rootNode.addChild(peterGriffinFqn);
// let's store some data in the node
peterGriffin.put("isCartoonCharacter", Boolean.TRUE);
peterGriffin.put("favouriteDrink", new Beer());
// some tests (just assume this code is in a JUnit test case)
assertTrue(peterGriffin.get("isCartoonCharacter"));
assertEquals(peterGriffinFqn, peterGriffin.getFqn());
assertTrue(rootNode.hasChild(peterGriffinFqn));
Set keys = new HashSet();
keys.add("isCartoonCharacter");
keys.add("favouriteDrink");
assertEquals(keys, peterGriffin.getKeys());
// let's remove some data from the node
peterGriffin.remove("favouriteDrink");
assertNull(peterGriffin.get("favouriteDrink");
// let's remove the node altogether
rootNode.removeChild(peterGriffinFqn);
assertFalse(rootNode.hasChild(peterGriffinFqn));
The
Cache
interface also exposes put/get/remove
operations that take an
Fqn
as an argument:
Fqn peterGriffinFqn = Fqn.fromString("/griffin/peter");
cache.put(peterGriffinFqn, "isCartoonCharacter", Boolean.TRUE);
cache.put(peterGriffinFqn, "favouriteDrink", new Beer());
assertTrue(peterGriffin.get(peterGriffinFqn, "isCartoonCharacter"));
assertTrue(cache.getRootNode().hasChild(peterGriffinFqn));
cache.remove(peterGriffinFqn, "favouriteDrink");
assertNull(cache.get(peterGriffinFqn, "favouriteDrink");
cache.removeNode(peterGriffinFqn);
assertFalse(cache.getRootNode().hasChild(peterGriffinFqn));
The previous section used the
Fqn
class in its
examples; now let's learn a bit more about that class.
A Fully Qualified Name (Fqn) encapsulates a list of names which represent
a path to a particular location in the cache's tree structure. The
elements in the list are typically
String
s but can be
any
Object
or a mix of different types.
This path can be absolute (i.e., relative to the root node), or relative
to any node in the cache. Reading the documentation on each API call that
makes use of
Fqn
will tell you whether the API expects
a relative or absolute
Fqn
.
The
Fqn
class provides are variety of constructors;
see the javadoc for all the possibilities. The following illustrates the
most commonly used approaches to creating an Fqn:
// Create an Fqn pointing to node 'Joe' under parent node 'Smith'
// under the 'people' section of the tree
// Parse it from a String
Fqn<String> abc = Fqn.fromString("/people/Smith/Joe/");
// Build it directly. Marginally more efficient to construct than parsing
String[] strings = new String[] { "people", "Smith", "Joe" };
Fqn<String> abc = new Fqn<String>(strings);
// Here we want to use types other than String
Object[] objs = new Object[]{ "accounts", "NY", new Integer(12345) };
Fqn<Object> acctFqn = new Fqn<Object>(objs);
Note that
Fqn<String> f = new Fqn<String>("/a/b/c");
is not the same as
Fqn<String> f = Fqn.fromString("/a/b/c");
The former will result in an Fqn with a single element, called "/a/b/c"
which hangs directly under the cache root. The latter will result
in a 3 element Fqn, where "c" idicates a child of "b", which is a child
of "a", and "a" hangs off the cache root. Another way to
look at it is that the "/" separarator is only parsed when it forms
part of a String passed in to
Fqn.fromString()
and not
otherwise.
The JBoss Cache API in the 1.x releases included many overloaded
convenience methods that took a string in the
/a/b/c
format in place
of an
Fqn
. In the interests of API simplicity, no
such convenience methods are available in the JBC 2.x API.
It is good practice to stop and destroy your cache when you are done using it, particularly if it is a clustered cache and has thus used a JGroups channel. Stopping and destroying a cache ensures resources like the JGroups channel are properly cleaned up.
cache.stop();
cache.destroy();
Not also that a cache that has had
stop()
invoked
on it can be started again with a new call to
start()
.
Similarly, a cache that has had
destroy()
invoked
on it can be created again with a new call to
create()
(and then started again with a
start()
call).
Although technically not part of the API, the
mode
in which the cache is configured to operate affects the cluster-wide
behavior of any
put
or
remove
operation, so we'll briefly mention the various modes here.
JBoss Cache modes are denoted by the
org.jboss.cache.config.Configuration.CacheMode
enumeration.
They consist of:
See the chapter on Clustering for more details on how the cache's mode affects behavior. See the chapter on Configuration for info on how to configure things like the cache's mode.
The
@org.jboss.cache.notifications.annotation.CacheListener
annotation is a convenient
mechanism for receiving notifications from a cache about events that happen in the cache. Classes annotated
with
@CacheListener
need to be public classes. In addition, the class needs to have one or
more methods annotated with one of the method-level annotations (in the
org.jboss.cache.notifications.annotation
package). Methods annotated as such need to be public, have a void return type, and accept a single parameter
of
type
org.jboss.cache.notifications.event.Event
or one of it's subtypes.
@CacheStarted
- methods annotated such receive a notification when the cache is
started. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.CacheStartedEvent
.
@CacheStopped
- methods annotated such receive a notification when the cache is
stopped. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.CacheStoppedEvent
.
@NodeCreated
- methods annotated such receive a notification when a node is
created. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeCreatedEvent
.
@NodeRemoved
- methods annotated such receive a notification when a node is
removed. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeRemovedEvent
.
@NodeModified
- methods annotated such receive a notification when a node is
modified. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeModifiedEvent
.
@NodeMoved
- methods annotated such receive a notification when a node is
moved. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeMovedEvent
.
@NodeVisited
- methods annotated such receive a notification when a node is
started. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeVisitedEvent
.
@NodeLoaded
- methods annotated such receive a notification when a node is
loaded from a
CacheLoader
. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeLoadedEvent
.
@NodeEvicted
- methods annotated such receive a notification when a node is
evicted from memory. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeEvictedEvent
.
@NodeActivated
- methods annotated such receive a notification when a node is
activated. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodeActivatedEvent
.
@NodePassivated
- methods annotated such receive a notification when a node is
passivated. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.NodePassivatedEvent
.
@TransactionRegistered
- methods annotated such receive a notification when the cache
registers a
javax.transaction.Synchronization
with a registered transaction manager.
Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.TransactionRegisteredEvent
.
@TransactionCompleted
- methods annotated such receive a notification when the cache
receives a commit or rollback call from a registered transaction manager.
Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.TransactionCompletedEvent
.
@ViewChanged
- methods annotated such receive a notification when the group structure
of the cluster changes. Methods need to accept a parameter type which is assignable from
org.jboss.cache.notifications.event.ViewChangedEvent
.
@CacheBlocked
- methods annotated such receive a notification when the cluster
requests that cache operations are blocked for a state transfer event. Methods need to accept a
parameter type which is assignable from
org.jboss.cache.notifications.event.CacheBlockedEvent
.
@CacheUnblocked
- methods annotated such receive a notification when the cluster
requests that cache operations are unblocked after a state transfer event. Methods need to accept a
parameter type which is assignable from
org.jboss.cache.notifications.event.CacheUnblockedEvent
.
Refer to the javadocs on the annotations as well as the
Event
subtypes
for details of what is passed in to your method, and when.
Example:
@CacheListener
public class MyListener
{
@CacheStarted
@CacheStopped
public void cacheStartStopEvent(Event e)
{
switch (e.getType())
{
case Event.Type.CACHE_STARTED:
System.out.println("Cache has started");
break;
case Event.Type.CACHE_STOPPED:
System.out.println("Cache has stopped");
break;
}
}
@NodeCreated
@NodeRemoved
@NodeVisited
@NodeModified
@NodeMoved
public void logNodeEvent(NodeEvent ne)
{
log("An event on node " + ne.getFqn() + " has occured");
}
}
Cache loaders are an important part of JBoss Cache. They allow persistence of nodes to disk or to remote cache clusters, and allow for passivation when caches run out of memory. In addition, cache loaders allow JBoss Cache to perform 'warm starts', where in-memory state can be preloaded from persistent storage. JBoss Cache ships with a number of cache loader implementations.
org.jboss.cache.loader.FileCacheLoader
- a basic, filesystem based cache loader that persists data to disk. Non-transactional and not very
performant, but a very simple solution. Used mainly for testing and not recommended for production use.
org.jboss.cache.loader.JDBCCacheLoader
- uses a JDBC connection to store data. Connections could be created and maintained in an internal pool
(uses the c3p0 pooling library)
or from a configured DataSource. The database this CacheLoader connects to could be local or remotely
located.
org.jboss.cache.loader.BdbjeCacheLoader
- uses Oracle's BerkeleyDB file-based transactional database to persist data. Transactional and very
performant, but potentially restrictive license.
org.jboss.cache.loader.JdbmCacheLoader
- an upcoming open source alternative to the BerkeleyDB.
org.jboss.cache.loader.tcp.TcpCacheLoader
- uses a TCP socket to "persist" data to a remote cluster, using a "far cache" pattern.
[1]org.jboss.cache.loader.ClusteredCacheLoader
- used as a "read-only" CacheLoader, where other nodes in the cluster are queried for state.
These CacheLoaders, along with advanced aspects and tuning issues, are discussed in the chapter dedicated to CacheLoaders .
Eviction policies are the counterpart to CacheLoaders. They are necessary to make sure the cache does not run out of memory and when the cache starts to fill, the eviction algorithm running in a separate thread offloads in-memory state to the CacheLoader and frees up memory. Eviction policies can be configured on a per-region basis, so different subtrees in the cache could have different eviction preferences. JBoss Cache ships with several eviction policies:
org.jboss.cache.eviction.LRUPolicy
- an eviction policy that evicts the least recently used nodes when thresholds are hit.
org.jboss.cache.eviction.LFUPolicy
- an eviction policy that evicts the least frequently used nodes when thresholds are hit.
org.jboss.cache.eviction.MRUPolicy
- an eviction policy that evicts the most recently used nodes when thresholds are hit.
org.jboss.cache.eviction.FIFOPolicy
- an eviction policy that creates a first-in-first-out queue and evicts the oldest nodes when thresholds
are hit.
org.jboss.cache.eviction.ExpirationPolicy
- an eviction policy that selects nodes for eviction based on an expiry time each node is configured
with.
org.jboss.cache.eviction.ElementSizePolicy
- an eviction policy that selects nodes for eviction based on the number of key/value pairs held in the
node.
Detailed configuration and implementing custom eviction policies are discussed in the chapter dedicated to eviction policies. .