Chapter 5. Architecture

We've now gone through all the main concepts and the configuration
details; now we'll look a bit under the covers to understand a bit
more about the architectural design of the Hibernate/JBoss Cache
integration. Readers can skip this chapter if they aren't interested
in a look under the covers.

5.1. Hibernate Interface to the Caching Subsystem

The rest of Hibernate interacts with the Second Level Cache subsystem
via the org.hibernate.cache.RegionFactory interface.
What implementation of the interface is used is determined by the
value of the hibernate.cache.region.factory_class
configuration property. The interface itself is straightforward:

The start method is invoked during
SessionFactory startup and allows the region
factory implementation to access all the configuration settings
and initialize itself. The stop method is
invoked during SessionFactory shutdown.

The various build***Region methods are invoked as
Hibernate detects it needs to cache different data. Hibernate can
invoke these methods multiple times, with different
regionName values; each call results in the
establishment of a separate area in the underlying JBoss Cache
instance(s). For example, if an application includes an
entity class org.example.Order and another entity
class org.example.LineItem, you would see two
calls to buildEntityRegion, one for the
Order class and one for the
LineItem class. (Note that it is possible, and
recommended, to configure one or more shared regions for entities,
collections and queries. See Section 4.2, “Organization of Data in the Cache”
for some examples.)

For each call to a build***Region method, the
region factory returns a region object implementing the
EntityRegion, CollectionRegion,
QueryResultsRegion or TimestampsRegion
interface. Each interface specifies the needed semantics for
caching the relevant type of data. Thereafter, the Hibernate core
invokes on that region object to manage reading and writing data
in the cache.

Next, we'll look at the architecture of how the JBoss Cache integration
implements these interfaces, first in the case where a single JBoss
Cache instance is used, next in the case where multiple instances are
desired.

5.2. Single JBoss Cache Instance Architecture

The following diagram illustrates the key elements involved when
a single JBoss Cache instance is used:

For the single cache case, the user should specify
SharedJBossCacheRegionFactory as their
hibernate.cache.region.factory_class.

As part of its startup process, the region factory delegates
responsibility for providing JBoss Cache instances to an
implementation of the
org.hibernate.cache.jbc.CacheInstanceManager
interface. The region factory separately requests a JBoss Cache
instance for entities, one for collections, one for queries and one
for timestamps. Whether the CacheInstanceManager
provides the same underlying JBoss Cache instance for each
request or provides multiple caches is an implementation detail
of the CacheInstanceManager.

SharedJBossCacheRegionFactory creates an
instance of SharedCacheInstanceManager as
its CacheInstanceManager.
SharedCacheInstanceManager uses the JBoss Cache
configuration file specified by the user to create a single
org.jboss.cache.Cache instance, and provides
that same instance to the region factory when it requests the
cache for entities, collections, queries and timestamps.
SharedCacheInstanceManager also creates an
org.jgroups.ChannelFactory and passes it to
the Cache. The ChannelFactory
provides the cache with the org.jgroups.Channel
it uses for intra-cluster communication.

At this point, the region factory has a reference to a cache
for entities, a reference to a cache for collections, one for
queries and one for timestamps. In this particular case, each
reference points to the same underlying Cache
instance. When core Hibernate invokes the
buildEntityRegion operation on the region
factory, it instantiates an implementation of the
EntityRegion interface that knows how to
interface with JBoss Cache, passing it a reference to its
entity cache. Same thing happens for collections, etc.

Core Hibernate invokes on the EntityRegion,
which in turn invokes read and write operations on the underlying
JBoss Cache. The cache uses its Channel to
propagate changes to its peers in the cluster.

When the SessionFactory shuts down, it
invokes stop() on the region factory, which
in turn ensures that the JBoss Cache instance is stopped and
destroyed (which in turn closes the JGroups channel).

5.3. Multiple JBoss Cache Instance Architecture

The situation when multiple JBoss Cache instances are used is very
similar to the single cache case:

Here the user should specify
MultiplexedJBossCacheRegionFactory as their
hibernate.cache.region.factory_class. The
MultiplexedJBossCacheRegionFactory shares
almost all its code with SharedJBossCacheRegionFactory;
the main difference is it constructs a different CacheInstanceManager
implementation -- the MultiplexedCacheInstanceManager.

MultiplexedCacheInstanceManager differs from
SharedCacheInstanceManager in that it does
not directly instantiate a cache. Rather, it creates an
instance of org.jboss.cache.CacheManager,
providing it with a ChannelFactory and the
location of the user-specified cache configuration file. The
CacheManager parses the configuration file.

MultiplexedCacheInstanceManager analyzes
Hibernate's configuration to determine the name of the desired
cache configuration for entities, collections, queries and
timestamps. See Section 3.1.5, “The MultiplexedJBossCacheRegionFactory” for
details. It then asks its CacheManager to
provide each needed cache. In the diagram, two different caches are needed:

One, using the "optimistic-entity" configuration,
that is used for entities, collections and queries

Another, with the "timestamps-cache" configuration,
that is used for timestamps.

Both the "optimistic-entity" configuration and the "timestamps-cache"
configuration specify the use of the "udp" JGroups channel
configuration, so the CacheManager's
ChannelFactory will ensure that they share
the underlying JGroups resources.

The way the region factory creates regions is exactly the same
as in the single JBoss Cache case; the only difference is the
region factory's internal reference to its timestamps cache
now points to a different cache object from the entity, collection
and query cache references.