8 Replies Latest reply on Mar 29, 2007 8:02 PM by ben.wang

    PojoCache, Serializable object and cluster

    jacek187

      Question: should be changes made in simple serializable objects propagatet when using PojoCache?

      Why in prestented code testPojo fails with error:
      junit.framework.AssertionFailedError: expected:<2> but was:<1>
      and testTreeCache success?

      package org.jboss.cache.aop;
      
      import java.util.Properties;
      
      import javax.naming.Context;
      
      import junit.framework.TestCase;
      
      import org.jboss.cache.CacheException;
      import org.jboss.cache.PropertyConfigurator;
      
      public class PojoCacheSerializableTest extends TestCase {
       PojoCache cache_;
      
       PojoCache cache1_;
      
       public PojoCacheSerializableTest(String name) {
       super(name);
       }
      
       protected void setUp() throws Exception {
       super.setUp();
       Properties prop = new Properties();
       prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
       cache_ = new PojoCache();
       PropertyConfigurator config = new PropertyConfigurator(); // configure tree cache.
       config.configure(cache_, "META-INF/replSync-service.xml");
      
       cache1_ = new PojoCache();
       config.configure(cache1_, "META-INF/replSync-service.xml");
       cache_.start();
       cache1_.start();
       }
      
       protected void tearDown() throws Exception {
       super.tearDown();
       cache_.stop();
       cache1_.stop();
       }
      
       public void testPojo() throws CacheException {
       SimplePojo simplePojo = new SimplePojo();
       simplePojo.setStatus(1);
       cache_.putObject("a/b/c/d", simplePojo);
      
       SimplePojo simplePojo2 = (SimplePojo) cache1_.getObject("a/b/c/d");
       simplePojo2.setStatus(2);
       cache1_.putObject("a/b/c/d", simplePojo2);
      
       SimplePojo simplePojo3 = (SimplePojo) cache_.getObject("a/b/c/d");
       assertEquals(2, simplePojo3.getStatus());
       }
      
       public void testTreeCache() throws CacheException {
       SimplePojo simplePojo = new SimplePojo();
       simplePojo.setStatus(1);
       cache_.put("a/b/c/d", "key", simplePojo);
      
       SimplePojo simplePojo1 = (SimplePojo) cache1_.get("a/b/c/d", "key");
       simplePojo1.setStatus(2);
       cache1_.put("a/b/c/d", "key", simplePojo1);
      
       SimplePojo simplePojo2 = (SimplePojo) cache_.get("a/b/c/d", "key");
       assertEquals(2, simplePojo2.getStatus());
       }
      }
      
      



      SimplePojo
      package org.jboss.cache.aop;
      
      import java.io.Serializable;
      
      import org.jboss.cache.aop.annotation.InstanceOfPojoCacheable;
      public class SimplePojo implements Serializable{
       private int status;
       public int getStatus() {
       return status;
       }
       public void setStatus(int status) {
       this.status = status;
       }
      }
      
      


        • 1. Re: PojoCache, Serializable object and cluster

          Looks like you are interested in fine-grained, field-level replication. You are using a Serializable pojo then PojoCache will simply treat it as a coarse-grained object. What you need to do is to rid of Serializable interface but instrument the pojo first instead (via aopc, e.g.).

          Check for the examples directory under the distribution, it contains many examples for how to do that.

          • 2. Re: PojoCache, Serializable object and cluster
            jacek187

            Instrumentalization is not exactly what I need for all my objects (but for other is accepted), so question is: Is it possible to use PojoCache like TreeCache (put/get Serializable objects that will be replicated across cluster) or only instrumented objects will be replicated?
            Looks, that PojoCache put method throws an Exception, when not Serialized or instrumented object is used as argument, so if PojoCache accept Serialized object I except that this object will be replicated - no error, warning etc is throwed/logged...So maybe this is a bug?

            • 3. Re: PojoCache, Serializable object and cluster
              manik

              Are you talking about PojoCache.put() or PojoCache.putObject()?

              • 4. Re: PojoCache, Serializable object and cluster
                jacek187

                About PojoCache.putObject()PojoCache.getObject() (look into testPojo() method)

                Scenario is:
                1. PojoCache is empty
                2. Create instance of Serializable object
                3. Call PojoCache.putObject() on first cache.
                4. Get object fom second cache (object was replicated),
                4. Change something in object
                5. Because object is only serializable, put changed object back into second(PojoCache.putObject())
                6. Get object from first cache (PojoCache.getObject())
                I think, that should receive object from step 5, but i got object from step 2 (without any changes made in step 4!!!)

                ... or run presented in first post JUnit test.

                I know' that if pojo will be instrumented, changes would be replicated and step 5 is not needed), but my pojo is only serializable.
                And question: why afer first put object was replicated, but after second, third etc put object was not replicated? (And no warning/error or exception was logged?)

                • 5. Re: PojoCache, Serializable object and cluster
                  brian.stansberry

                  Just a theory: perhaps the optimization that checks if the object is already bound is seeing it's the same object and ignoring the second putObject() call? I.e. the optimization isn't being bypassed if the object isn't Advised?

                  • 6. Re: PojoCache, Serializable object and cluster
                    jacek187

                    I do some investigation and I think, that this is a bug in PojoCache (blocker in my opinion)
                    Look into TreeCacheAopDelegate._putObject method

                     if(!cache_.isMarshallNonSerializable())
                     AopUtil.checkObjectType(obj);
                    
                     if (obj == null) {
                     return cache_._removeObject(fqn, true);
                     }
                     // Skip some un-necessary update if obj is the same class as the old one
                     Object oldValue = internal_.getPojo(fqn);
                     if(oldValue == obj) return obj; // value already in cache. return right away.
                    
                    


                    if new object == oldObject mothod is leaved and nothing is in cache changed!
                    I think that this should be true only for Advised objects and for Serializable absolutly not!

                    I've checked, that if comment out this condition my test pass!!
                    But I still didn't decide to use modified code in production use, because I don't know that this change causes other unexpected effects.

                    Because this bug is stopper for my (My application is using only PojoCache, and there are many Serializable objects stored in cache. Now I can't create cluster without huge code modification) I decide to report new bug: JBCACHE-1016. I hope, that this issue will be soon resolved.

                    • 7. Re: PojoCache, Serializable object and cluster
                      brian.stansberry

                      Yep, that's the optimization I was talking about. I knew it existed but wasn't sure exactly where the code was or whether it checked for Advised.

                      I'm not sure if

                      if(oldValue == obj && obj instanceof Advised) return obj;
                      is sufficient, or if there needs to be some special handling of Collection and Map. Well, Jason can sort that one. :-)

                      Thanks for the report.

                      • 8. Re: PojoCache, Serializable object and cluster

                        Yes, that is a oversight indeed. What we do is only checking whether it is the same pojo instance during putObject. I have created a jira:
                        http://jira.jboss.com/jira/browse/JBCACHE-1017