10 Replies Latest reply on Jan 7, 2009 2:12 PM by adrigan

    Moving to Pojo 3 from pojo 2 and attach fails

    adrigan

      Hi,

      I am preparing my existing application that uses multiple pojo caches to be able to be accessed from the latest JBoss App Server 5. In doing this, I realized I had to "upgrade" to the latest release of Pojo cache. In other words, I did not want to mix versions of the pojo cache but instead use the same version as JBoss App server 5.

      For step 1, I simply want to get the old application running with Naga.
      I change my command files to point to the places within the JBoss App Server (same libraries) as follows:

      set JBOSS_POJO=%BUILD_AREA%\lib\jboss\jboss-5.0.0.GA\server\AMOD\lib
      set JBOSS_POJO_JARS=%JBOSS_POJO%\jbosscache-pojo.jar;
      set JBOSS_POJO_JARS=%JBOSS_POJO_JARS%;%JBOSS_POJO%\jbosscache-core.jar;
      set JBOSS_POJO_JARS=%JBOSS_POJO_JARS%;%JBOSS_POJO%\jgroups.jar;
      set JBOSS_POJO_JARS=%JBOSS_POJO_JARS%;%JBOSS_JARS%;
      
      set JBOSS_CACHE_PARAMS=-javaagent:%JBOSS_CLIENT%\jboss-aop-client.jar
      
      -Djboss.aop.path=%JBOSS_POJO%\META-INF\pojocache-aop.xml
      
      


      As you can imagine, these variables are placed on the classpath and command line of my bat file. I extracted the pojocache-aop.xml from the jar file in my server called AMOD. It did not match the one in the documentation - but it worked (while the one in the 3.0 documentation did not.) Here it is:
      <?xml version="1.0" encoding="UTF-8"?>
      <!--
       This is a variant of jboss-aop.xml.
      -->
      <aop>
       <!-- If a POJO has a Replicable annotation, it will be asepectized. -->
      
       <!--
       Supports inheritance and polymorphism. It can either be a concrete class
       or an interface. All sub-classes or interface implementors will be instrumeneted.
       -->
       <prepare expr="field(* $instanceof{@org.jboss.cache.pojo.annotation.Replicable}->*)" />
      
       <!-- Work around that ensures annotated classes which do not access fields are instrumented -->
       <introduction expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})"/>
      
       <!-- Array support -->
       <!-- Comment entire section to disable -->
       <arrayreplacement expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})"/>
       <interceptor name="pojocache-array" class="org.jboss.cache.pojo.interceptors.dynamic.ArrayInterceptor"/>
       <introduction expr="class($instanceof{@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>
      


      My code from the application that worked on version 2 of pojo has not changed. The classes are annotated as follows.
      @org.jboss.cache.pojo.annotation.Replicable
      public class EquipmentItemNode
       extends ANode
      


      I use the following configuration file to create the cache. I pulled it from the "all.xml" from the jbosscache-core.jar (3.0) version.
      <?xml version="1.0" encoding="UTF-8"?>
      
      <jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.0">
      
      
       <!--
       isolation levels supported: READ_COMMITTED and REPEATABLE_READ
       nodeLockingSchemes: mvcc, pessimistic (deprecated), optimistic (deprecated)
       -->
       <locking
       isolationLevel="REPEATABLE_READ"
       lockParentForChildInsertRemove="false"
       lockAcquisitionTimeout="20000"
       nodeLockingScheme="mvcc"
       writeSkewCheck="false"
       concurrencyLevel="500"/>
      
       <!--
       Used to register a transaction manager and participate in ongoing transactions.
       -->
       <transaction
       transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup"
       syncRollbackPhase="false"
       syncCommitPhase="false"/>
      
       <!--
       Used to register JMX statistics in any available MBean server
       -->
       <jmxStatistics
       enabled="false"/>
      
       <!--
       If region based marshalling is used, defines whether new regions are inactive on startup.
       -->
       <startup
       regionsInactiveOnStartup="true"/>
      
       <!--
       Used to register JVM shutdown hooks.
       hookBehavior: DEFAULT, REGISTER, DONT_REGISTER
       -->
       <shutdown
       hookBehavior="DEFAULT"/>
      
       <!--
       Used to define async listener notification thread pool size
       -->
       <listeners
       asyncPoolSize="1"
       asyncQueueSize="1000000"/>
      
       <!--
       Used to enable invocation batching and allow the use of Cache.startBatch()/endBatch() methods.
       -->
       <invocationBatching
       enabled="false"/>
      
       <!--
       serialization related configuration, used for replication and cache loading
       -->
       <serialization
       objectInputStreamPoolSize="12"
       objectOutputStreamPoolSize="14"
       version="3.0.0"
       marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller"
       useLazyDeserialization="false"
       useRegionBasedMarshalling="false"/>
      
       <!--
       This element specifies that the cache is clustered.
       modes supported: replication (r) or invalidation (i).
       -->
       <clustering mode="replication" clusterName="JBossCache-cluster">
      
       <!--
       Defines whether to retrieve state on startup
       -->
       <stateRetrieval timeout="20000" fetchInMemoryState="false"/>
      
       <!--
       Network calls are synchronous.
       -->
       <sync replTimeout="20000"/>
       <!--
       Uncomment this for async replication.
       -->
       <!--<async useReplQueue="true" replQueueInterval="10000" replQueueMaxElements="500" serializationExecutorPoolSize="20" serializationExecutorQueueSize="5000000"/>-->
      
       <!-- Uncomment to use Buddy Replication -->
       <!--
       <buddy enabled="true" poolName="myBuddyPoolReplicationGroup" communicationTimeout="2000">
       <dataGravitation auto="true" removeOnFind="true" searchBackupTrees="true"/>
       <locator class="org.jboss.cache.buddyreplication.NextMemberBuddyLocator">
       <properties>
       numBuddies = 1
       ignoreColocatedBuddies = true
       </properties>
       </locator>
       </buddy>
       -->
      
       <!--
       Configures the JGroups channel. Looks up a JGroups config file on the classpath or filesystem. udp.xml
       ships with jgroups.jar and will be picked up by the class loader.
       -->
       <jgroupsConfig>
      
       <UDP discard_incompatible_packets="true" enable_bundling="false" enable_diagnostics="false" ip_ttl="2"
       loopback="false" max_bundle_size="64000" max_bundle_timeout="30" mcast_addr="228.10.10.10"
       mcast_port="45588" mcast_recv_buf_size="25000000" mcast_send_buf_size="640000"
       oob_thread_pool.enabled="true" oob_thread_pool.keep_alive_time="10000" oob_thread_pool.max_threads="4"
       oob_thread_pool.min_threads="1" oob_thread_pool.queue_enabled="true" oob_thread_pool.queue_max_size="10"
       oob_thread_pool.rejection_policy="Run" thread_naming_pattern="pl" thread_pool.enabled="true"
       thread_pool.keep_alive_time="30000" thread_pool.max_threads="25" thread_pool.min_threads="1"
       thread_pool.queue_enabled="true" thread_pool.queue_max_size="10" thread_pool.rejection_policy="Run"
       tos="8" ucast_recv_buf_size="20000000" ucast_send_buf_size="640000" use_concurrent_stack="true"
       use_incoming_packet_handler="true"/>
       <PING num_initial_members="3" timeout="2000"/>
       <MERGE2 max_interval="30000" min_interval="10000"/>
       <FD_SOCK/>
       <FD max_tries="5" shun="true" timeout="10000"/>
       <VERIFY_SUSPECT timeout="1500"/>
       <pbcast.NAKACK discard_delivered_msgs="true" gc_lag="0" retransmit_timeout="300,600,1200,2400,4800"
       use_mcast_xmit="false"/>
       <UNICAST timeout="300,600,1200,2400,3600"/>
       <pbcast.STABLE desired_avg_gossip="50000" max_bytes="400000" stability_delay="1000"/>
       <pbcast.GMS join_timeout="5000" print_local_addr="true" shun="false" view_ack_collection_timeout="5000"
       view_bundling="true"/>
       <FRAG2 frag_size="60000"/>
       <pbcast.STREAMING_STATE_TRANSFER/>
       <pbcast.FLUSH timeout="0"/>
      
       </jgroupsConfig>
       </clustering>
      
       <!--
       Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds. 0 means
       the eviction thread will never run.
       -->
       <eviction wakeUpInterval="0"> <!-- was 500 -->
       <default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm" eventQueueSize="200000">
       <property name="maxNodes" value="5000"/>
       <property name="timeToLive" value="1000"/>
       </default>
       <region name="/org/jboss/data1">
       <property name="timeToLive" value="2000"/>
       </region>
       <region name="/org/jboss/data2" algorithmClass="org.jboss.cache.eviction.FIFOAlgorithm" eventQueueSize="100000">
       <property name="maxNodes" value="3000"/>
       <property name="minTimeToLive" value="4000"/>
       </region>
       </eviction>
      
      
       <!--
       Cache loaders.
      
       If passivation is enabled, state is offloaded to the cache loaders ONLY when evicted. Similarly, when the state
       is accessed again, it is removed from the cache loader and loaded into memory.
      
       Otherwise, state is always maintained in the cache loader as well as in memory.
      
       Set 'shared' to true if all instances in the cluster use the same cache loader instance, e.g., are talking to the
       same database.
      LKA - comment out until we get our database set up - Derby comes with JBoss 5 - may use it
      
       <loaders passivation="false" shared="false">
       <preload>
       <node fqn="/org/jboss"/>
       <node fqn="/org/tempdata"/>
       </preload>
       -->
       <!--
       we can have multiple cache loaders, which get chained
      
       <loader class="org.jboss.cache.loader.JDBCCacheLoader" async="true" fetchPersistentState="true"
       ignoreModifications="true" purgeOnStartup="true">
      
       <properties>
       cache.jdbc.table.name=jbosscache
       cache.jdbc.table.create=true
       cache.jdbc.table.drop=true
       cache.jdbc.table.primarykey=jbosscache_pk
       cache.jdbc.fqn.column=fqn
       cache.jdbc.fqn.type=varchar(255)
       cache.jdbc.node.column=node
       cache.jdbc.node.type=blob
       cache.jdbc.parent.column=parent
       cache.jdbc.sql-concat=1 || 2
       cache.jdbc.driver = org.apache.derby.jdbc.EmbeddedDriver
       cache.jdbc.url=jdbc:derby:jbossdb;create=true
       cache.jdbc.user=user1
       cache.jdbc.password=user1
       </properties>
       -->
       <!-- alternatively use a connection from a datasorce, as per the code sample below-->
       <!--<properties>-->
       <!--cache.jdbc.datasource=AllSampleDS-->
       <!--cache.jdbc.table.name=jbosscache-->
       <!--cache.jdbc.table.create=true-->
       <!--cache.jdbc.table.drop=true-->
       <!--</properties>
       <singletonStore enabled="true" class="org.jboss.cache.loader.SingletonStoreCacheLoader">
       <properties>
       pushStateWhenCoordinator=true
       pushStateWhenCoordinatorTimeout=20000
       </properties>
       </singletonStore>
       </loader>
       </loaders>
      -->
      
       <!--
       Define custom interceptors. All custom interceptors need to extend org.jboss.cache.interceptors.base.CommandInterceptor
       -->
       <!--
       <customInterceptors>
       <interceptor position="first" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor">
       <property name="attrOne" value="value1" />
       <property name="attrTwo" value="value2" />
       </interceptor>
       <interceptor position="last" class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/>
       <interceptor index="3" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/>
       <interceptor before="org.jboss.cache.interceptors.CallInterceptor"
       class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/>
       <interceptor after="org.jboss.cache.interceptors.CallInterceptor"
       class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/>
       </customInterceptors>
       -->
      </jbosscache>
      


      When I attach an object to the cache, I do not receive an exception at all. But - it is not attached as a subsequent find does not retrieve it. I put the following debug line around the attach to see if a fqn id is assigned to the object.

      Ojbect pojo = myCache.attach(name, object);
      
       trace.log(Level.INFO, "did attach object " + object.getClass().toString() + " " +
       object.toString() + " to name " + name +
       " in cache name " +
       this.nameOfCache + " with fqn of " +
       this.myCache.getInternalFqn(object));
      
      Dec 23, 2008 3:39:06 PM com.lm.cache.CacheManager attachObjectToCache
      INFO: did attach object class com.lm.dataModel.EquipmentItemNode / to name / in cache name EquipmentCache with fqn of null
      
      

      The result I get back confuses the day lights out of me. No exception is thrown - the object is annotated and instrumented, but it is not actually attached. This did work on the prior version.
      I figure I must have the configuration messed up. I would appreciate any and all help. Thank you.

        • 1. Re: Moving to Pojo 3 from pojo 2 and attach fails
          manik

          Did you try using the same config file from your working 2.x setup? You can still use old 2.x config files, even though they are deprecated. Also, maybe you should try the config file conversion script included in the 3.x distribution.

          • 2. Re: Moving to Pojo 3 from pojo 2 and attach fails
            jason.greene
            • 3. Re: Moving to Pojo 3 from pojo 2 and attach fails
              adrigan

              Thank you for your responses. I got a little farther.

              I took the "total-replication.xml" from the jbosscache-core.jar from my server lib area and was able to run. I then began commenting out pieces of my xml configuration taken from the all.xml in the jbosscache-pojo.jar I commented out the "serialization" portion. It may have been at least part of the problem.

               <!--
               serialization related configuration, used for replication and cache loading
              
               <serialization
               objectInputStreamPoolSize="12"
               objectOutputStreamPoolSize="14"
               version="3.0.0"
               marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller"
               useLazyDeserialization="false"
               useRegionBasedMarshalling="false"/>
               -->
              

              Does that make sense to you? Why would this cause a problem?


              Another question: I use the proxy method as described in the pojo 2.1 documentation. Are these no longer needed with pojo 3.0?

              Here is my proxy code:

               private List<StatusValueTimeStamped> statusValues = null;
              
               /**
               * Proxy is needed for pojo cache
               * @return
               */
               private List<StatusValueTimeStamped> getStatusValuesProxy()
               {
               return statusValues;
               }
              


              I get this super strange error ( I have never seen in all my career).
              Exception in thread "AWT-EventQueue-0" java.lang.VerifyError: (class: com/lm/dataModel/rules/StatusRule, method: propagateFromHere
              OnUpTree signature: (Lcom/lm/dataModel/ANode;Lcom/lm/dataModel/ANode$Source;Lcom/lm/dataModel/ANode$StatusValue;)Z) Unable to pop
              operand off an empty stack
               at com.lm.dataModel.ANode.setStatusValueWithPropagation(ANode.java:301)
               at com.lm.seem.StatusTableModel.setValueAt(StatusTableModel.java:133)
              

              I am passing "ANode" as the first parameter (which is in the cache) to the method. This is code from inside the ANode class (line 301) above.

               public synchronized void setStatusValueWithPropagation(Source source,
               StatusValue statusValue)
               {
               StatusRule.propagateFromHereOnUpTree(this, source, statusValue);
               }
              

              The signature of the StatusRule method is as follows:
              public static boolean propagateFromHereOnUpTree(ANode myNode, Source source,
               StatusValue status)
              

              All this code worked in the pojo 2.1 version.
              I am no expert, but it looks like object (ANode) is not on the stack?

              Your help would be greatly appreciated. Thank you.


              • 4. Re: Moving to Pojo 3 from pojo 2 and attach fails
                jason.greene

                The VerifyError is the source of the problem, it means that the bytecode violates a class formatting rule. The problematic class is com.lm.dataModel.rules.StatusRule. Did you run aopc on this class, or are you using loadtime instrumentation?

                • 5. Re: Moving to Pojo 3 from pojo 2 and attach fails
                  adrigan

                  I use load time instrumentation.

                  • 6. Re: Moving to Pojo 3 from pojo 2 and attach fails
                    jason.greene

                    Ok, any chance you could post the source to that method?

                    • 7. Re: Moving to Pojo 3 from pojo 2 and attach fails
                      adrigan

                      Yes, thank you for you help. I think you are on the right track. I am not sure if we really did the best job in implementing this class.

                      We have a tree of equipment item nodes whose status may be set through the children. For instance, if a power supply is down to say a computer - the whole computer is "hosed." We have a set of rules that determines how each child sets the status of its parent. This is what you are seeing in this class.

                      @org.jboss.cache.pojo.annotation.Replicable
                      public class StatusRule
                      {
                      
                       @org.jboss.cache.pojo.annotation.Transient
                       protected transient static Logger trace =
                       ApplGlobalFileLogger.getFileLogger();
                      
                       protected String description = null;
                      
                       public static enum RULE_TYPE
                       {
                      
                       F0, F1, F2, F3,
                       C0, C1, C2, C3
                       };
                      
                       public StatusRule(String description)
                       {
                       this.description = description;
                       }
                      
                       public String getDescription()
                       {
                       return description;
                       }
                      
                       /**
                       * The class that extends this class
                       * must OVERRIDE what it means to set the status of each node.
                       * Some rules may look at children and then look at the dominance rule to
                       * see if that exists and over rides the children rule.
                       * Note: This was an abstract method - but the JCache disallowed abstracts.
                       * Other rules must simply override this method.
                       * @param myNode
                       * @param source
                       * @param status
                       * @return
                       */
                       //public abstract boolean applyRule(ANode myNode, Source source, StatusValue statusValue);
                       public boolean applyRule(ANode myNode, Source source, StatusValue statusValue)
                       throws Exception
                       {
                       if (source == null) {
                       trace.log(Level.SEVERE, " bad source - to apply rule it is null");
                       throw new Exception();
                       }
                      
                       if (myNode == null) {
                       return false;
                       }
                       StatusValue calculatedValue = statusValue; // the default
                      
                       String[] children = myNode.getChildNodes();
                       ANode child = null;
                       if (source.equals(Source.CHILDREN_SETTING_STATUS)) {
                      
                       for (String childFullPathName : children) {
                       child = EquipmentHierarchy.getInstance().getNode(childFullPathName);
                       if (child != null) {
                       //look at each child and follow the rule above as stated in the description
                       }
                       }
                       }
                      
                       // always directly set this node without looking at children because the
                       // base class does the propagation. All propagation is the same and goes
                       // up the tree from this place!
                       myNode.setStatusValueImmediateNoPropagateForPropagationRULEOnly(source, statusValue); // non recursive one
                      
                       return true;
                      
                       }
                      
                       /**
                       * Change status on this status value on this node on upward
                       * @param myNode
                       * @param source
                       * @param status
                       * @return
                       */
                       public static boolean propagateFromHereOnUpTree(ANode myNode, Source source,
                       StatusValue status)
                       {
                       try {
                       String name = null;
                       if (myNode != null) {
                       name = myNode.getFullPathName();
                       }
                       trace.log(Level.INFO, "Propagation rule started on " + name);
                      
                       if (myNode == null) {
                       trace.log(Level.SEVERE, "Propagation rule has no node associated with it!");
                       return false; // can do nothing
                       }
                      
                       // do the from here part!
                       // set my node's status
                       System.out.println("setStatusValueWithPropagation " +
                       myNode.getRuleType().toString());
                       switch (myNode.getRuleType()) {
                       case F0:
                       F0StatusRule.getInstance().applyRule(myNode, source, status);
                       break;
                       case F1:
                       F1StatusRule.getInstance().applyRule(myNode, source, status);
                       break;
                       case F2:
                       F2StatusRule.getInstance().applyRule(myNode, source, status);
                       break;
                       case F3:
                       F3StatusRule.getInstance().applyRule(myNode, source, status);
                       break;
                       case C0:
                       break;
                       case C1:
                       break;
                       case C2:
                       break;
                       case C3:
                       break;
                       default:
                       System.out.println("Invalid rule type : " +
                       myNode.getRuleType().toString());
                       }
                      
                       ANode parent = null;
                       String parentFullPathName = myNode.getParentNode();
                       if (parentFullPathName != null) {
                       parent =
                       EquipmentHierarchy.getInstance().getNode(parentFullPathName);
                       // do the on up tree part
                       // in all cases want to propagat parent = e the status up the tree
                      
                       // move up to the parent in the tree and
                       // now we are propagating based on the source of a CHILD setting status
                       parent.setStatusValueWithPropagation(Source.CHILDREN_SETTING_STATUS, status); // indirect recursion
                       } else //parent is null at the root
                       {
                       // end of the recursion
                       trace.log(Level.INFO, "Ending recursion on node " + name);
                       return true;
                       }
                       return true;
                       } catch (Exception ex) {
                       Logger.getLogger(StatusRule.class.getName()).log(Level.SEVERE, null, ex);
                       return false;
                       }
                      
                       }
                      
                       // propagation goodies
                       /**
                       * Method to reset the status down the tree from this node - note - it sets the operator status.
                       * Note: method left here just in case needed later. At the moment there is no need so
                       * made private.
                       */
                       protected synchronized void resetOperatorStatusFromNodeOnDown(ANode node)
                       {
                       StatusValue statusValue = StatusValue.NOT_TESTED;
                       String[] children = node.getChildNodes();
                       Source source = Source.OPERATOR;
                       ANode child = null;
                       for (String childFullPathName : children) {
                       //look at each child and follow the rule above as stated in the description
                       child = EquipmentHierarchy.getInstance().getNode(childFullPathName);
                       if (child != null) {
                       child.setStatusValueImmediateNoPropagateForPropagationRULEOnly(source, statusValue); // non recursive one
                      
                       }
                      
                       }
                      
                       // most simple rule - directly set this node without looking at children
                       node.setStatusValueImmediateNoPropagateForPropagationRULEOnly(source, statusValue); // non recursive one
                      
                       }
                      
                       @Override
                       public boolean equals(Object obj)
                       {
                       return super.equals(obj);
                       }
                      
                       @Override
                       public int hashCode()
                       {
                       return super.hashCode();
                       }
                      
                       @Override
                       public String toString()
                       {
                       StringBuilder buf = new StringBuilder(30);
                      
                      
                       buf.append("Textual Description = ");
                       if (this.description != null) {
                       buf.append(this.description);
                       }
                      
                       return buf.toString();
                       }
                      }
                      


                      The next class extends the class listed above. It is what is breaking in our run.
                      @org.jboss.cache.pojo.annotation.Replicable
                      public class F0StatusRule
                       extends StatusRule
                       implements java.io.Serializable
                      {
                      
                       private static F0StatusRule instance = null;
                       private transient static String myDescription =
                       "1. If all children have status of NOT TESTED, then the parent status will be NOT TESTED." +
                       "\n" +
                       "2. If all critical children have status of GOOD or NOT TESTED, and all non-critical children have status of GOOD, GOOD WITH LOSS OF REDUNDANCY, or NOT TESTED, then the parent status will be GOOD." +
                       "\n" +
                       "3. If all children have status of GOOD, GOOD WITH LOSS OF REDUNDANCY, or NOT TESTED, then parent status will be GOOD WITH LOSS OF REDUNDANCY." +
                       "\n" +
                       "4. If all critical children have status of GOOD, GOOD WITH LOSS OF REDUNDANCY, DEGRADED, or NOT TESTED, then parent status will be DEGRADED." +
                       "\n" +
                       "5. If the children have status other than the ones mentioned above, the parent status will be FAILED.";
                      
                       private F0StatusRule(String description)
                       {
                       super(description);
                       }
                       /**
                       * Singleton
                       * @return
                       */
                       public static synchronized F0StatusRule getInstance()
                       {
                       if (instance == null) {
                       instance = new F0StatusRule(myDescription);
                       }
                       return instance;
                       }
                       @Override
                       // emo - i don't think statusValue needs to be passed in here
                       public boolean applyRule(ANode myNode, Source source, StatusValue statusValue)
                       throws Exception
                       {
                      
                       // Check inputs...
                       if (source == null) {
                       trace.log(Level.SEVERE, " bad source - to apply rule it is null");
                       throw new Exception();
                       }
                       if (myNode == null) {
                       return false;
                       }
                      
                       // Initialize generic values
                       StatusValue calculatedStatus = StatusValue.NOT_TESTED;
                       int[] criticalStatusCounts = new int[StatusValue.values().length];
                       int[] nonCriticalStatusCounts = new int[StatusValue.values().length];
                      
                       if (source.equals(Source.CHILDREN_SETTING_STATUS)) {
                       // Get children information
                       String[] children = myNode.getChildNodes();
                       int childCount = children.length;
                      
                       // Go through all the children and get their status, dividing them
                       // between critical and non critical. Also keep track of how many of
                       // each (critical/non critical) there are
                       ANode child = null;
                       int criticalChildCount = 0;
                       int nonCriticalChildCount = 0;
                       for (String childFullPathName : children) {
                       child =
                       EquipmentHierarchy.getInstance().getNode(childFullPathName);
                       if (child != null) {
                       if (myNode.getChildCriticality(childFullPathName)) {
                       criticalStatusCounts[child.getSummaryStatus().ordinal()]++;
                       criticalChildCount++;
                       } else {
                       nonCriticalStatusCounts[child.getSummaryStatus().ordinal()]++;
                       nonCriticalChildCount++;
                       }
                       //look at each child and follow the rule above as stated in the description
                       } else {
                       System.out.println("child " + childFullPathName +
                       " missing for " +
                       myNode.getFullPathName());
                       }
                       }
                      
                       // Calculate the status according to the rule
                       int statusMatches = criticalStatusCounts[StatusValue.NOT_TESTED.ordinal()] +
                       nonCriticalStatusCounts[StatusValue.NOT_TESTED.ordinal()];
                       // All status are NOT_TESTED
                       if (statusMatches == childCount) {
                       calculatedStatus = StatusValue.NOT_TESTED;
                       } else {
                       // Check to see if all critical are NOT_TESTED/GOOD
                       // and if all non critical are NOT_TESTED/GOOD/LOSS_WITH_REDUNDANCY
                       int criticalMatches = criticalStatusCounts[StatusValue.NOT_TESTED.ordinal()] +
                       criticalStatusCounts[StatusValue.GOOD.ordinal()];
                       int nonCriticalMatches =
                       nonCriticalStatusCounts[StatusValue.NOT_TESTED.ordinal()] +
                       nonCriticalStatusCounts[StatusValue.GOOD.ordinal()] +
                       nonCriticalStatusCounts[StatusValue.GOOD_WITH_LOSS_OF_REDUNDANCY.ordinal()];
                       if (criticalMatches == criticalChildCount && nonCriticalMatches ==
                       nonCriticalChildCount) {
                       calculatedStatus = StatusValue.GOOD;
                       } else {
                       // Check to see if all critical are NOT_TESTED/GOOD/LOSS_WITH_REDUNDANCY
                       // and if all non critical are NOT_TESTED/GOOD/LOSS_WITH_REDUNDANCY
                       criticalMatches +=
                       criticalStatusCounts[StatusValue.GOOD_WITH_LOSS_OF_REDUNDANCY.ordinal()];
                       if (criticalMatches == criticalChildCount &&
                       nonCriticalMatches == nonCriticalChildCount) {
                       calculatedStatus = StatusValue.GOOD_WITH_LOSS_OF_REDUNDANCY;
                       } else {
                       // Check to see if all critical are NOT_TESTED/GOOD/LOSS_WITH_REDUNDANCY/DEGRADED
                       criticalMatches +=
                       criticalStatusCounts[StatusValue.DEGRADED.ordinal()];
                       if (criticalMatches == criticalChildCount)// &&
                       {
                       calculatedStatus = StatusValue.DEGRADED;
                       } else {
                       // All else are FAILED
                       calculatedStatus = StatusValue.FAILED;
                       }
                       }
                       }
                       }
                      
                       } else {
                       calculatedStatus = statusValue;
                       }
                       // always directly set this node without looking at children because the
                       // base class does the propagation. All propagation is the same and goes
                       // up the tree from this place!
                       myNode.setStatusValueImmediateNoPropagateForPropagationRULEOnly(source,
                       calculatedStatus);
                       return true;
                       }
                      }
                      



                      Using pojo 2 - we found a strange bug where we had to say that a class implements serialiable in order for that attribute/field to be replicated in the cache.

                      Let me clarify - we had to say implements serializable when one of the attributes of the class was a String and any other attribute (if it existed was primitive (not another class)).

                      It is something we just learned to do by default - if a class had a string attribute in it - make sure to say implements serialiable. Perhaps this "feature" has been fixed in 3.0 and now we can remove the implements serializable?

                      I do appreciate your help with problem!


                      • 8. Re: Moving to Pojo 3 from pojo 2 and attach fails
                        jason.greene

                        I was finally able to track down the source of the problem. I have filed a bug entry which you can track here:

                        https://jira.jboss.org/jira/browse/PCACHE-79

                        The problem is specific to array interception and a specific bytecode sequence involving switches and arrays. This problem is likely to occur when using an enum in a switch, since the java compiler implements this using an array.

                        The workaround is to disable array interception by editing your aop.xml file. See the bug description for more info on how to do this.

                        In regards to the usage of Serializable. I am not aware of any issue in 2.1 that required you to do this when you used String fields.

                        • 9. Re: Moving to Pojo 3 from pojo 2 and attach fails
                          adrigan

                          Wow! Thank you for finding that problem. I did not change the xml file - but simply removed the switch from the code and never saw the byte code error again.
                          Thank you for your diligence! I am impressed with this JBoss Team!


                          I have gotten a lot farther thanks to your help - but seem to have one last problem. When I start my separate applications and they connect to the cache with the same name - they appear to connect to separate caches. Here is the code that used to work on pojo 2. I have 3 separate caches for different objects within our application. Each cache uses the same xml file found here. This xml file has been updated to work with pojo 3.

                          <?xml version="1.0" encoding="UTF-8"?>
                          
                          <jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.0">
                          
                          
                           <!--
                           isolation levels supported: READ_COMMITTED and REPEATABLE_READ
                           nodeLockingSchemes: mvcc, pessimistic (deprecated), optimistic (deprecated)
                           -->
                           <locking
                           isolationLevel="REPEATABLE_READ"
                           lockParentForChildInsertRemove="false"
                           lockAcquisitionTimeout="20000"
                           nodeLockingScheme="mvcc"
                           writeSkewCheck="false"
                           concurrencyLevel="500"/>
                          
                           <!--
                           Used to register a transaction manager and participate in ongoing transactions.
                           -->
                          
                           <transaction
                           transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup"
                           syncRollbackPhase="false"
                           syncCommitPhase="false"/>
                          
                          
                           <!--
                           Used to register JMX statistics in any available MBean server
                           -->
                           <jmxStatistics
                           enabled="false"/>
                          
                           <!--
                           If region based marshalling is used, defines whether new regions are inactive on startup.
                           -->
                           <startup
                           regionsInactiveOnStartup="true"/>
                          
                          
                           <!--
                           Used to register JVM shutdown hooks.
                           hookBehavior: DEFAULT, REGISTER, DONT_REGISTER
                           -->
                           <shutdown
                           hookBehavior="DEFAULT"/>
                          
                           <!--
                           Used to define async listener notification thread pool size
                           -->
                           <listeners
                           asyncPoolSize="1"
                           asyncQueueSize="1000000"/>
                          
                           <!--
                           Used to enable invocation batching and allow the use of Cache.startBatch()/endBatch() methods.
                           -->
                           <invocationBatching
                           enabled="false"/>
                          
                           <!--
                           serialization related configuration, used for replication and cache loading
                           -->
                           <!-- LKA - Causes strange error where attach a node - but then can not find it in the very next line
                           <serialization
                           objectInputStreamPoolSize="12"
                           objectOutputStreamPoolSize="14"
                           version="3.0.0"
                           marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller"
                           useLazyDeserialization="false"
                           useRegionBasedMarshalling="false"/>
                           -->
                          
                          <!--
                          1/6/09 We have 3 separate caches at the moment:
                           <clustering mode="replication" clusterName="AlertsCache"> </clustering>
                           <clustering mode="replication" clusterName="EquipmentCache"/></clustering>
                           <clustering mode="replication" clusterName="TestListsCache"/></clustering>
                           -->
                           <!--
                           This element specifies that the cache is clustered.
                           modes supported: replication (r) or invalidation (i).
                           -->
                           <clustering mode="replication" clusterName="JBossCluster-Cache">
                          
                           <!--
                           Defines whether to retrieve state on startup
                           -->
                           <stateRetrieval timeout="20000" fetchInMemoryState="false"/>
                          
                           <!--
                           Network calls are synchronous.
                           -->
                           <sync replTimeout="20000"/>
                           <!--
                           Uncomment this for async replication.
                           -->
                           <!--<async useReplQueue="true" replQueueInterval="10000" replQueueMaxElements="500" serializationExecutorPoolSize="20" serializationExecutorQueueSize="5000000"/>-->
                          
                           <!-- Uncomment to use Buddy Replication -->
                           <!--
                           <buddy enabled="true" poolName="myBuddyPoolReplicationGroup" communicationTimeout="2000">
                           <dataGravitation auto="true" removeOnFind="true" searchBackupTrees="true"/>
                           <locator class="org.jboss.cache.buddyreplication.NextMemberBuddyLocator">
                           <properties>
                           numBuddies = 1
                           ignoreColocatedBuddies = true
                           </properties>
                           </locator>
                           </buddy>
                           -->
                          
                           <!--
                           Configures the JGroups channel. Looks up a JGroups config file on the classpath or filesystem. udp.xml
                           ships with jgroups.jar and will be picked up by the class loader.
                           -->
                           <jgroupsConfig>
                          
                           <UDP discard_incompatible_packets="true" enable_bundling="false" enable_diagnostics="false" ip_ttl="2"
                           loopback="false" max_bundle_size="64000" max_bundle_timeout="30" mcast_addr="228.10.10.10"
                           mcast_port="45588" mcast_recv_buf_size="25000000" mcast_send_buf_size="640000"
                           oob_thread_pool.enabled="true" oob_thread_pool.keep_alive_time="10000" oob_thread_pool.max_threads="4"
                           oob_thread_pool.min_threads="1" oob_thread_pool.queue_enabled="true" oob_thread_pool.queue_max_size="10"
                           oob_thread_pool.rejection_policy="Run" thread_naming_pattern="pl" thread_pool.enabled="true"
                           thread_pool.keep_alive_time="30000" thread_pool.max_threads="25" thread_pool.min_threads="1"
                           thread_pool.queue_enabled="true" thread_pool.queue_max_size="10" thread_pool.rejection_policy="Run"
                           tos="8" ucast_recv_buf_size="20000000" ucast_send_buf_size="640000" use_concurrent_stack="true"
                           use_incoming_packet_handler="true"/>
                           <PING num_initial_members="3" timeout="2000"/>
                           <MERGE2 max_interval="30000" min_interval="10000"/>
                           <FD_SOCK/>
                           <FD max_tries="5" shun="true" timeout="10000"/>
                           <VERIFY_SUSPECT timeout="1500"/>
                           <pbcast.NAKACK discard_delivered_msgs="true" gc_lag="0" retransmit_timeout="300,600,1200,2400,4800"
                           use_mcast_xmit="false"/>
                           <UNICAST timeout="300,600,1200,2400,3600"/>
                           <pbcast.STABLE desired_avg_gossip="50000" max_bytes="400000" stability_delay="1000"/>
                           <pbcast.GMS join_timeout="5000" print_local_addr="true" shun="false" view_ack_collection_timeout="5000"
                           view_bundling="true"/>
                           <FRAG2 frag_size="60000"/>
                           <pbcast.STREAMING_STATE_TRANSFER/>
                           <pbcast.FLUSH timeout="0"/>
                          
                           </jgroupsConfig>
                           </clustering>
                          
                           <!--
                           Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds. 0 means
                           the eviction thread will never run.
                          
                           <eviction wakeUpInterval="500">
                           <default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm" eventQueueSize="200000">
                           <property name="maxNodes" value="5000"/>
                           <property name="timeToLive" value="1000"/>
                           </default>
                           <region name="/org/jboss/data1">
                           <property name="timeToLive" value="2000"/>
                           </region>
                           <region name="/org/jboss/data2" algorithmClass="org.jboss.cache.eviction.FIFOAlgorithm" eventQueueSize="100000">
                           <property name="maxNodes" value="3000"/>
                           <property name="minTimeToLive" value="4000"/>
                           </region>
                           </eviction>
                           -->
                          
                           <!--
                           Cache loaders.
                          
                           If passivation is enabled, state is offloaded to the cache loaders ONLY when evicted. Similarly, when the state
                           is accessed again, it is removed from the cache loader and loaded into memory.
                          
                           Otherwise, state is always maintained in the cache loader as well as in memory.
                          
                           Set 'shared' to true if all instances in the cluster use the same cache loader instance, e.g., are talking to the
                           same database.
                          LKA - comment out until we get our database set up - Derby comes with JBoss 5 - may use it
                          
                           <loaders passivation="false" shared="false">
                           <preload>
                           <node fqn="/org/jboss"/>
                           <node fqn="/org/tempdata"/>
                           </preload>
                           -->
                           <!--
                           we can have multiple cache loaders, which get chained
                          
                           <loader class="org.jboss.cache.loader.JDBCCacheLoader" async="true" fetchPersistentState="true"
                           ignoreModifications="true" purgeOnStartup="true">
                          
                           <properties>
                           cache.jdbc.table.name=jbosscache
                           cache.jdbc.table.create=true
                           cache.jdbc.table.drop=true
                           cache.jdbc.table.primarykey=jbosscache_pk
                           cache.jdbc.fqn.column=fqn
                           cache.jdbc.fqn.type=varchar(255)
                           cache.jdbc.node.column=node
                           cache.jdbc.node.type=blob
                           cache.jdbc.parent.column=parent
                           cache.jdbc.sql-concat=1 || 2
                           cache.jdbc.driver = org.apache.derby.jdbc.EmbeddedDriver
                           cache.jdbc.url=jdbc:derby:jbossdb;create=true
                           cache.jdbc.user=user1
                           cache.jdbc.password=user1
                           </properties>
                           -->
                           <!-- alternatively use a connection from a datasorce, as per the code sample below-->
                           <!--<properties>-->
                           <!--cache.jdbc.datasource=AllSampleDS-->
                           <!--cache.jdbc.table.name=jbosscache-->
                           <!--cache.jdbc.table.create=true-->
                           <!--cache.jdbc.table.drop=true-->
                           <!--</properties>
                           <singletonStore enabled="true" class="org.jboss.cache.loader.SingletonStoreCacheLoader">
                           <properties>
                           pushStateWhenCoordinator=true
                           pushStateWhenCoordinatorTimeout=20000
                           </properties>
                           </singletonStore>
                           </loader>
                           </loaders>
                          -->
                          
                           <!--
                           Define custom interceptors. All custom interceptors need to extend org.jboss.cache.interceptors.base.CommandInterceptor
                           -->
                           <!--
                           <customInterceptors>
                           <interceptor position="first" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor">
                           <property name="attrOne" value="value1" />
                           <property name="attrTwo" value="value2" />
                           </interceptor>
                           <interceptor position="last" class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/>
                           <interceptor index="3" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/>
                           <interceptor before="org.jboss.cache.interceptors.CallInterceptor"
                           class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/>
                           <interceptor after="org.jboss.cache.interceptors.CallInterceptor"
                           class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/>
                           </customInterceptors>
                           -->
                          </jbosscache>
                          


                          Each cache then sets its own cache cluster name to match the objects it contains. For example, we have one for equipment, one for alerts, and one for tests. It works as follows:
                           private PojoCache createCache(String configFileName, String clusterName)
                           throws Exception
                           {
                          
                           trace.log(Level.INFO, "creating cache with " + configFileName +
                           " in cluster, cache name " +
                           clusterName + "," + this.nameOfCache);
                          
                           Configuration config = createConfigurationFromXMLFile(configFileName);
                          
                           config.setClusterName(clusterName); // We can set a different cluster group.
                           trace.log(Level.INFO, "Printout of configuration:\n" + config.toString());
                           boolean toStart = true;
                           PojoCache cache = PojoCacheFactory.createCache(config, toStart);
                          
                           return cache;
                           }
                          
                           public CacheManager(String nameOfCache, String configFileName, String clusterName)
                           {
                          
                           //this.logger = trace;
                           this.nameOfCache = nameOfCache;
                           try
                           {
                           this.myCache = createCache(configFileName, clusterName);
                           }
                           catch (Exception e)
                           {
                           trace.log(Level.SEVERE, "Severe Error - cache is not working. Exit", e);
                           System.exit(-1);
                           }
                          
                           }
                          

                          Where each application does the following:
                           String configFileName =
                           "META-INF/total-replication-cache-service.xml";
                           String clusterName = "Equipment-Cluster";
                           cacheManager = new CacheManager("EquipmentCache", configFileName, clusterName);
                          

                          And another cache .... you get the picture I am sure.
                           cacheManager = new CacheManager("TestListsCache", configFileName, clusterName);
                          


                          When I run separate applications on the same lap top I get the following two consoles. Notice that though the one attached the pojo - the other does not find it.
                          Jan 6, 2009 12:48:03 PM com.lm.cache.CacheManager createCache
                          INFO: creating cache with META-INF/total-replication-cache-service.xml in cluster, cache name Equipment-Cluster,EquipmentCache
                          Jan 6, 2009 12:48:05 PM com.lm.cache.CacheManager createCache
                          INFO: Printout of configuration:
                          org.jboss.cache.config.Configuration@6530b8c5
                          log4j:WARN No appenders could be found for logger (org.jboss.cache.factories.ComponentRegistry).
                          log4j:WARN Please initialize the log4j system properly.
                          
                          -------------------------------------------------------
                          GMS: address is 127.0.0.1:1836
                          -------------------------------------------------------
                          Jan 6, 2009 12:48:10 PM com.lm.dataModel.EquipmentHierarchy <init>
                          INFO: In constructor of the tree manager.
                          Jan 6, 2009 12:48:10 PM com.lm.cache.CacheManager findObjectInCache
                          SEVERE: did NOT find / with transformedName / in cache name EquipmentCache
                          Jan 6, 2009 12:48:10 PM com.lm.dataModel.EquipmentHierarchy createNode
                          INFO: This new node is a root node - name is /
                          Jan 6, 2009 12:48:11 PM com.lm.cache.CacheManager findObjectInCache
                          SEVERE: did NOT find / with transformedName / in cache name EquipmentCache
                          Jan 6, 2009 12:48:11 PM com.lm.cache.CacheManager attachObjectToCache
                          INFO: did attach object class com.lm.dataModel.EquipmentItemNode / to name / in cache name EquipmentCache with fqn of /__JBossInte
                          rnal__/_ID_/3l5o5c71-j125gs-fpmuul9v-1-fpmuul9v-2


                          The other console has: The idea is the constructor attempts to find the root node (in this case a "/") in the given cache name. If it does not find it, it will do an attach. In pojo 2, the first one did not find the root node - and so it created/attached it to the cache. Then the next application DID find the root node. In this manner, it did not mater which application ran first - their constructors of the pojo held in the cache did all the magic. I think you get the idea.
                          Jan 6, 2009 12:52:52 PM com.lm.cache.CacheManager createCache
                          INFO: creating cache with META-INF/total-replication-cache-service.xml in cluster, cache name Equipment-Cluster,EquipmentCache
                          Jan 6, 2009 12:52:52 PM com.lm.cache.CacheManager createCache
                          INFO: Printout of configuration:
                          org.jboss.cache.config.Configuration@52a94ae3
                          
                          -------------------------------------------------------
                          GMS: address is 127.0.0.1:1847
                          -------------------------------------------------------
                          Jan 6, 2009 12:52:53 PM com.lm.dataModel.EquipmentHierarchy <init>
                          INFO: In constructor of the tree manager.
                          Jan 6, 2009 12:52:53 PM com.lm.cache.CacheManager findObjectInCache
                          SEVERE: did NOT find / with transformedName / in cache name EquipmentCache
                          


                          Now (with pojo 3) the second application does not see the pojo created by the first - so we aren't really sharing the same cache. Do you have any ideas on what has changed? Thank you again for your diligence!


                          • 10. Re: Moving to Pojo 3 from pojo 2 and attach fails
                            adrigan

                            I got it working by using the config2to3.bat on my old xml file as suggested early on.

                            Thank you for all your help.