Ben Wang, ben.wang@jboss.org
Bela Ban, bela@jboss.org
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.
Here are the current features supported:
TreeCache/Aop configuration xml file. Please
see the documentation of TreeCache for
details.POJO has a reference to another advised
POJO, TreeCacheAop will transparently
manage the sub-object states as well. During the initial putObject(...)
call, TreeCacheAop will traverse the object tree and map
it accordingly to the internal TreeCache nodes. This
feature can best be examined through the tutorial.TreeCacheAop , a replication request will be
sent out only when any attribute is modified and only the node
corresponds to that modified attribute. This greatly reduces the
overhead and
communication of the underlying replication process.List, Set, and Map
based objects automatically without declaring them as aop-enabled. That
is, you can use them either as a plain POJO or a
sub-object to POJO without declaring them as advisable.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:
jboss-aop.jar, trove.jar,
and javassist.jar-Djava.system.class.loader=org.jboss.aop.standalone.SystemClassLoader.There are 3 additional APIs for TreeCacheAop:
Object putObject(String fqn, Object pojo) where fqn
is a user-specified fully qualified name (FQN) to store the node in TreeCache,
e.g., "/aop/joe", and pojo is the object
instance to be managed by TreeCacheAop. This call returns
the existing object under fqn, as a result, a successful
call will replace that old value with pojo instance. Note
that a user will only need to issue this call once for each pojo.
Once it is issued, TreeCacheAop will assign an
interceptor for the pojo instance and its sub-objects.Object getObject(String fqn). This call will return
the current object content located under fqn. This is
used mostly when you start a replicated node and you want to get the
object reference.Object removeObject(String fqn). This call will
remove the contents under fqn and return the POJO
instance stored there (null if it doesn't exist). Note
this call will also remove everything stored under fqn.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>
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;
}
...
}
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.
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);
Here are some of the current limitation in TreeCacheAop.
TreeCache and TreeCacheAop
can share the same fqn name, i.e., the same node. However, if you do
remove the node, you will remove any contents associated with that
nodes, say, both remove(String fqn) and removeObject(String
fqn, Object pojo) method calls. Both method calls currently do
not differentiate the content type. This limit will be removed in the
future release.