Clustering Entities do not provide remote services like session beans, so they are not concerned with the load-balancing logic or session replication. You can, however, use a cache for your entities to avoid roundtrips to the database. JBoss AS7EJB 3.0 persistence-layer JPA implementation is based on the Hibernate framework and, as such, this framework has a complex cache mechanism, which is implemented both at Session level and at SessionFactory level.
The latter mechanism is called second-level caching. The purpose of a JPA/Hibernate second-level cache is to store entities or collections locally retrieved from the database or to maintain results of recent queries.
Enabling the second-level cache for your Enterprise applications needs some properties to be set. If you are using JPA to access the second-level cache, all you have to add in the persistence.xml configuration file is:
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.cache.use_second_level_cache"
value="true"/>
<property name='hibernate.cache.use_minimal_puts"value="true"/>
</prperties>
The first element, shared-cache-mode, is the JPA 2.0 way to specify whether the entities and entity-related state of a persistence unit will be cached. The shared cache- mode element has five possible values, as indicated in the following table:
Shared Cache mode | Description |
ALL | Causes all entities and entity-related state and data to be cached. |
NONE | Causes caching to be disabled for the persistence unit. |
ENABLE_SELECTIVE | Allows caching if the @Cacheable annotation is specified on the entity class. |
DISABLE_SELECTIVE | Enables the cache and causes all entities to be cached except those for which @Cacheable (false) is specified. |
The property named hibernate.cache.use_minimal_puts performs some optimization on the second-level cache, by reducing the amount of writes in the caches at the cost of some additional reads.
In addition, if you plan to use the Hibernate Query cache in your applications, you need to activate it with a separate property:
<property name="hibernate.cache.use_qurey_cache"value="true"/>
For the sake of completeness, we will also include here the configuration needed for using Infinispan as a caching provider for native Hibernate applications. This is the list of properties you have to add to your hibernate.cfg.xml:
name=”hibernate.cache.region.factory_class”value=”org.hibernate.cache.infinispan.
name=”hibernate.cache.infinispan.cachemanager”value=”java:jboss/infinispan/hibernate”/> name=”hibernate.transaction.manager_lookup_class”value=”org.hibernate.transaction. value=”true”/>
As you can see, the configuration is a bit more verbose because you have to tell Hibernate to use Infinispan as a caching provider. This requires setting the correct Hibernate transaction factory, using the hibernate.transaction.factory_class property.
Next, the property hibernate.cache.infinispan.cachemanager exposes the CacheManager used by Infinispan. By default, Infinispan binds in the JNDI a shared CacheManager under the key java:jboss/infinispan/hibernate. This will be in charge to handle the second-level cache on the cached objects.
Finally, the property hibernate.cache.region.factory_class tells Hibernate to use the Infinispan second-level caching integration, using the previous Infinispan CacheManager found in JNDI as the source for Infinispan cache’s instances.
Unless you have set shared-cache-mode to ALL, Hibernate will not cache entity automatically. You have to select which entities or queries need to be cached. This is definitely the safest option since indiscriminate caching can actually hurt performance.
The following example shows how to do this for JPA entities using annotations.
import java.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region
=”properties”)
public class Property {
@Id
@Column(name=”key”)
private String key;
@Column(name=”value”)
private String value;
// Getter & setters omitted for brevity
}
The @javax.persistence.Cacheable dictates whether the Hibernate shared cache should be used for instances of the entity class and is applicable only when the shared cache- mode is set to one of the selective modes.
The @org.hibernate.annotations.Cache annotation is the older annotation used to achieve the same purpose of @Cacheable. You can still use it for defining which strategy for controlling concurrent access to cache contents Hibernate should use.
The CacheConcurrencyStrategy.TRANSACTIONAL provides support for an Infinispan fully-transactional JTA environment.
Frequently asked Jboss Interview Questions
If there are chances that your application data is read but never modified, you can apply the CacheConcurrencyStrategy.READ_ONLY that does not evict data from the cache (unless performed programmatically).
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
Finally, the other attribute that can be defined is the caching region where entities are placed. If you do not specify a cache region for an entity class, all instances of this class will be cached in the _default region. Defining a caching region can be useful if you want to perform fine-grained management of caching areas.
The query cache can be used to cache data from a query so that if the same query is issued again, it will not hit the database but return the cached value.
In the following example, the query result set named listUsers is configured to be cached using the @QueryHint annotation inside a @NamedQuery:
@NamedQueries(
{@
NamedQuery(
name = “listUsers”,
query = “FROM User c WHERE c.name = :name”,
hints = { @QueryHint(name = “org.hibernate.cacheable”, value =
“true”) }
)}
)
public class User {
@Id
@Column(name=” key”)
private String key;
@Column(name=” name”)
private String name;
. . . . .
}
Clustering web applications requires the least effort for the developer. As we have just discussed, all you need to switch on clustering in a web application is adding the following directive in the web.xml descriptor:
<web-app>
<distributable/>
</web-app>
By default, clustered web applications will use the web cache contained in the Infinispan configuration. One thing you can customize is setting up a specific cache per deployment unit. This can be achieved by adding to JBoss-web.xml the replication config directive containing the cache name to be used:
<jboss-web>
<replication-config>
<cache-name>web.dist</cache-name>
</replication-config>
</joboss-web>
The previous configuration should obviously reference a cache defined in the main configuration file:
<cache-container name="web"default-cache="repl">
<alias>standard-session-cache</alias>
<distributed-cache mode="ASYNC" name="web.dist"batching="true">
<locking isolation ="REPEATABLE_READ"/>
<file-store/>
</distributed-cache>
</cache-container>
Our work-support plans provide precise options as per your project tasks. Whether you are a newbie or an experienced professional seeking assistance in completing project tasks, we are here with the following plans to meet your custom needs:
Name | Dates | |
---|---|---|
JBoss Training | Dec 24 to Jan 08 | View Details |
JBoss Training | Dec 28 to Jan 12 | View Details |
JBoss Training | Dec 31 to Jan 15 | View Details |
JBoss Training | Jan 04 to Jan 19 | View Details |
Ravindra Savaram is a Technical Lead at Mindmajix.com. His passion lies in writing articles on the most popular IT platforms including Machine learning, DevOps, Data Science, Artificial Intelligence, RPA, Deep Learning, and so on. You can stay up to date on all these technologies by following him on LinkedIn and Twitter.