Author: jason.greene(a)jboss.com
Date: 2008-08-21 20:15:38 -0400 (Thu, 21 Aug 2008)
New Revision: 6596
Modified:
pojo/branches/2.2/src/main/docbook/userguide/en/master.xml
pojo/branches/2.2/src/main/docbook/userguide/en/modules/appendix.xml
pojo/branches/2.2/src/main/docbook/userguide/en/modules/architecture.xml
Log:
Update docs
Add array section
Modified: pojo/branches/2.2/src/main/docbook/userguide/en/master.xml
===================================================================
--- pojo/branches/2.2/src/main/docbook/userguide/en/master.xml 2008-08-21 19:21:04 UTC
(rev 6595)
+++ pojo/branches/2.2/src/main/docbook/userguide/en/master.xml 2008-08-22 00:15:38 UTC
(rev 6596)
@@ -18,8 +18,8 @@
<bookinfo>
<title>POJO Cache</title>
<subtitle>User Documentation</subtitle>
- <releaseinfo>Release 2.1.0.GA</releaseinfo>
- <pubdate>March 2008</pubdate>
+ <releaseinfo>Release 2.2.0.GA</releaseinfo>
+ <pubdate>October 2008</pubdate>
<author>
<firstname>Ben</firstname>
Modified: pojo/branches/2.2/src/main/docbook/userguide/en/modules/appendix.xml
===================================================================
--- pojo/branches/2.2/src/main/docbook/userguide/en/modules/appendix.xml 2008-08-21
19:21:04 UTC (rev 6595)
+++ pojo/branches/2.2/src/main/docbook/userguide/en/modules/appendix.xml 2008-08-22
00:15:38 UTC (rev 6596)
@@ -161,149 +161,29 @@
<title>PojoCache configuration xml</title>
<para>Attached is a full listing for
<literal>pojocache-aop.xml</literal>.</para>
<programlisting role="XML"><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- This is the PojoCache configuration file that specifies:
- 1. Interceptor stack for API
- 2. Annotation binding for POJO (via "prepare" element)
+<aop>
+ <!-- If a POJO has a Replicable annotation, it will be asepectized. -->
- Basically, this is a variant of jboss-aop.xml. Note that
- except for the customization of interceptor stack, you should
- not need to modify this file.
-
- To run PojoCache, you will need to define a system property:
- jboss.aop.path that contains the path to this file such that JBoss Aop
- can locate it.
+ <!--
+ Supports inheritance and polymorphism. It can either be a concrete class
+ or an interface. All sub-classes or interface implementors will be instrumeneted.
-->
- <aop>
+ <prepare expr="field(*
$instanceof{(a)org.jboss.cache.pojo.annotation.Replicable}->*)" />
- <!--
- This defines the PojoCache 2.0 interceptor stack. Unless necessary, don't
modify the stack here!
- -->
+ <!-- Work around that ensures annotated classes which do not access fields are
instrumented -->
+ <introduction
expr="class($instanceof{(a)org.jboss.cache.pojo.annotation.Replicable})"/>
- <!-- Check id range validity -->
- <interceptor name="CheckId"
class="org.jboss.cache.pojo.interceptors.CheckIdInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Track Tx undo operation -->
- <interceptor name="Undo"
class="org.jboss.cache.pojo.interceptors.PojoTxUndoInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Begining of interceptor chain -->
- <interceptor name="Start"
class="org.jboss.cache.pojo.interceptors.PojoBeginInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Check if we need a local tx for batch processing -->
- <interceptor name="Tx"
class="org.jboss.cache.pojo.interceptors.PojoTxInterceptor"
- scope="PER_INSTANCE"/>
-
- <!--
- Mockup failed tx for testing. You will need to set
PojoFailedTxMockupInterceptor.setRollback(true)
- to activate it.
- -->
- <interceptor name="MockupTx"
class="org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Perform parent level node locking -->
- <interceptor name="TxLock"
class="org.jboss.cache.pojo.interceptors.PojoTxLockInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Interceptor to perform Pojo level rollback -->
- <interceptor name="TxUndo"
class="org.jboss.cache.pojo.interceptors.PojoTxUndoSynchronizationInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Interceptor to used to check recursive field interception. -->
- <interceptor name="Reentrant"
class="org.jboss.cache.pojo.interceptors.MethodReentrancyStopperInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Whether to allow non-serializable pojo. Default is false. -->
- <interceptor name="MarshallNonSerializable"
-
class="org.jboss.cache.pojo.interceptors.CheckNonSerializableInterceptor"
- scope="PER_INSTANCE">
- <attribute
name="marshallNonSerializable">false</attribute>
- </interceptor>
-
- <!-- This defines the stack macro -->
- <stack name="Attach">
- <interceptor-ref name="Start"/>
- <interceptor-ref name="CheckId"/>
- <interceptor-ref name="MarshallNonSerializable"/>
- <interceptor-ref name="Tx"/>
- <!-- NOTE: You can comment this out during production although leaving it
here is OK. -->
- <interceptor-ref name="MockupTx"/>
- <interceptor-ref name="TxLock"/>
- <interceptor-ref name="TxUndo"/>
- </stack>
-
- <stack name="Detach">
- <interceptor-ref name="Start"/>
- <interceptor-ref name="CheckId"/>
- <interceptor-ref name="Tx"/>
- <!-- NOTE: You can comment this out during production although leaving it
here is OK. -->
- <interceptor-ref name="MockupTx"/>
- <interceptor-ref name="TxLock"/>
- <interceptor-ref name="TxUndo"/>
- </stack>
-
- <stack name="Find">
- <interceptor-ref name="Start"/>
- <interceptor-ref name="CheckId"/>
- </stack>
-
- <!--
- The following section should be READ-ONLY!! It defines the annotation binding to
the stack.
- -->
-
- <!-- This binds the jointpoint to specific in-memory operations. Currently in
PojoUtil. -->
- <bind pointcut="execution(*
- @org.jboss.cache.pojo.annotation.Reentrant->toString())">
- <interceptor-ref name="Reentrant"/>
- </bind>
-
- <bind pointcut="execution(*
-
org.jboss.cache.pojo.PojoUtil->@org.jboss.cache.pojo.annotation.TxUndo(..))">
- <interceptor-ref name="Undo"/>
- </bind>
-
- <bind pointcut="execution(*
org.jboss.cache.pojo.impl.PojoCacheImpl->@org.jboss.cache.pojo.annotation.Attach(..))">
- <stack-ref name="Attach"/>
- </bind>
-
- <bind pointcut="execution(*
org.jboss.cache.pojo.impl.PojoCacheImpl->@org.jboss.cache.pojo.annotation.Detach(..))">
- <stack-ref name="Detach"/>
- </bind>
-
- <bind pointcut="execution(*
org.jboss.cache.pojo.impl.PojoCacheImpl->@org.jboss.cache.pojo.annotation.Find(..))">
- <stack-ref name="Find"/>
- </bind>
-
-
- <!--
- Following is declaration for JDK50 annotation. You use the specific annotation
on your
- POJO such that it can be instrumented. Idea is user will then need only to
annotate like:
- @org.jboss.cache.pojo.annotation.Replicable
- in his POJO. There will be no need of jboss-aop.xml from user's side.
- -->
-
- <!-- If a POJO has PojoCachable annotation, it will be asepctized. -->
- <prepare expr="field(*
$instanceof{(a)org.jboss.cache.pojo.annotation.Replicable}->*)" />
-
- <!-- Observer and Observable to monitor field modification -->
- <bind pointcut="
- set(* $instanceof{(a)org.jboss.cache.pojo.annotation.Replicable}->*)
- ">
- <interceptor
class="org.jboss.cache.pojo.observable.SubjectInterceptor"/>
- </bind>
-
- <introduction
class="$instanceof{(a)org.jboss.cache.pojo.annotation.Replicable}">
- <mixin>
- <interfaces>org.jboss.cache.pojo.observable.Subject</interfaces>
- <class>org.jboss.cache.pojo.observable.SubjectImpl</class>
- <construction>new
org.jboss.cache.pojo.observable.SubjectImpl(this)</construction>
- </mixin>
- </introduction>
- </aop>
-
+ <!-- Array support -->
+ <!-- Comment entire section to disable -->
+ <arrayreplacement
expr="class($instanceof{(a)org.jboss.cache.pojo.annotation.Replicable})"/>
+ <interceptor name="pojocache-array"
class="org.jboss.cache.pojo.interceptors.dynamic.ArrayInterceptor"/>
+ <introduction
expr="class($instanceof{(a)org.jboss.cache.pojo.annotation.Replicable})">
+ <interfaces>org.jboss.cache.pojo.impl.ArrayInterceptable</interfaces>
+ </introduction>
+ <arraybind name="pojocache-array" type="READ_WRITE">
+ <interceptor-ref name="pojocache-array"/>
+ </arraybind>
+</aop>
]]></programlisting>
</sect1>
</chapter>
Modified: pojo/branches/2.2/src/main/docbook/userguide/en/modules/architecture.xml
===================================================================
--- pojo/branches/2.2/src/main/docbook/userguide/en/modules/architecture.xml 2008-08-21
19:21:04 UTC (rev 6595)
+++ pojo/branches/2.2/src/main/docbook/userguide/en/modules/architecture.xml 2008-08-22
00:15:38 UTC (rev 6596)
@@ -19,86 +19,6 @@
</mediaobject>
</figure>
- <sect1>
- <title>POJO Cache interceptor stack</title>
-
- <para>As mentioned, the JBoss Aop framework is used to provide a configurable
interceptor stack.
- In the current implementation, the main POJO Cache methods have their own
independant stack. These are specified in
<literal>META-INF/pojocache-aop.xml</literal>
- In most cases, this file should be left alone, although advanced users may wish
to add their own interceptors.
- The Following is the default configuration:</para>
-<programlisting role="XML"><![CDATA[
- <!-- Check id range validity -->
- <interceptor name="CheckId"
class="org.jboss.cache.pojo.interceptors.CheckIdInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Track Tx undo operation -->
- <interceptor name="Undo"
class="org.jboss.cache.pojo.interceptors.PojoTxUndoInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Begining of interceptor chain -->
- <interceptor name="Start"
class="org.jboss.cache.pojo.interceptors.PojoBeginInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Check if we need a local tx for batch processing -->
- <interceptor name="Tx"
class="org.jboss.cache.pojo.interceptors.PojoTxInterceptor"
- scope="PER_INSTANCE"/>
-
- <!--
- Mockup failed tx for testing. You will need to set
PojoFailedTxMockupInterceptor.setRollback(true)
- to activate it.
- -->
- <interceptor name="MockupTx"
class="org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Perform parent level node locking -->
- <interceptor name="TxLock"
class="org.jboss.cache.pojo.interceptors.PojoTxLockInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Interceptor to perform Pojo level rollback -->
- <interceptor name="TxUndo"
class="org.jboss.cache.pojo.interceptors.PojoTxUndoSynchronizationInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Interceptor to used to check recursive field interception. -->
- <interceptor name="Reentrant"
class="org.jboss.cache.pojo.interceptors.MethodReentrancyStopperInterceptor"
- scope="PER_INSTANCE"/>
-
- <!-- Whether to allow non-serializable pojo. Default is false. -->
- <interceptor name="MarshallNonSerializable"
class="org.jboss.cache.pojo.interceptors.CheckNonSerializableInterceptor"
- scope="PER_INSTANCE">
- <attribute
name="marshallNonSerializable">false</attribute>
- </interceptor>
-
- <stack name="Attach">
- <interceptor-ref name="Start"/>
- <interceptor-ref name="CheckId"/>
- <interceptor-ref name="Tx"/>
- <interceptor-ref name="TxLock"/>
- <interceptor-ref name="TxUndo"/>
- </stack>
-
- <stack name="Detach">
- <interceptor-ref name="Start"/>
- <interceptor-ref name="CheckId"/>
- <interceptor-ref name="Tx"/>
- <interceptor-ref name="TxLock"/>
- <interceptor-ref name="TxUndo"/>
- </stack>
-
- <stack name="Find">
- <interceptor-ref name="Start"/>
- <interceptor-ref name="CheckId"/>
- </stack>
-]]></programlisting>
-<para>
- The stack should be self-explanatory. For example, for the
<literal>Attach</literal> stack,
- we currently have <literal>Start, CheckId, Tx, TxLock</literal>,
and
- <literal>TxUndo</literal> interceptors. The stack always starts with
a
- <literal>Start</literal> interceptor such that initialization can be
done properly.
- <literal>CheckId</literal> is to ensure the validity of the Id
(e.g., it didn't use any internal
- Id string). Finally, <literal>Tx, TxLock</literal>, and
<literal>TxUndo</literal> are handling the
- the proper transaction locking and rollback behavior (if needed).
-</para>
- </sect1>
<sect1>
<title>Field interception</title>
@@ -116,7 +36,7 @@
All access qualifiers are intercepted. In other words, all
<literal>private</literal>, all <literal>protected</literal>, all
default, and all <literal>public</literal> fields will be intercepted.
</listitem>
<listitem>
- Any field with <literal>final</literal>,
<literal>static</literal>, and/or <literal>transient</literal>
qualifiers, <emphasis role="bold">will be skipped</emphasis>.
Therefore, they will not be replicated, passivated, or manipulated in any way by POJO
Cache.
+ Any field with <literal>static</literal>, and/or
<literal>transient</literal> qualifiers, <emphasis
role="bold">will be skipped</emphasis>. Therefore, they will not be
replicated, passivated, or manipulated in any way by POJO Cache.
</listitem>
</itemizedlist>
</para>
@@ -416,12 +336,9 @@
</listitem>
</itemizedlist>
- The drawback to this approach is that the calling application must re-get any
collection references that were attached. Otherwise,
- the cache will not be aware of future changes. If the collection is
referenced from another object, then the calling app can obtain
- the proxy by using the publishing mechanism provided by the object (e.g.
Person.getHobbies()).
-
- If, however, the collection is directly attached to the cache, then a
subsequent <literal>find()</literal> call will need to be made
- to retrieve the proxy.
+ The drawback to this approach is that the calling application must re-get any
collection references that were directly attached. Otherwise,
+ the cache will not be aware of future changes. However, if the collection is
referenced from an attached object, then this is transparently
+ handled. More specifically, the attached object will see the proxy instead of
the original.
</para>
<para>The following code snippet illustrates obtaining a direct Collection
proxy reference:
@@ -486,4 +403,51 @@
</itemizedlist>
</sect2>
</sect1>
+ <sect1>
+ <title>Array Mapping</title>
+
+ <para>As of 2.2, array fields of any attached object are updated
transparently, provided that the array
+ is written/read from a class marked with
<literal>@Replicable</literal>. If this is the case, only
+ the indexes of the array that are modified are replicated. However, if the
array is passed externally
+ to a class that is not marked as <literal>@Replicable</literal>,
then the changes will not be noticed. For this
+ reason, it is recommended to abstract access to the array where possible
(i.e. setItem(item, index)).
+ If an external, non-replicable class needs access to the array, then it is
recommended to pass a copy,
+ and add a method to the container object that reapplies the changes. Also,
due to JVM limitations,
+ an array can not be monitored if it is directly attached to the cache (i.e. a
first class object). POJO
+ Cache still allows this, but they are treated as a serializable type. As with
other serializable type,
+ they must be reattached after every change.
+ </para>
+
+ <para>The following code snippet illustrates accessing a replicated array
through abstraction:
+ </para>
+<programlisting role="JAVA"><![CDATA[
+@Replicable public class Team
+{
+ private String[] members = new String[10];
+
+ public String getMember(int index)
+ {
+ return members[index];
+ }
+
+ public void setMember(int index, String member)
+ {
+ members[index] = member;
+ }
+}
+
+public class SomeExternalClass
+{
+ ...
+ public void someMethod()
+ {
+ Team team = new Tesam();
+ cache.attach("/team/1", team);
+
+ team.setMember(0, "John");
+ team.setMember(1, "Joe");
+ }
+}
+]]></programlisting>
+ </sect1>
</chapter>