JBoss.org Community Documentation
In order to store an object in POJO Cache, it must be either instrumented or made serializable. Instrumentation is the most optimal approach since it preserves object identity and provides field granular replication. POJO Cache currently uses the JBoss AOP project to provide instrumentation, so the same processes described in the AOP documentation are used with POJO Cache.
The primary input to JBoss AOP is the AOP binding file, which is
responsible for specifying which classes should be instrumented.
POJO Cache provides a binding file,
pojocache-aop.xml
, which matches all classes that have been annotated with the
@Replicable
annotation. Advanced users may choose to alter this definition to
instrument classes in other various interesting ways. However, it is
recommended to just stick with the default annotation binding.
The instrumentation process can be executed at either load-time, or
compile-time. Load-time instrumentation uses a Java agent to
intercept and modify classes as they are loaded; whereas
compile-time instrumentation requires running
aopc
as part of the compilation process.
Load-time is the recommended approach, since compile-time instrumentation adds hard dependencies to the weaved bytecode which ties the output to a particular version of JBoss AOP.
Load-time instrumentation uses a Java agent to intercept all classes loaded by the JVM. As they are loaded JBoss AOP instruments them, allowing POJO Cache to monitor field changes. To enable load time instrumentation the JVM must be started with the following specified:
The
jboss.aop.path
system property set to the location of
pojocache-aop.xml
A javaagent argument which includes jboss-aop-jdk50.jar
These requirements lead to the following example ant task:
<java classname="Foo" fork="yes">
<jvmarg value="-javaagent:lib/jboss-aop.jar"/>
<jvmarg value="-Djboss.aop.path=etc/META-INF/pojocache-aop.xml"/>
<classpath refid="test.classpath"/>
</java>
There is also a pojo-run command line script in the POJO Cache distribution that passes the proper arguments to the JVM for you.
$ pojo-run -classpath myclasses org.foo.Bar
Once the JVM is executed in this manner, any class with the
@Replicable
annotation will be instrumented when it is loaded.
While load-time is the preferred approach, it is also possible to instrument classes at compile-time. To do this, the aopc tool is used, with the following requirements:
The
aoppath
option must point to the location of pojocache-aop.xml
The
src
option must point to the location of your class files that are
to be instrumented. This is typically the output folder of a
javac
run.
The following is an example ant task which performs compile-time instrumentation:
<taskdef name="aopc" classname="org.jboss.aop.ant.AopC" classpathref="aop.classpath"/>
<target name="aopc" depends="compile" description="Precompile aop class">
<aopc compilerclasspathref="aop.classpath" verbose="true">
<src path="${build}"/>
<include name="org/jboss/cache/aop/test/**/*.class"/>
<aoppath path="${output}/resources/pojocache-aop.xml"/>
<classpath path="${build}"/>
<classpath refid="lib.classpath"/>
</aopc>
</target>
In this example, once the aopc target is executed the classes in the build directory are modified. They can then be packaged in a jar and loaded using the normal Java mechanisms.
The advanced user might decide to alter the provided AOP
descriptor. In order to do this, it is important to understand the
reasons behind what is provided, and what is required by POJO
Cache. Previous sections have mentioned that any class with the
@Replicable
annotation will be instrumented. This happens, because the
provided AOP descriptor,
pojocache-aop.xml
, has a prepare statement which matches any class (or subclass)
using the annotation. This is shown in the following snippet:
<prepare expr="field(* $instanceof{@org.jboss.cache.pojo.annotation.Replicable}->*)"/>
More specifically, any code which accesses a field on a class
which has been annotated with
@Replicable
, will be instrumented: The "field" pointcut in the expression
matches both read and write operations. The wildcard "*" indicates
that all java protection modes are intercepted (private, package,
protected, public). The
$instanceof
expression refers to any annotation that subclasses
@Replicable
. Finally, the ending wildcard allows the matched field to have
any name.