6 Replies Latest reply on Nov 8, 2004 11:09 PM by sdanig

    Maintaining consistent object graph

    sdanig

      I added the following code to the Address class included with JBossCacheAop:

      int id = -1;
       public int getId() {
       return this.id;
       }
       public void setId(int id) {
       this.id = id;
       }
       public boolean equals(Object o) {
       if(!(o instanceof Address)) return false;
       return ((Address)o).getId() == this.getId();
       }
       public int hashCode() {
       return id;
       }


      Basically it's just an extra ID property that is used to determine equality. With this extra code, I was expecting JBossCacheAop to be intelligent about maintaining my object graph for me:

      bsh % import org.jboss.cache.aop.*;
      bsh % import org.jboss.test.cache.test.standAloneAop.*;
      bsh % TreeCacheAop tree = new TreeCacheAop();
      bsh % tree.startService();
      bsh % Person joe = new Person();
      bsh % Person mary = new Person();
      bsh % Address addr = new Address();
      bsh % addr.setId(1);
      bsh % joe.setAddress(addr);
      bsh % mary.setAddress(addr);
      bsh % System.out.println(joe.getAddress() == mary.getAddress());
      true
      bsh % Address addr2 = new Address();
      bsh % addr2.setId(1);
      bsh % joe.setAddress(addr2);
      bsh % System.out.println(joe.getAddress() == mary.getAddress());
      false


      I was expecting that last false to be true.

      Basically, I make two Person instances, joe and mary, both using the same Address instance. If I modify that Address instance, the modification is visible from both joe and mary, as expected. However, if I create a new Address with the same ID as the first one, such that addr.equals(addr2) returns true, and assign it to one of the two people, then the other person still references the old address.

      I had expected the object as a whole to be replaced throughout the object graph, given that they are "equal". Am I doing something wrong, or is this functionality not implemented?

      Thanks in advance,

      Daniel

        • 1. Re: Maintaining consistent object graph

          Daniel,

          This is a good question. However, I'd say this is an expected behavior.

          Think of it as in Java. Even if your addr and addr2 are equal, doesn't mean they are the same object instance. Therefore, if you do mary.setAddree(addr1), then joe and mary will own different address instances.

          And this is the behavior in TreeCacheAop now of object identity. Track only the reference but not based object equality.

          -Ben

          • 2. Re: Maintaining consistent object graph
            belaban

            Use equals() rather than ==

            Bela

            • 3. Re: Maintaining consistent object graph
              sdanig

              The end goal is not for that last false to be true, so it's not enough for me to just change that portion of the code. The end goal is that when I implement custom equality logic in my domain objects, the cache uses that logic to ensure that only the most recent instance of any given domain object is ever in the cache, regardless of how many other domain objects reference them. Testing whether the two addresses were equal using == rather than .equals() was just a way of verifying that.

              Basically, if Joe and Mary and their shared Address are in the cache, but I reload Mary (and her Address) from the database and stick her in the cache again, I need Joe to automatically reference the newer Address that Mary references.

              If I were to modify the JBossCache source to behave this way, what class(es) would I need to look at?

              • 4. Re: Maintaining consistent object graph
                sdanig

                I've been looking through the code a little. Here's a question for someone more knowledgeable than I: Given the described scenario, what if all my domain objects extend some common superclass DomainObject, and I add the DomainObject class to the Set of immediates (primitives) in org.jboss.cache.aop.CachedType? I assume my domain objects will be cached at the domain object level, rather than being deflated into the primitives of which they are composed (Strings, ints, booleans, etc).

                Does this give me the cache consitency behaviour described earlier in this thread?

                • 5. Re: Maintaining consistent object graph
                  twundke

                  Daniel,
                  To be honest your problem is one of general data/object structures, not the cache. As Ben already pointed out, you're asking the cache to do something different than what plain old Java does. Personally, I think the cache should retain the same semantics as Java (ie. placing two different objects into the cache will always result in two different objects being retrieved from the cache).

                  In order to do what you're asking you're going to have to change your data/object structure. This is the best way, as then your code won't break when you suddenly take away the cache. So, for example, you could simply store the address ID in the Person object, and then use that to look up the actual Address object. This could potentially all be handled by the Person object itself (looking up the Address object when getAddress() is called), hiding the details from the caller.

                  Thinking along a general data structures line will lead you to a much more robust solution.

                  Tim

                  • 6. Re: Maintaining consistent object graph
                    sdanig

                    Tim -

                    I can see that it might be implemented as you say, and I've no doubt that keeping only identifiers or proxy references would solve the problem, but the requirement that we cache only the latest version of the domain objects arises directly from the fact that we have to cache them in the first place. In a nutshell, each client maintains a very interconnected graph of domain objects, subgraphs of which get sent to the server to be persisted by Hibernate. If the graph is not consistent, Hibernate will barf, as it should. If we were not caching on the client, we would not have to solve this problem. As far as I can tell, this places the responsibility more on the cache than on the objects comprising the problem domain. If we stop using the cache, then yes, the graph consistency semantics disappear, but that is exactly what we want (I think).

                    Anyways, it looks like JBossCache may not be the ideal solution to this problem. If anyone has any suggestions I would appreciate them! And thanks for taking the time to read my posts...

                    Daniel