Mindmajix

Clustering entities

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”/>
</properties>

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 sharedcache- mode element has five possible values, as indicated in the following table:

Screenshot_13

Screenshot_14

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_query_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:
<property

name=”hibernate.cache.region.factory_class”value=”org.hibernate.cache.infinispan.<property
name=”hibernate.cache.infinispan.cachemanager”value=”java:jboss/infinispan/hibernate”/>
<property
name=”hibernate.transaction.manager_lookup_class”value=”org.hibernate.transaction.<property name=”hibernate.cache.use_second_level_cache”
value=”true”/>
<property name=”hibernate.cache.use_minimal_puts” 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.

Caching entities

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 javax.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 sharedcache- 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.

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 a fine-grained management of caching areas.

Caching queries

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

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 replicationconfig directive containing the cache name to be used:

<jboss-web>
<replication-config>
<cache-name>web.dist</cache-name>
</replication-config>
</jboss-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>


0 Responses on Clustering entities"

Leave a Message

Your email address will not be published. Required fields are marked *

Copy Rights Reserved © Mindmajix.com All rights reserved. Disclaimer.
Course Adviser

Fill your details, course adviser will reach you.