Version 8

    FIELD Level Session Replication

    by Ben Wang, Brian Stansberry and Galder Zamarreno

     

    FIELD level session replication is a new feature that will be supported in JBoss 4.0.4 (starting in CR2 actually).  It allows the use of the feature of PojoCache (formerly known as TreeCacheAop) to monitor changes to the individuals fields in POJOs you place in a "HttpSession" object. Only the changed fields will be replicated around the cluster.

     

    In this wiki page, we will go through brief introduction of PojoCache and JBoss Aop that provide the enabling framework. Next we will discuss the configuration and how to use it. We will also try to provide a guideline on when to use FIELD level session replication granularity. Finally, we supply a couple of example tutorials that guide you through step by step.

     

    PojoCache introduction

     

    PojoCache is a key component of JBoss Cache. It is an object-oriented, transactional and distributed cache system that can handle object relationship during serialization (e.g., replication and/or persistence), and has fine-grained field-level replication that is transparent to the caller.

     

    It has APIs like putObject(), getObject(), removeObject(), and findObjects() to attach, retrieve, detach, and query your POJO to the cache system, respectively.

     

    We have used PojoCache to implement the current FIELD-level http session replication.

     

    Again full JBoss Cache documentation can be found here.

     

    JBoss Aop introduction

     

    Aspect-Oriented Programming (AOP) is a new paradigm that allows you to organize and layer your software applications in ways that are impossible with traditional object-oriented approaches. Aspects allow you to transparently glue functionality together so that you can have a more layered design. AOP allows you to intercept any event in a Java program and trigger functionality based on those events. Combined with JDK 5.0 annotations, it allows you to extend the Java language with new syntax.

     

    JBoss AOP is a 100% Pure Java aspected oriented framework usable in any programming environment or tightly integrated with our application server.

     

    JBoss Aop is used by PojoCache underneath to perform dynamic interception of field access. As a result, your POJO will need to be prepared for use by JBoss Aop.

     

    Full documentation can be found here.

     

    What should I do with my POJO (plain old Java object)?

     

    In order for you to use FIELD-level session replication, here are the steps to prepare and use your POJO: Prepare, Instrument, and Usage.

     

    If you're using AS 4.0.4.x, you can only use JDK 1.4 style (javadoc) annotation require a pre-processing step. (A full example is attached at the end of this page.). In AS 4.0.5.GA, you either use JDK1.4 style (javadoc) annotation or JDK50 annotations. From AS/EAP 4.2, as JDK50 is only supported, you can only use JDK 5.0 annotations. (A full example is attached at the end of this page.)

     

    The prepare section that follows is split in two categories, depending on the type of annotations used.

     

    Prepare - JDK 1.4 style (javadoc) annotation

     

    You can "prepare" your POJO either through annotation or xml (via jboss-aop.xml). We recommend you to use annotation since it provides you flexibility without worrying about the underlying JBoss Aop syntax. As a result, we will only explain the annotation step. If you prefer the xml step, please refer to PojoCache documentation for details.

     

    To annotate your POJO, we provide two annotations: @@org.jboss.web.tomcat.tc5.session.AopMarker and @@org.jboss.web.tomcat.tc5.session.InstanceAopMarker. When you annotate your POJO with AopMarker, you indicate that this POJO will be used in FIELD-level replication. Note that because there is no formal annotation defined in JDK 1.4, you will need to annotate it inside the class JavaDoc section. For example,

    /*
     * My usual comments here first.
     * @@org.jboss.web.tomcat.tc5.session.AopMarker
     */
    public class Address 
    {
    ...
    }
    

     

    If you annotate it with InstanceAopMarker instead, then all of its subclasses (or all of its implementing classes, if it is an interface) will be automatically annotated as well. For example,

    /*
     *
     * @@org.jboss.web.tomcat.tc5.session.InstanceOfAopMarker
     */
    public class Person 
    {
    ...
    }
    

    then when you have a sub-class like

    public class Student extends Person
    {
    ...
    }
    

    there will be no need to annotate Student. It will be annotated automatically because it is a sub-class of Person.

     

    Once you have annotated your classes with these xdoclet-style annotations, you need to run a special pre-compiler called annoc on your classes. For usage of the Ant annoc target, please refer to JDK 1.4 example with AS 4.0.x.

     

    Prepare - JDK 5.0 annotation

     

    You can "prepare" your POJO either through annotation or xml (via jboss-aop.xml). We recommend you to use annotation since it provides you flexibility without worrying about the underlying JBoss Aop syntax. As a result, we will only explain the annotation step. If you prefer the xml step, please refer to PojoCache documentation for details.

     

    To annotate your POJO, we provide two annotations: @org.jboss.cache.aop.annotation.PojoCacheable and @org.jboss.cache.aop.annotation.InstanceOfPojoCacheable. When you annotate your POJO PojoCacheable, you indicate that this POJO will be used in FIELD-level replication. For example,

    /*
     * My usual comments here first.
     */
    @org.jboss.cache.aop.annotation.PojoCacheable
    public class Address 
    {
    ...
    }
    

     

    If you annotate it with InstanceOfPojoCacheable instead, then all of its subclasses (or all of its implementing classes, if it is an interface) will be automatically annotated as well. For example,

    /*
     * My comments
     */
    @org.jboss.cache.aop.annotation.InstanceOfPojoCacheable
    public class Person 
    {
    ...
    }
    

    then when you have a sub-class like

    public class Student extends Person
    {
    ...
    }
    

    there will be no need to annotate Student. It will be annotated automatically because it is a sub-class of Person.

     

    There's no need to do any pre-processing with JDK 5.0 annotations as shown in JDK 5.0 with AS/EAP 4.2 example.

     

    Instrumentation

     

    In JBoss Aop, there are two modes of instrumentation (to bytecode manipulate your POJO class):

     

    • compile-time. You use a so-called aop precompiler (aopc) to pre-process your POJO class files.

     

    • load-time. You use a special system class loader so the bytecodes are manipulated at load time.

     

    In general, we recommend using aopc to pre-process your classes first so we won't focus on the load time configuration.  For more on that, see the JBoss Aop documentation.

     

    For usage of the Ant aopc targets, please refer to the attached JDK 1.4 example with AS 4.0.x or JDK 5.0 with AS/EAP 4.2 example.

     

    To help make it easier to use annoc and aopc in your own builds, the example uses an Ant script PojoCacheTasks.xml that is an independent declaration of the annoc and aopc targets.  A copy of this file can be directly imported into to your project's build using the Ant <import/> task. Take a look at the example's build.xml  to see how this can be used.

     

    Use it

     

    Here is a code snippet to use your POJO.

    // Do this only once. So this can be in init(), e.g.
    if(firstTime)
    {
      Person joe = new Person("Joe", 40);
      Person mary = new Person("Mary", 30);
      Address addr = new Address();
      addr.setZip(94086);
    
      joe.setAddress(addr);
      mary.setAddress(addr); // joe and mary share the same address!
    
      session.setAttribute("joe", joe); // that's it.
      session.setAttribute("mary", mary); // that's it.
    }
    
    Person mary = (Person)session.getAttribute("mary");
    mary.getAddress().setZip(95123); // this will update and replicate the zip code.
    

     

    Configurations - JDK1.4 style (javadoc) annotation - AS 4.0.x

     

    To do FIELD level replication, there are couple of new configurations.

     

    • tc5-cluster-service.xml file has been replaced with a new tc5-cluster.sar.  The SAR is in exploded format (i.e. not zipped) so you can easily access/update its internals.

     

    • Configurations previously done in tc5-cluster-service.xml (e.g. choosing REPL_SYNC or configuring JGroups) are now done in tc5-cluster.sar/META-INF/jboss-service.xml.  In 4.0.4, this file has been updated with the following changes:

      • TreeCacheAop mbean. We have used org.jboss.cache.TreeCacheAop (internal PojoCache implementation class) mbean instead of plain cache one org.jboss.cache.TreeCache.

      • useMarshalling. Indicates whether to the cache should unmarshall objects replicated from other cluster nodes, or store them internally as a byte{FOOTNOTE DEF  } until a web app requests them.  TreeCache default is "false", must be "true" if session replication granularity "FIELD" is used.

      • inactiveOnStartup. Whether or not the entire tree is inactive upon startup, only responding to replication messages after activateRegion() is called to activate one or more parts of the tree when a webapp is deployed.  Must be "true" if useMarshalling" is "true".

      • TransactionManagerLookupClass You will need to use org.jboss.cache.BatchModeTransactionManagerLookup here. Note that you still can use JTA transaction inside your web app. This simply tells PojoCache not to participate in your JTA-specific transaction.

     

    • tc5-cluster.aop. This is a JBoss Aop deployment package for FIELD-level replication. It contains the annotation interfaces and declaraton. Need to make sure that you include it in your JBoss config (it's there as part of the standard all config in the tc5-cluster.sar.) But simply treat it as a library deployment. There is no need to modify it.

     

    • jboss-web.xml. This is your web app JBoss specific xml. Two options that are related here.

      • replication-granularity. You should specify this as "FIELD".

      • replication-field-batch-mode. Indicate whether you want to have batch the replication of field-level changes to the cluster so there is just one replication per http request. Default is true; no need to add this element if the default is acceptable.

     

    • Dependency on AspectDeployer. The annotation interfaces in tc5-cluster.aop as well as the org.jboss.cache.TreeCacheAop class depend on the jboss-aop.deployer or the jboss-aop-jdk50.deployer being available.  This deployer is included as part of the all configuration.

     

    Configurations - JDK50 annotation - AS/EAP 4.2+

     

    To do FIELD level replication, there are couple of new configurations.

     

    • tc5-cluster.sar directory has been replaced with a new jboss-web-cluster.sar.  The SAR is still in exploded format (i.e. not zipped) so you can easily access/update its internals.

     

    • Configurations previously done in tc5-cluster.sar/META-INF/jboss-service.xml (e.g. choosing REPL_SYNC or configuring JGroups) are now done in jboss-web-cluster.sar/META-INF/jboss-service.xml.  To use FIELD level replication, please make sure you modify the following parameters:

      • UseRegionBasedMarshalling. Indicates whether to the cache should unmarshall objects replicated from other cluster nodes, or store them internally as a byte{FOOTNOTE DEF  } until a web app requests them.  TreeCache default is "false", must be "true" if session replication granularity "FIELD" is used.

      • InactiveOnStartup. Whether or not the entire tree is inactive upon startup, only responding to replication messages after activateRegion() is called to activate one or more parts of the tree when a webapp is deployed.  Must be "true" if UseRegionBasedMarshalling is "true".

     

    • jboss-web-cluster.aop. This is a JBoss Aop deployment package for FIELD-level replication. It contains the annotation interfaces and declaraton. Need to make sure that you include it in your JBoss config (it's there as part of the standard all config in the jboss-web-cluster.sar.) But simply treat it as a library deployment. There is no need to modify it.

     

    • jboss-web.xml. This is your web app JBoss specific xml. Two options that are related here.

      • replication-granularity. You should specify this as "FIELD".

      • replication-field-batch-mode. Indicate whether you want to have batch the replication of field-level changes to the cluster so there is just one replication per http request. Default is true; no need to add this element if the default is acceptable.

     

    • Dependency on AspectDeployer. The annotation interfaces in jboss-web-cluster.aop as well as the org.jboss.cache.TreeCacheAop class depend on the jboss-aop-jdk50.deployer being available.  This deployer is included as part of the all configuration.

     

    How do I use Collection classes?

    You can use straight Collection classes in your session code without preparing them first. PojoCache will simply replace your collections with a proxy so it can interact with the underlying cache store. The one key thing to be aware of is if you assign a collection to a session attribute, you need to call getAttribute() to get a reference to the proxy before making any further changes.  If you hold a reference to the original collection and then change it, those changes will not be reflected in the session or replicated.

    //

    Below is a code snippet showing use of a Collection:

    // Do this only once.
    if(firstTime)
    {
      Person joe = new Person("Joe", 40);
      Person mary = new Person("Mary", 30);
    
      List list = new ArrayList();
      list.add(joe);
      list.add(mary);
    
      session.setAttribute("myList", list); // that's it.
    }
    
    Person ben = new Person("Ben", 20);
    List list = (List)session.getAttribute("myList"); // this will return a proxy
    list.add(ben); // this will be replicated automatically
    Person joe = (Person)list.get(0);
    joe.setAge(50); // so is this!
    

     

    Note however, currently there are restrictions placed on the PojoCache Collection classes. Please see the PojoCache FAQ for more details.

     

    Troubleshooting

    • How do I know if it is working?

      • Verifying that FIELD level fine-grained replication is working properly in a development environment is straightforward. Since we assume that you won't be doing session.setAttribute() for each http request (see Guideline section below for this assumption), if you modify a POJO it should show up in the replicated JBoss instance. So you can always failover to retrieve to verify that it is working properly.

     

    • What happens if it is not working?

      • Please make sure that you can run the example attached here first.

      • Check that your class has been instrumented. Two steps here assuming you are using annoc and aopc.

        • annoc. After you issue this target, you should check the time stamp of your POJO class to see it they have been modified. JBoss Aop will insert some metadata in the POJO class file. You can also check the output as well. If you don't see it, it is probably because your class path is not specified correctly.

        • aopc. After this target is completed, you should see many extra class files generated by JBoss Aop. You can verify it from the output. Again, if you don't see the extra class files, mostly likely, your class path is not set correctly.

      • look for any error log (like not "aspectized") in server.log

      • You can use the public TreeCacheAop MBean API:

        • Use the public JMX MBean API findObjects(String fqn) to query the objects (returned in Map) located under the fqn. You can do this either through JMX console or the JMX command line command, e.g., twiddle.sh. To find a web app specific POJOs, you will need to supply the fqn like JSESSION/yourHost/yourWebName. For example, in my test environment for the example attached here, I use fqn like JSESSION/localhost/test-http-scoped-FIELD or JSESSION/localhost/test-http-scoped-FIELD-50, depending on the example version. You can drill down to a particular session id as well. This will return the top-level POJOs (no embedded ones) in toString(). You can then check whether it has been replicated or not.

        

    Usage guideline

    You should consider using FIELD-level because:

    • FIELD-level fine-grained replication can have potential performance gain if your POJO is big (and thus your session size) and the changes are fine-grained, e.g., only to some selected fields. This also applies for example if you store a big list of POJOs in your session.

    • POJO can posses object relationship, e.g., multiple referenced. Distributed PojoCache will handle this transparently for you.

     

    • you want transparency in replication changes. Traditionally, you need to perform session.setAttribute() to trigger the replication changes (or via trigger option). But using FIELD-level, you don't need to track your changes.

     

    And here are some cases that you may not want to use FIELD level:

    • You have simple and small POJOs. Your POJO is small in size and also there is no object relationship, then PojoCache possess not clear advantage to plain cache because of its extra overhead.

    • Your application is bounded by memory usage. Because PojoCache need almost twice as much of memory (the original POJO in-memory space and also the additional cache store for the primitive fields), you may not want to use FIELD level.

    • Your POJO lifetime is short. That is, you need to create and destroy your POJO often (e.g., between each http request). Then the replication layer needs to do "putObject" and "removeObject" often, it will be slow in performance.

     

    Examples

     

    There're two examples currently available:

     

    • An full example using JDK 1.4 (javadoc) annotations to be run with AS 4.0.4.GA or 4.0.5.GA is available from JDK 1.4 example with AS 4.0.x that serves as a tutorial on how to use your POJOs, deploy it, and validate it.

    • An full example using JDK 5.0 annotations to be run with AS/EAP 4.2+ is available from JDK 5.0 with AS/EAP 4.2 example that serves as a tutorial on how to use your POJOs, deploy it, and validate it.

     

     

    Problem

     

    Please report problems to the [Clustering user forum|

    http://www.jboss.com/index.html?module=bb&op=viewforum&f=64]

     

     

     

    Referenced by: