Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Chapter 18. Caching

In almost all enterprise applications, the database is the primary bottleneck, and the least scalable tier of the runtime environment. People from a PHP/Ruby environment will try to tell you that so-called "shared nothing" architectures scale well. While that may be literally true, I don't know of many interesting multi-user applications which can be implemented with no sharing of resources between different nodes of the cluster. What these silly people are really thinking of is a "share nothing except for the database" architecture. Of course, sharing the database is the primary problem with scaling a multi-user application—so the claim that this architecture is highly scalable is absurd, and tells you a lot about the kind of applications that these folks spend most of their time working on.
Almost anything we can possibly do to share the database less often is worth doing.
This calls for a cache. Well, not just one cache. A well designed Seam application will feature a rich, multi-layered caching strategy that impacts every layer of the application:
  • The database, of course, has its own cache. This is super-important, but can't scale like a cache in the application tier.
  • Your ORM solution (Hibernate, or some other JPA implementation) has a second-level cache of data from the database. This is a very powerful capability, but is often misused. In a clustered environment, keeping the data in the cache transactionally consistent across the whole cluster, and with the database, is quite expensive. It makes most sense for data which is shared between many users, and is updated rarely. In traditional stateless architectures, people often try to use the second-level cache for conversational state. This is always bad, and is especially wrong in Seam.
  • The Seam conversation context is a cache of conversational state. Components you put into the conversation context can hold and cache state relating to the current user interaction.
  • In particular, the Seam-managed persistence context (or an extended EJB container-managed persistence context associated with a conversation-scoped stateful session bean) acts as a cache of data that has been read in the current conversation. This cache tends to have a pretty high hitrate! Seam optimizes the replication of Seam-managed persistence contexts in a clustered environment, and there is no requirement for transactional consistency with the database (optimistic locking is sufficient) so you don't need to worry too much about the performance implications of this cache, unless you read thousands of objects into a single persistence context.
  • The application can cache non-transactional state in the Seam application context. State kept in the application context is of course not visible to other nodes in the cluster.
  • The application can cache transactional state using the Seam pojoCache component, which integrates JBossCache into the Seam environment. This state will be visible to other nodes if you run JBoss cache in a clustered mode.
  • Finally, Seam lets you cache rendered fragments of a JSF page. Unlike the ORM second-level cache, this cache is not automatically invalidated when data changes, so you need to write application code to perform explicit invalidation, or set appropriate expiration policies.
For more information about the second-level cache, you'll need to refer to the documentation of your ORM solution, since this is an extremely complex topic. In this section we'll discuss the use of JBossCache directly, via the pojoCache component, or as the page fragment cache, via the <s:cache> control.

18.1. Using JBossCache in Seam

The built-in pojoCache component manages an instance of org.jboss.cache.aop.PojoCache. You can safely put any immutable Java object in the cache, and it will be replicated across the cluster (assuming that replication is enabled). If you want to keep mutable objects in the cache, you'll need to run the JBossCache bytecode preprocessor to ensure that changes to the objects will be automatically detected and replicated.
To use pojoCache, all you need to do is put the JBossCache jars in the classpath, and provide a resource named treecache.xml with an appropriate cache configuration. JBossCache has many scary and confusing configuration settings, so we won't discuss them here. Please refer to the JBossCache documentation for more information.
For an EAR depoyment of Seam, we recommend that the JBossCache jars and configuration go directly into the EAR. Make sure you declare the jars in application.xml.
Now you can inject the cache into any Seam component:
@Name("chatroom")
public class Chatroom {
    @In PojoCache pojoCache;
    
    public void join(String username) {
      try
      {
         Set<String> userList = (Set<String>) pojoCache.get("chatroom", "userList");
         if (userList==null) 
         {
            userList = new HashSet<String>();
            pojoCache.put("chatroom", "userList", userList);
         }
         userList.put(username);
      }
      catch (CacheException ce)
      {
         throw new RuntimeException(ce);
      }
    }
}
If you want to have multiple JBossCache configurations in your application, use components.xml:
<core:pojo-cache name="myCache" cfg-resource-name="myown/cache.xml"/>

 
 
  Published under the terms of the Open Publication License Design by Interspire