Ben Wang, ben.wang@jboss.org
Bela Ban, bela@jboss.org
Jboss TreeCacheAop
extends the functionality of TreeCache
to POJO
s (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 POJO
s
(configured in a jboss-aop.xml
file) through plain get/set
methods associated with the POJO
s.
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
POJO
s. 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.