7 Replies Latest reply on Sep 1, 2005 9:01 PM by ben.wang

    A simple example of self-referencing objects problem

    roginsky

      I have a very simple example that illustrates the problem I described in my previous question (Posted: Fri Aug 19, 2005 21:08 PM Post subject: Problem with caching an object with a complex object graph).

      Here is the cached class:
      --------------------------------------------------------------------
      package cachetest;

      import java.util.ArrayList;
      import java.util.List;

      public class MySimpleObject {

      private String id = null;
      private List decendants = new ArrayList(); // reference to objects of the same class

      public String getId() {
      return id;
      }

      public void setId(String anID) {
      id = anID;
      }

      public MySimpleObject setCrossReferences() {
      MySimpleObject retVal = new MySimpleObject();
      retVal.setId(getId() + "_copy");
      decendants.add(retVal);
      return retVal;
      }
      }
      --------------------------------------------------------------------
      And the test:
      --------------------------------------------------------------------
      package cachetest;

      import org.jboss.cache.PropertyConfigurator;
      import org.jboss.cache.aop.TreeCacheAop;
      import org.jboss.cache.Fqn;

      public class SelfReferencingObjectsCacheTest {

      public static void main(String[] args) throws Exception {

      TreeCacheAop cache = new TreeCacheAop();
      PropertyConfigurator config = new PropertyConfigurator();
      config.configure(cache, "tree-cache.xml");
      cache.startService();

      try {
      MySimpleObject o = new MySimpleObject();
      o.setId("1");
      cache.putObject(Fqn.fromString("/MyObject/1"), o);

      MySimpleObject newObject = o.setCrossReferences();
      cache.putObject(Fqn.fromString("/MyObject/" + newObject.getId()), newObject);
      }
      catch (Exception e) {
      e.printStackTrace();
      }
      }
      }

      I aspectize MySimpleObject class using Aopc (it generates a "get" and "set" class per each property, so seems to be working properly).

      --------------------------------------------------------
      And the stack trace:
      --------------------------------------------------------
      java.lang.RuntimeException: InternalDelegate.incrementRefCount(): REF_COUNT for reference counting is null at: /__JBossInternal__/MyObject/1/decendants/0
      at org.jboss.cache.aop.InternalDelegate.incrementRefCount(InternalDelegate.java:73)
      at org.jboss.cache.aop.TreeCacheAopDelegate.addRefFqn(TreeCacheAopDelegate.java:592)
      at org.jboss.cache.aop.TreeCacheAopDelegate.getObjectGraphInternalFqn(TreeCacheAopDelegate.java:571)
      at org.jboss.cache.aop.TreeCacheAopDelegate.handleObjectGraph(TreeCacheAopDelegate.java:513)
      at org.jboss.cache.aop.TreeCacheAopDelegate._putObject(TreeCacheAopDelegate.java:171)
      at org.jboss.cache.aop.TreeCacheAop._putObject(TreeCacheAop.java:376)
      at org.jboss.cache.aop.TreeCacheAop.putObject(TreeCacheAop.java:255)
      at cachetest.SelfReferencingObjectsCacheTest.main(SelfReferencingObjectsCacheTest.java:22)
      org.jboss.util.NestedRuntimeException: TreeCacheAop.putObject(): ; - nested throwable: (java.lang.RuntimeException: InternalDelegate.incrementRefCount(): REF_COUNT for reference counting is null at: /__JBossInternal__/MyObject/1/decendants/0)
      at org.jboss.cache.aop.TreeCacheAop.putObject(TreeCacheAop.java:270)
      at cachetest.SelfReferencingObjectsCacheTest.main(SelfReferencingObjectsCacheTest.java:22)
      Caused by: java.lang.RuntimeException: InternalDelegate.incrementRefCount(): REF_COUNT for reference counting is null at: /__JBossInternal__/MyObject/1/decendants/0
      at org.jboss.cache.aop.InternalDelegate.incrementRefCount(InternalDelegate.java:73)
      at org.jboss.cache.aop.TreeCacheAopDelegate.addRefFqn(TreeCacheAopDelegate.java:592)
      at org.jboss.cache.aop.TreeCacheAopDelegate.getObjectGraphInternalFqn(TreeCacheAopDelegate.java:571)
      at org.jboss.cache.aop.TreeCacheAopDelegate.handleObjectGraph(TreeCacheAopDelegate.java:513)
      at org.jboss.cache.aop.TreeCacheAopDelegate._putObject(TreeCacheAopDelegate.java:171)
      at org.jboss.cache.aop.TreeCacheAop._putObject(TreeCacheAop.java:376)
      at org.jboss.cache.aop.TreeCacheAop.putObject(TreeCacheAop.java:255)
      ... 1 more


      If I don't aspectize the class, but declare is "Serializable", this example works, I don't get an exception.

        • 1. Re: A simple example of self-referencing objects problem

          Can you download the latest in JBossCache cvs module (1.2.4Alpha)? I have refactored the object graph model so I think that should solve your problem.

          Thanks,

          -Ben

          • 2. Re: A simple example of self-referencing objects problem

            This has more explanation why the refactoring.

            • 3. Re: A simple example of self-referencing objects problem
              roginsky

              Ben, thanks so much! I couldn't find tag (or branch) 1.2.4Alpha in JBossCache, so I'm going to download the latest. Any word on when 1.2.4 is going to be released?

              • 4. Re: A simple example of self-referencing objects problem

                It scheduled for next month.

                • 5. Re: A simple example of self-referencing objects problem
                  roginsky

                  I downloaded the latest code, and it solved the problem I had, but I ran into a new problem.
                  I added a single field to MySimpleObject class:

                  private StatusEnum status = StatusEnum.OPEN;

                  where StatusEnum is:

                  public enum StatusEnum {
                  OPEN,
                  CLOSE
                  }

                  When I attempt to change this field's value like this:
                  status = StatusEnum.CLOSE; (after MySimpleObject is cached), I get this exception:

                  java.lang.RuntimeException: TreeCacheAopDelegate.putObject(). There is existing pojo under fqn /MyObject/1/status Operation not allowed.
                  at org.jboss.cache.aop.TreeCacheAopDelegate.retrieveCurrentValue(TreeCacheAopDelegate.java:103)
                  at org.jboss.cache.aop.TreeCacheAopDelegate._putObject(TreeCacheAopDelegate.java:152)
                  at org.jboss.cache.aop.TreeCacheAop._putObject(TreeCacheAop.java:371)
                  at org.jboss.cache.aop.TreeCacheAop.putObject(TreeCacheAop.java:222)
                  at org.jboss.cache.aop.CacheInterceptor.invoke(CacheInterceptor.java:97)
                  at org.jboss.aop.joinpoint.FieldWriteInvocation.invokeNext(FieldWriteInvocation.java:51)
                  at cachetest.MySimpleObject.status_w_$aop(MySimpleObject.java)
                  at cachetest.MySimpleObject.setCrossReferences(MySimpleObject.java:24)
                  at cachetest.SelfReferencingObjectsCacheTest.main(SelfReferencingObjectsCacheTest.java:21)

                  There seems to be a restriction preventing me from changing a cached field. Is it a temporary restriction (there is a TODO comment in the code). If it's permanent, is there any work around?

                  Thanks a lot for all your help!

                  Just in case, this is the new MySimpleObject.java:
                  ---------------------------------------------------------
                  package cachetest;

                  import java.util.ArrayList;
                  import java.util.List;

                  public class MySimpleObject {

                  private String id = null;
                  private StatusEnum status = StatusEnum.OPEN;
                  private List decendants = new ArrayList(); // reference to objects of the same class

                  public String getId() {
                  return id;
                  }

                  public void setId(String anID) {
                  id = anID;
                  }

                  public MySimpleObject setCrossReferences() {
                  MySimpleObject retVal = new MySimpleObject();
                  retVal.setId(getId() + "_copy");
                  decendants.add(retVal);
                  status = StatusEnum.CLOSE;
                  return retVal;
                  }
                  }

                  • 6. Re: A simple example of self-referencing objects problem

                    Yes, there is an outstanding Jira for this:
                    http://jira.jboss.com/jira/browse/JBCACHE-246

                    I will fix it within one week. Temp work around is do a removeObject and putObject again, alhtough I know it is a bit painful.

                    -Ben

                    • 7. Re: A simple example of self-referencing objects problem

                      JBCACHE-246 is resolved. Please download the latest code after 24 hours and try it again to see if it solves your problem now.

                      Beta is scheduled for week of 9/12.