JBoss TreeCacheAop

Ben Wang, ben.wang@jboss.org
Bela Ban, bela@jboss.org


Overview

Jboss TreeCacheAop extends the functionality of TreeCache to POJOs (Plain Old Java Objects) with AOP (Aspect-Oriented Programming)-enabled capability. That is, in addition to the TreeCache basic features such as locking, replication, and transaction, TreeCacheAop also provides transparent object cache retrieval and update for user-specified POJOs (configured in a jboss-aop.xml file) through plain get/set methods associated with the POJOs.

TreeCacheAop employs the JBoss standalone AOP framework in the JBoss4.0 release to perform advice and pointcut. The framework provides declarative semantics (e.g., xml configuration) to advised POJOs. Once it is declared, a user will only need to initiate the transparent cache mechanism on that POJO by issuing a putObject(String fqn, Object pojo) method call first. After that, plain get/set methods from that POJO [e.g., getName(), setName(), etc] will be intercepted by the AOP framework, and the framework will, in turn, invoke the CacheInterceptor that will retrieve or update the object contents from the cache, respectively.

Note that modifications to public fields (or modifications to private fields from inside an object) are supported too.

TreeCacheAop can also be used as a plain TreeCache. For example, if a POJO is not declared aop-enabled, a user will need to use the TreeCache API [e.g., get(String fqn) and set(String fqn, String key, String value)] to manage the cache states. Of course, users will need to consider the extra cost in doing this.

Feature

Here are the current features supported:

Requirement

TreeCacheAop requires the following libraries (in addition to jboss-cache.jar and the required libraries for the plain TreeCache), and specific class loader during start up:

API

There are 3 additional APIs for TreeCacheAop:

Configuration

In addition to the TreeCache configuration xml file, you will also need a META-INF/jboss-aop.xml file located under the class path. JBoss AOP framework will read this file during startup to make necessary byte code manipulation for advice and introduction. You will need to declare any of your POJO to be advisable so that AOP framework knows to start intercepting either method, field, or constructor invocations. The standalone TreeCacheAop package provides an example declaration for the tutorial classes, namely, Person and Address. Detailed class declaration for Person and Address are provided in the next section. But here is the snippet for META-INF/jboss-aop.xml:
<aop>
<advisable class="org.jboss.test.cache.test.standAloneAop.Address"
fieldFilter="ALL" methodFilter="ALL" constructorFilter="ALL"/>

<advisable class="org.jboss.test.cache.test.standAloneAop.Person"
fieldFilter="ALL" methodFilter="ALL" constructorFilter="ALL" />

<introduction-pointcut class="org.jboss.test.cache.test.standAloneAop.Person">
<mixin>
<interfaces>org.jboss.cache.aop.WriteReplaceable</interfaces>
<class>org.jboss.cache.aop.WriteReplacer</class>
<construction>new org.jboss.cache.aop.WriteReplacer(this)</construction>
</mixin>
</introduction-pointcut>
</aop>

Example POJO

The example POJO classes used for TreeCacheAop tutorial are: Person and Address. Here is the snippet of the class definition for Person and Address (note that neither class implements Serializable).

public class Person {
String name=null;
int age=0;
Map hobbies=null;
Address address=null;
Set skills;
List languages;

public String getName() {
return name;
}

public void setName(String name) {
this.name=name;
}
...
}
and
public class Address {
String street=null;
String city=null;
int zip=0;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street=street;
}
...
}

Example usage

The usage of TreeCacheAop is best illustrated with the accompanying tutorial. But here are the example and some comments:
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.aop.TreeCacheAop;
import org.jboss.test.cache.test.standAloneAop.Person;
import org.jboss.test.cache.test.standAloneAop.Address;

tree = new TreeCacheAop();
config = new PropertyConfigurator();
// configure tree cache.
config.configure(tree, "META-INF/replSync-service.xml");
joe = new Person(); // instantiate a Person object named joe
joe.setName("Joe Black");
joe.setAge(31);

addr = new Address(); // instantiate a Address object named addr
addr.setCity("Sunnyvale");
addr.setStreet("123 Albert Ave");
addr.setZip(94086);

joe.setAddress(addr); // set the address reference
tree.start();  // kick start tree cache
tree.putObject("/aop/joe", joe); // add aop sanctioned object (and sub-objects) into cache.
// since it is advisable, use of plain get/set methods will take care of cache contents automatically. joe.setAge(41);

Note that a typical TreeCacheAop usage involves instantiating the TreeCacheAop, configure, and start the instance. Then, a user creates the advisable POJO that will be put into the cache using putObject(...) API.

In addition, TreeCacheAop also supports get/set with parameter type of some Collection classes (i.e., List, Map, and Set). For example, the following code snippet in addition to the above example will trigger TreeCacheAop to manage the states for the Lanugages list as well:
lang = new ArrayList();
lang.add("Ensligh");
lang.add("Mandarin");

joe.setLanguages(lang);

Limitations and Problems

Here are some of the current limitation in TreeCacheAop.