JBoss.org Community Documentation
To cluster stateful session beans in EJB 3.0, you need to tag the bean implementation class with
the @Cluster
annotation, just as we did with the EJB 3.0 stateless session bean
earlier. The @org.jboss.ejb3.annotation.cache.tree.CacheConfig annotation can also be applied to the bean to specify caching behavior. Below is the definition of the @CacheConfig annotation:
public @interface CacheConfig { String name() default "jboss.cache:service=EJB3SFSBClusteredCache"; int maxSize() default 10000; long idleTimeoutSeconds() default 300; boolean replicationIsPassivation() default true; long removalTimeoutSeconds() default 0; }
name
specifies the object name of the JBoss Cache Mbean that should be used for caching the bean (see below for more on this Mbean).
maxSize
specifies the maximum number of beans that can cached before the cache should start passivating beans, using an LRU algorithm.
idleTimeoutSeconds
specifies the max period of time a bean can go unused before the cache should passivate it (irregardless of whether maxSize beans are cached.)
removalTimeoutSeconds
specifies the max period of time a bean can go unused before the cache should remove it altogether.
replicationIsPassivation
specifies whether the cache should consider a replication as being equivalent to a passivation, and invoke any @PrePassivate and @PostActivate callbacks on the bean. By default true, since replication involves serializing the bean, and preparing for and recovering from serialization is a common reason for implementing the callback methods.
Here is an example of a clustered EJB 3.0 stateful session bean implementation.
@Stateful @Clustered @CacheConfig(maxSize=5000,removalTimeoutSeconds=18000) public class MyBean implements MySessionInt { private int state = 0; public void increment() { System.out.println("counter: " + (state++)); } }
As with stateless beans, the @Clustered annotation can also be omitted and the clustering configuration applied in jboss.xml; see the example above.
As with EJB 2.0 clustered SFSBs, JBoss provides a mechanism whereby a bean implementation can expose a method the container can invoke to check whether the bean's state is not dirty after a request and doesn't need to be replicated. With EJB3, the mechanism is a little more formal; instead of just exposing a method with a known signature, an EJB3 SFSB must implement the org.jboss.ejb3.cache.Optimized interface:
public interface Optimized { boolean isModified(); }
JBoss Cache provides the session state replication service for EJB 3.0 stateful session beans. The
related MBean service is defined in the ejb3-clustered-sfsbcache-service.xml
file
in the deploy
directory. The contents of the file are as follows.
<server> <mbean code="org.jboss..cache.TreeCache" name="jboss.cache:service=EJB3SFSBClusteredCache"> <attribute name="ClusterName"> ${jboss.partition.name:DefaultPartition}-SFSBCache </attribute> <attribute name="IsolationLevel">REPEATABLE_READ</attribute> <attribute name="CacheMode">REPL_ASYNC</attribute> <!-- We want to activate/inactivate regions as beans are deployed --> <attribute name="UseRegionBasedMarshalling">true</attribute> <!-- Must match the value of "useRegionBasedMarshalling" --> <attribute name="InactiveOnStartup">true</attribute> <attribute name="ClusterConfig"> ... ... </attribute> <!-- The max amount of time (in milliseconds) we wait until the initial state (ie. the contents of the cache) are retrieved from existing members. --> <attribute name="InitialStateRetrievalTimeout">17500</attribute> <!-- Number of milliseconds to wait until all responses for a synchronous call have been received. --> <attribute name="SyncReplTimeout">17500</attribute> <!-- Max number of milliseconds to wait for a lock acquisition --> <attribute name="LockAcquisitionTimeout">15000</attribute> <!-- Name of the eviction policy class. --> <attribute name="EvictionPolicyClass"> org.jboss.cache.eviction.LRUPolicy </attribute> <!-- Specific eviction policy configurations. This is LRU --> <attribute name="EvictionPolicyConfig"> <config> <attribute name="wakeUpIntervalSeconds">5</attribute> <name>statefulClustered</name> <!-- So default region would never timeout --> <region name="/_default_"> <attribute name="maxNodes">0</attribute> <attribute name="timeToIdleSeconds">0</attribute> </region> </config> </attribute> <!-- Store passivated sessions to the file system --> <attribute name="CacheLoaderConfiguration"> <config> <passivation>true</passivation> <shared>false</shared> <cacheloader> <class>org.jboss.cache.loader.FileCacheLoader</class> <!-- Passivate to the server data dir --> <properties> location=${jboss.server.data.dir}${/}sfsb </properties> <async>false</async> <fetchPersistentState>true</fetchPersistentState> <ignoreModifications>false</ignoreModifications> </cacheloader> </config> </attribute> </mbean> </server>
The configuration attributes in this MBean are essentially the same as the attributes in the standard JBoss Cache TreeCache
MBean discussed
in Chapter 22, JBossCache and JGroups Services
. Again, we omitted the JGroups configurations in the
ClusterConfig
attribute (see more in Section 22.1, “JGroups Configuration”). Two noteworthy items:
The cache is configured to support eviction. The EJB3 SFSB container uses the JBoss Cache eviction mechanism to manage SFSB passivation. When beans are deployed, the EJB container will programatically add eviction regions to the cache, one region per bean type.
A JBoss Cache CacheLoader is also configured; again to support SFSB passivation. When beans are evicted from the cache, the cache loader passivates them to a persistent store; in this case to the filesystem in the $JBOSS_HOME/server/all/data/sfsb directory. JBoss Cache supports a variety of different CacheLoader implementations that know how to store data to different persistent store types; see the JBoss Cache documentation for details. However, if you change the CacheLoaderConfiguration, be sure that you do not use a shared store (e.g., a single schema in a shared database.) Each node in the cluster must have its own persistent store, otherwise as nodes independently passivate and activate clustered beans, they will corrupt each others data.