This howto will guide you to use the EJB3 cartridge caching and clustering facilities, based on the JBoss distributed/clustered caching environment.
JBoss Cache supports a high performance, in-memory, transactional, and replicated cache for the cluster.
JBoss Cache has 2 types of caching
Access by one node in the cluster makes the POJO available to all nodes via the distributed entity cache.
The following example was taken from the manageable entities howto with the caching options enabled. The manageable components are not relevant here and will not be discussed.
Remember: You must set the persistenceProviderExtensions namespace property such that Hibernate cache specific annotations are generated.
The following sections will show you how to enable and configure caching and clustering.
The EJB3 cartridge allows you to configure caching through namespace properties via your application andromda.xml descriptor. Make sure the hibernateCacheProvider and hibernateTreecacheMbeanObject properties are defined to use the internal JBoss Cache with JBoss.
<namespace name="ejb3"> <properties> ... <property name="hibernateCacheProvider">org.jboss.ejb3.entity.TreeCacheProviderHook</property> <property name="hibernateTreecacheMbeanObject">jboss.cache:service=EJB3EntityTreeCache</property> <!-- uncomment to enable default entity cache settings --> <property name="hibernateEntityCache">TRANSACTIONAL</property> <!-- uncomment to enable default association caching configuration --> <property name="hibernateAssociationCache">TRANSACTIONAL</property> ... </properties> </namespace>
Your generated persistence.xml descriptor will look something like:
<?xml version="1.0" encoding="UTF-8"?> <!-- Attention: Generated code! Do not modify by hand! Generated by: persistence.xml.vsl in andromda-ejb3-cartridge. --> <persistence> <persistence-unit name="howtomodelcaching"> <jta-data-source>java:/jdbc/howtomodelcaching</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/> <property name="hibernate.cache.provider_class" value="org.jboss.ejb3.entity.TreeCacheProviderHook"/> <property name="hibernate.treecache.mbean.object_name" value="jboss.cache:service=EJB3EntityTreeCache"/> </properties> </persistence-unit> </persistence>
In situations where data, persisted by entity beans are rarely changed, you can employ the entity cache option to avoid unnecessary round-trips to the database.
To enable entity caching, you enable the hibernateEnableCache ejb3 namespace property in your andromda.xml like so:
<namespace name="ejb3"> <properties> ... <property name="hibernateEnableCache">true</property> <property name="useDefaultCacheRegion">false</property> ... </properties> </namespace>
The useDefaultCacheRegion property allows you to specify whether you want all entities to use the default cache region specified in ejb3-entity-cache-service.xml and the cache region set on corresponding finder queries. By default, this is set to false. If you set it to true, the user specified cache regions for entities will not be defined.
If you enable the default entity caching in your andromda.xml descriptor (by enabling hibernateEntityCache), then caching will be enabled for all entities. To override this default value, you can model the andromda_persistence_entity_cache tagged value on individual entities.
Once you have enabled entity caching, you will notice the @org.hibernate.annotations.Cache annotation at the class level in all entities.
The corresponding entity cache region is defined in the ejb3-entity-cache-service.xml configuration service file for the Car and Person entities:
.... <!-- The Car entity cache --> <region name="/org/andromda/howto2/rental/Car"> <attribute name="maxNodes">10000</attribute> <attribute name="timeToLiveSeconds">5000</attribute> </region> <!-- The Person entity cache --> <region name="/org/andromda/howto2/rental/Person"> <attribute name="maxNodes">10000</attribute> <attribute name="timeToLiveSeconds">5000</attribute> </region> ....
You must deploy the ejb3-entity-cache-service.xml to your JBoss deploy folder as you do with your ear package bundle. Remember, if you have other cached enabled applications, you must merge the changes to the ejb3-entity-cache-service.xml manually, otherwise you will override previous configurations.
To enable entity association relationship caching, you enable the hibernateEnableAssociationsCache ejb3 namespace property in your andromda.xml like so:
<namespace name="ejb3"> <properties> ... <property name="hibernateEnableCache">true</property> <property name="hibernateEnableAssociationsCache">true</property> ... </properties> </namespace>
If you enable the default association cache strategy in your andromda.xml descriptor, (by enabling hibernateAssociationCache), then all collection association caching will be enabled by default. To override this default value, you can model the andromda_persistence_association_cache tagged value on individual target association ends.
Once you have enabled entity association caching, you will notice the @org.hibernate.annotations.Cache annotation on One-To-Many and Many-To-Many relationships.
To enable entity query caching for all queries, you enable the hibernateUseQueryCache ejb3 namespace property in your andromda.xml like so:
<namespace name="ejb3"> <properties> ... <property name="hibernateEnableCache">true</property> <property name="hibernateUseQueryCache">true</property> <property name="useDefaultCacheRegion">false</property> ... </properties> </namespace>
In many circumstance, you shouldn't enable query cache for all queries (using the hibernateUseQueryCache property) but enable caching for required queries only. You can enable caching for individual finder method using the andromda_ejb_query_useCache tagged value which is modeled on the finder method.
The useDefaultCacheRegion property allows you to specify whether you want all queries to use the default cache region specified in ejb3-entity-cache-service.xml. By default, this is set to false. If you set it to true, the user specified cache regions will not be defined and the hint on queries to set the cache region will not be assigned.
The cartridge will look for at least one query which is marked for caching. If it finds one such query, the persistence.xml descriptor will include the hibernate.cache.use_query_cache like so:
<?xml version="1.0" encoding="UTF-8"?> <!-- Attention: Generated code! Do not modify by hand! Generated by: persistence.xml.vsl in andromda-ejb3-cartridge. --> <persistence> <persistence-unit name="howtomodel2"> <jta-data-source>java:/jdbc/howtomodel2</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/> <property name="hibernate.cache.provider_class" value="org.jboss.ejb3.entity.TreeCacheProviderHook"/> <property name="hibernate.treecache.mbean.object_name" value="jboss.cache:service=EJB3EntityTreeCache"/> <property name="hibernate.cache.use_query_cache">true</property> </properties> </persistence-unit>
In the above example, the Car entity has the findByType finder marked as cacheable. When generating thefindByType DAO method in CarDaoBase.java, the cartridge will set the org.hibernate.cacheRegion hint automatically like so:
public java.util.List findByType(final int transform, final org.andromda.howto2.rental.CarType type) throws org.andromda.howto2.rental.CarDaoException { try { javax.persistence.Query queryObject = emanager.createNamedQuery("Car.findByType"); queryObject.setParameter("type", type.name()); queryObject.setHint("org.hibernate.cacheRegion", "/org/andromda/howto2/rental/Car_findByType"); java.util.List results = queryObject.getResultList(); transformEntities(transform, results); return results; } catch (Exception ex) { throw new org.andromda.howto2.rental.CarDaoException(ex); } }
The corresponding cache region is defined in the ejb3-entity-cache-service.xml configuration service file:
.... <!-- The Car entity cache --> <region name="/org/andromda/howto2/rental/Car"> <attribute name="maxNodes">10000</attribute> <attribute name="timeToLiveSeconds">5000</attribute> </region> ....
You must deploy the ejb3-entity-cache-service.xml to your JBoss deploy folder as you do with your ear package bundle. Remember, if you have other cached enabled applications, you must merge the changes to the ejb3-entity-cache-service.xml manually, otherwise you will override previous configurations.
Enabling session bean clustering is achieved by setting the enableClustering ejb3 namespace property to true.
<namespace name="ejb3"> <properties> ... property name="enableClustering">true</property> ... </properties> </namespace>
There is nothing more you need to do for stateless session beans. For stateful session beans, you must make sure that the JBoss Cache session state replication service is deployed. Simply make sure that ejb3-clustered-sfsbcache-service.xml exists in your JBoss deploy directory.
To expose service operations and session beans as webservices click here.