Marilen Corciovei [
http://community.jboss.org/people/marilenc] created the document:
" Hibernate JbossCache integration"
To view the document, visit:
http://community.jboss.org/docs/DOC-15863
--------------------------------------------------------------
h2. Introduction
JbossCache is a wonderfully complex piece of software. Trying to use it with Hibernate
might seem an easy task at first but in reality it can also prove wonderfully
complicated.
First question is: *why would you consider using it in the first place?* Compared to
ehcache for instance there are a few theoretical advantages: clustering (scalability),
configurability and jmx monitoring.
Next question which is not quite obvious is *which version to use?* The answer is a bit
complicated since there are a lot of changes in versions which vary from architectural to
configuration points. This document is concerned with integration of hibernate 3.3.1 with
jboss cache 3.1.0 (Cascabel) as they are shipped in jboss 5.1.0.GA.
h2. Choices
I think most people consider that cache integration should be a matter of switching a
config option. I cannot argue with this logic and for them the most appropriate
configuration (as described in most documents) is as following (if using a
hibernate-service.xml .har configuration):
<property
name="cacheRegionFactoryClass">org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory</property>
along with activation of second level and query cache:
<property name="queryCacheEnabled">true</property>
<property name="secondLevelCacheEnabled">true</property>
This will probably work from start but also from start you will loose one of the
advantages: jmx monitoring
Let’s go back to the cacheRegionFactoryClass and it’s
hibernate.cache.region.factory_class equivalent. The hibernate documentation states there
are 4 options for this property. Here is my understanding of them:
* SharedJBossCacheRegionFactory will create a Cache (as in org.jboss.cache.Cache) based
on a treecache.xml configuration and use it for it’s caching purposes. You can provide
your configuration (in fact you must provide it) and everything seems perfect except that
you cannot have jmx instrumentation. I have found no way to obtain the Cache from a
SessionFactory and pass it to a CacheJmxWrapper for instrumentation.
* JndiSharedJBossCacheRegionFactory seems the perfect solution for the above problem as
you can create your cache and jmx via a -jboss-beans.xml configuration and then pass it
to hibernate. *Can you? No.* As there is no way to bind the cache to JNDI from the
-jboss-beans.xml configuration. No problem I might say. I will bind it myself. However
the Cache object is not serializable and you will end with an exception. *No again.*
javax.naming.CommunicationException [Root exception is java.io.NotSerializableException:
* MultiplexedJBossCacheRegionFactory is the most recommended solution. What it does is to
create multiple Caches managed by a CacheManager. Remember: you can still have multiple
cache regions with different eviction policies even in a single cache so the reason for
multiple caches seems an extreme case for me such as: having different passivations or
transport options. Note that this CacheManager is created by hibernate and is not exposed
to jmx. If you want to have a clustering environment with not much fuss you will end up
with jboss default cache manager which also creates several Cache’s of it’s own.
* JndiMultiplexedJBossCacheRegionFactory seems then a wises choice as it will let you
connect/use the existing CacheManager created by jboss (I will discuss configuration
issues later).
h2. Configuration
Here are some example configurations for the cases described above.
h3. treecache.xml for the SharedJbossCacheRegionFactory
You have to put it somewhere in the classpath root, for instance in your .har file. The
following example is local, does not uses jgroups and has a special region for
timestamps.
<?xml version="1.0" encoding="UTF-8"?>
<jbosscache xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance
http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:jboss:jbosscache-core:config:3.1">
<!--
isolation levels supported: READ_COMMITTED and REPEATABLE_READ
nodeLockingSchemes: mvcc, pessimistic (deprecated), optimistic (deprecated)
-->
<locking isolationLevel="REPEATABLE_READ"
lockParentForChildInsertRemove="false" lockAcquisitionTimeout="20000"
nodeLockingScheme="mvcc" writeSkewCheck="false"
useLockStriping="true" concurrencyLevel="500" />
<!-- Used to register a transaction manager and participate in ongoing
transactions. -->
<transaction
transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup"
syncRollbackPhase="false" syncCommitPhase="false" />
<!-- Used to register JMX statistics in any available MBean server -->
<jmxStatistics enabled="true" />
<!-- If region based marshalling is used, defines whether new regions are inactive
on startup. -->
<startup regionsInactiveOnStartup="true" />
<!--
Used to register JVM shutdown hooks.
hookBehavior: DEFAULT, REGISTER, DONT_REGISTER
-->
<shutdown hookBehavior="DEFAULT" />
<!-- Used to define async listener notification thread pool size -->
<listeners asyncPoolSize="1" asyncQueueSize="100000" />
<!-- Used to enable invocation batching and allow the use of
Cache.startBatch()/endBatch() methods. -->
<invocationBatching enabled="false" />
<!-- serialization related configuration, used for replication and cache loading
-->
<serialization objectInputStreamPoolSize="12"
objectOutputStreamPoolSize="14" version="3.0.0"
marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller"
useLazyDeserialization="false" useRegionBasedMarshalling="false"
/>
<!--
Eviction configuration. WakeupInterval defines how often the eviction thread runs,
in milliseconds. 0 means
the eviction thread will never run.
-->
<eviction wakeUpInterval="500">
<default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm"
eventQueueSize="200000">
<property name="maxNodes" value="5000" />
<property name="timeToLive" value="40000" />
</default>
<region name="/TS"
algorithmClass="org.jboss.cache.eviction.NullEvictionAlgorithm">
</region>
</eviction>
</jbosscache>
h3. -jboss-beans.xml deployement
Of a cache which cannot be bound to jndi and passed to SharedJbossCacheRegionFactory, also
local:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="urn:jboss:bean-deployer:2.0">
<!-- First we create a Configuration object for the cache -->
<bean name="DiapasonCacheConfig"
class="org.jboss.cache.config.Configuration">
<property name="runtimeConfig">
<bean class="org.jboss.cache.config.RuntimeConfig">
<property name="transactionManager">
<inject bean="jboss:service=TransactionManager"
property="TransactionManager"/>
</property>
<!--
<property name="muxChannelFactory"><inject
bean="JChannelFactory"/></property>
-->
</bean>
</property>
<property name="multiplexerStack">udp</property>
<property name="clusterName">Diapason-EntityCache</property>
<property name="isolationLevel">REPEATABLE_READ</property>
<property name="cacheMode">LOCAL</property>
<property name="stateRetrievalTimeout">15000</property>
<property name="syncReplTimeout">20000</property>
<property name="lockAcquisitionTimeout">15000</property>
<property name="exposeManagementStatistics">true</property>
</bean>
<!-- Factory to build the Cache. -->
<bean name="DefaultCacheFactory"
class="org.jboss.cache.DefaultCacheFactory">
<constructor factoryClass="org.jboss.cache.DefaultCacheFactory"
factoryMethod="getInstance" />
</bean>
<!-- The cache itself -->
<bean name="DiapasonCache" class="org.jboss.cache.Cache">
<constructor factoryMethod="createCache">
<factory bean="DefaultCacheFactory"/>
<parameter
class="org.jboss.cache.config.Configuration"><inject
bean="DiapasonCacheConfig"/></parameter>
<parameter class="boolean">false</parameter>
</constructor>
</bean>
<!-- JMX Management -->
<bean name="DiapasonCacheJmxWrapper"
class="org.jboss.cache.jmx.CacheJmxWrapper">
<annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.cache:service=DiapasonTreeCache",
exposedInterface=org.jboss.cache.jmx.CacheJmxWrapperMBean.class,
registerDirectly=true)</annotation>
<constructor>
<parameter><inject
bean="DiapasonCache"/></parameter>
</constructor>
</bean>
<!-- a bean I tried to use to register the cache to jndi, ignore
<bean name="CacheX" class="ro.len.CacheX">
<property name="cache"><inject
bean="DiapasonCache"/></property>
</bean>
-->
</deployment>
h3. MultiplexedJBossCacheRegionFactory
No config is needed in this case as hibernate will use 2 files jbc2-configs.xml and
jgroups-stacks.xml both found in hibernate-jbosscache2.jar. Of course if you want to take
advantage of the configurability of Jboss Cache you will have to take these files and
adapt them to your need.
h3. JndiMultiplexedJBossCacheRegionFactory
This option will give you most of the things you want and can be configured as following:
<property
name="cacheRegionFactoryClass">org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory</property>
<property
name="deployedCacheManagerJndiName">java:/CacheManager</property>
This will make use of the existing CacheManager which is registered to JNDI. However if
using the “default” configuration for jboss this is not the case. You will need to copy
jboss-cache-manager.sar and jgroups-channelfactory.sar from the all/deploy/cluster to
default/deploy/cluster along with an extra jar for pojo cache (jbosscache-pojo.jar, still
don’t know the use of that).
In order to configure your cache you will need to edit the
jboss-cache-manager-jboss-beans.xml file notably the optimistic-entity entry which
hibernate will use.
h2. Conclusions
You might ask: *why use jboss cache after all?* it does seem a bit too complicated. I
think you can find at least the following benefits:
* Configurability related to *cache regions*. This seems the most interesting benefit
from my point of view, can be done in any of the previous configs and does not require a
CacheManager or clustering.This is where you can configure various eviction policies.
You might want for instance some data to be evicted much slower than other or some data
never to evicted. This means of course some mapping (.hbm) changes in case of entities
consisting in adding the region attribute to the cache part of the mapping and some code
change in case of queries.
* *JMX* is of great use. First, it allows to see that the eviction configured really
works and second it shows lock problems which unfortunately where a problem in previous
jboss cache versions (as in jboss 4.2.2 GA). Let’s hope it will no longer be the case.
* Of least importance for most people it will be *clustering*. But even if initially it
might be of reduced importance it’s good to know if you ever need it support is already
there and only some configuration is required
h2. Links
Finally here are some links which I read a lot of times in the process of testing these
configurations and are the base for this article which intended to be much more shorter:
*
http://docs.jboss.org/jbosscache/3.1.0.CR1/userguide_en/html_single/index...
documentation for this cache version
*
http://docs.jboss.org/jbossclustering/hibernate-caching/3.3/en-US/html_si...
hibernate, jboss cache integration
*
http://community.jboss.org/message/270922#270922 post discussing the jmx/jndi exposure
(found it later but describes similar observations)
*
http://www.len.ro/2010/02/jboss-migration-4-2-2-ga-to-5-1-0-ga/ migration from jboss 4
to 5 document (why I arrived to this problem)
--------------------------------------------------------------
Comment by going to Community
[
http://community.jboss.org/docs/DOC-15863]
Create a new document in JBoss Cache at Community
[
http://community.jboss.org/choose-container!input.jspa?contentType=102&am...]