Version 39

    Ben Wang 04-2006 Rev 1


    Ben Wang 06-2006 Rev 2



    This is a proposal for generic POJO clustering using JDK5.0 annotation support.


    Typically, when we talk about POJO clustering, it involves combination of the following aspects:

    • server-side POJO state replication

    • runtime container bridge

      • session context replication (such as timestamp and other contextual information) with integration with POJO state replication

      • clustered client invocation handler

    • client-side remoting framework

      • failover mechanism (unless this is run using HTTP of which fail over is externalized)

      • discovery service


    The first item should be covered by the current clustering annotation while container integration will be vendor specific (e.g., in JBoss case, it will be Microcontainer-specific integration). The client-side configuration of remoting should reside on the client side. Finally, for failover mechanism, we will provide a generic annotation to specify the default failover options (this can also be overriden during runtime via xml).


    Ideally, we'd like to have POJO that is annotated with certain clustering annotations and it can then be run inside any container (e.g., Tomcat NonHttpSession, other flavor of AS such as Weblogic and Websphere, etc.) that is clustering capable.


    Generically, POJO carries two different contexts: stateful and entity. Although from clustering aspect, these two different contexts should be transparent (afterall, both are represented by Java objects). However, since nowaday entity POJO all deals with RDBMS and some form of ORM (object relational mapping) library such as Hibernate. The ORM library usually has its own entity cache solution that maps directly to the DB. Having said that, with some exceptions, we expect the current annotation can be applied to both type of POJOs. Whenever possible, we will explain the exception in the following (such as passivation).


    Finally, please note that for all the annotations proposed here, again we will provide an equivalent external (partial) XML override as well such that a user can further configure clustering runtime environment.


    For overall clustering features and aspects, we have logically divided them into two separate tiers: replication and application (POJO) tiers. They are discussed as follows.


    Replication tier


    Following are the replication tier aspects that are applied to the whole replication instance (e.g., in JBoss' case, it is the JBossCache layer), although some of these aspects can be futher fine-tuned in the application tier as well for POJO specific behaviors. Note that these are configured externally, and are therefore not covered by annotation.


    • Cluster group membership (e.g., mcast address and ports)

    • Clustering topology, e.g., Buddy Replication group selection

    • Replication mode, e.g., synchronous or asynchronous mode

    • Locking and isolation level, e.g., whether it is optimistic or pessimistic locking

    • Cache loader and its load type selection (e.g., jdbc)

    • Passivation


    Application tier


    The application tier annotation can be futher divided into POJO class- and field- levels to express for clustering behavior.


    Class level

    Following are the proposed annotations that can be defined at the class level.


    • @Replicated, Replication declaration with the following attributes:

      • granularity, CoarseGrained/FineGrained. If FineGrained is specified, POJO will be replicated.

      • clusterGroup, specify which cluster group to use. Note that this will replace the partition name that JBoss have been using in the past.

      • passivation, off. Override the option in the Replication layer. Note that we can only specify "off" option here now.

      • replicationMode, sync or async. Again, this is to override the replication mode.

      • batchMode, yes/no. Whether to batch the updates for replication or not.

    This is a configuration annotation that specifies the default POJO cluster behavior.

    This is a mandatory annotation that signifies the POJO to be clusterable. Container may parse this annotation to pre-process the POJO (e.g., apsectize the POJO). Note that the annotation's attributes are optional since we have defaults.


    If a user designates POJO as fine-grained, then on the POJO level, there are extra attributes available:

      • serializable denotes that we don't do fine-grained replication on this POJO. However, we still maintains reference counting for object relationship. For example, this POJO can be referenced from another POJO.

      • name, name that is associated with the underlying replication store. Can use this for query purpose. In PojoCache, think of an POJO instnace is the combintation of this name plus an unique ID. User, for example, can query all this POJO classs instances using this name.


    • @LoadBalancePolicy, client-side loadbalance policy to specify such as round-robin, FCFS, etc.


    • @Singleton, deployed as a singleton service


    Field level

    Furthermore, if it is fine-grained, there are additional per field level annotation to fine-fune the POJO clustering behavior.

    • @Transient. No replication will be performed on this field. Use this if you have Resource type file, e.g.

    • @Serializable. Replication will be done at this field level only (even it is a complex object), e.g. no recursive mapping. This still maitains object reference counting though.


    Callback events

    We also propose the following relevant clustering callback events on the POJO class and filed levels that can be annotated as well.

    • prePojoReplicated

    • postPojoReplicated

    • preFieldReplicated

    • postFieldReplicated

    • postAttach Event after when pojo is attached to the PojoCache

    • preDetach Event before pojo is detached from the PojoCache


    Q: Or should we just provide the AOP aspect libary Observer/Observable?



    To faciliate the use of PojoCache, it provides POJO method-level annotatoins are as follow to facilitate api-less call:

    • @Attach Whenever the assoicated method is called, we will attach this pojo automatically to the cache.

    • @Detach Whenever the associated method is called, we will detach this pojo from the cache


    Sample usage


    In my opinion, I envisage two ways people are going to use clustered POJS combined with client-side remoting: 1) ejb3 style sfsb, 2) stateless bean as a facade. We will look at both usages with snippets.


    First of all, here is a psuedo POJO to use with PojoCache:

    @Replicated(name="myOwnName", mode="async") // replicates the Pojo across all nodes in a cluster
    @Remoting(loadbalancepolicy=sticky.class) // creates clustered proxy, also exposes as a remote bean?
                                              // relation to ejb3 Remote?
    public class Pojo {
       int age;
       String uniqueName;
       @Transient // don't replicate hash !
       int hash;
       Address addr;
       @Serializable // don't instrument hobbies, use serialization to replicate !
       List  hobbies;
       @Attach // Will attach this pojo directly to PojoCache during contructor
       public Pojo() {;}
       @Detach // Will detach this pojo from PojoCache after done() finishes
       public done() {;}
       @PostAttach  // Event subscription
       public handleEvent() {;}   


    Stateful POJO with remoting


    Here is a psuedo client code that accesses the POJO remotely:

    public static Main(String args)
      Pojo pojo_;
      pojo_ = new Pojo(); // trigger attachment to PojoCache remotely
      pojo_.setUniqueName("Whats up"); // trigger fine-grained replication
      Address addr = new Address();
      pojo_.setAddress(addr); // associate with a sub-POJO
      // many more operations later, we have a failover
      pojo_.setAge(51); // This will failover to remote node (#2, e.g.)
      // ...
      pojo.done(); // ok, we are done. Server-side PojoCache will detach this pojo.
                   // any more operation from this one will not be replicated.
                   // Should we just combine with @Remove as well to remove it from Container?

    Note that maybe this case is already covered under ejb3 sfsb. E.g., the clustering will be done behind the scene already during the sfsb lifecycle and everything is identified by a container-assigned session ID.


    Clustered POJO accessed via a facade

    Here is sample code for a stateless POJO on the server side first:

     * A stateless session facade that is Remote to interact with client.
    public class PojoFacade
      public Object doProcess1(...) 
          // This is the way to get PojoCache instance
          PojoCache cache = PojoCacheFactory.getInstance();
          // We can query the pojo as well using the criteria.
          Pojo pojo = cache.find(Pojo.class).addCriteria(Pojo.uniqueName = "Whats up");
          if(pojo == null)
            // This can attach the pojo to the PojoCache
            pojo = new Pojo();
      public Object doProcess2(...)


    then here is the client side code:

    public static Main(String args)
       PojoFacade facade = remoting.lookup("facade"); // thru some Remoting lookup   
       facade.doProcess1(...); // First node
       facade.doProcess2(...); // We failover this one to remote node (#2, e.g.)



    Discovery annotations?


    JBoss specific implementation

    We will be using PojoCache to act as the replication layer for FineGrained replication. The following are issues if we were to comply with the above annotations.

    • Currently, we have defined @Clustered annotation and also @CacheConfig in the ejb3 framework. We will need to deprecate CacheConfig annotation in favor of ClusterConfig.

    • For ejb3 entity bean, we will also require Hibernate to use these annotations, except features associated with fine-grained since Hibernate manages the field attributes themselves.


    EJB3 integration?

    Currently this is how an ejb3 SFSB pojo will look like:

    public class Pojo {
       int age;
       String uniqueName;
       int hash;
       Address addr;
       List  hobbies;
       public Pojo() {;}
       public done() {;}
       public handleEvent() {;}   

    Should we combine this ejb3 sfsb (even it is run outside of ejb3 container)?