4 Replies Latest reply on Jul 16, 2008 2:24 PM by rahulkumarc

    JBoss Cache Issue

      We are using jboss cache (Tree cache) to cache our objects in all our products. We are facing a critical issue. After saving an object to the jboss cache using put method and retrieving the object from jboss cache using get method and changing the state of the object, the state of the object inside the jboss cache is also getting modified. According to the jboss cache documentation the state of the object inside the cache should not be modified until I call put method.

      I am forwarding a test case

      Test Case
      ------------

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

      import org.jboss.cache.PropertyConfigurator;
      import org.jboss.cache.TreeCache;

      public class TestCache {

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

      List l1 = new ArrayList();
      List l2 = new ArrayList();

      l2.add("One");
      l2.add("Two");
      l2.add("Three");

      l1.add(l2);

      TreeCache jbossCache = null;
      try {
      jbossCache = new TreeCache();
      PropertyConfigurator config = new PropertyConfigurator();
      config.configure(jbossCache, "C:\\jboss_cache.xml");
      jbossCache.startService();
      }
      catch(Exception ex) {
      System.out.println(ex);
      }

      jbossCache.put("fqn", "ListInList", l1);
      System.out .println("l1 : "+l1.hashCode());

      List l3 = (List) jbossCache.get("fqn","ListInList");
      System.out .println("l3 : "+l3.hashCode());

      for (Iterator i = l3.iterator(); i.hasNext(); ){
      List l4 = (List) i.next();
      for (Iterator i1 = l4.iterator(); i1.hasNext(); ){
      String str = (String) i1.next();
      System.out .println(str);
      }
      }

      List l5 = (List)l3.get(0);
      l5.remove(1);

      List l6 = (List) jbossCache.get("fqn","ListInList");
      System.out .println("l6 : "+l6.hashCode());

      for (Iterator i2 = l6.iterator(); i2.hasNext(); ){
      List l7 = (List) i2.next();
      for (Iterator i3 = l7.iterator(); i3.hasNext(); ){
      String str = (String) i3.next();
      System.out .println(str);
      }
      }
      }
      }

      Configuration File
      ---------------------

      <?xml version="1.0" encoding="UTF-8"?>

      <!-- ===================================================================== -->
      <!-- -->
      <!-- ECMF Base TreeCache Service Configuration -->
      <!-- -->
      <!-- ===================================================================== -->






      <!-- ==================================================================== -->
      <!-- Defines TreeCache configuration -->
      <!-- ==================================================================== -->



      jboss:service=Naming
      jboss:service=TransactionManager

      <!--
      Configure the TransactionManager
      -->

      org.jboss.cache.GenericTransactionManagerLookup



      <!--
      Node locking scheme:
      OPTIMISTIC
      PESSIMISTIC (default)
      -->
      PESSIMISTIC

      <!--
      Note that this attribute is IGNORED if your NodeLockingScheme above is OPTIMISTIC.

      Isolation level : SERIALIZABLE
      REPEATABLE_READ (default)
      READ_COMMITTED
      READ_UNCOMMITTED
      NONE
      -->
      READ_COMMITTED

      <!--
      Valid modes are LOCAL
      REPL_ASYNC
      REPL_SYNC
      INVALIDATION_ASYNC
      INVALIDATION_SYNC
      -->
      REPL_SYNC

      <!--
      Just used for async repl: use a replication queue
      -->
      false

      <!--
      Replication interval for replication queue (in ms)
      -->
      0

      <!--
      Max number of elements which trigger replication
      -->
      0

      <!-- Name of cluster. Needs to be the same for all clusters, in order
      to find each other
      -->
      @cache_cluster_name@

      <!-- JGroups protocol stack properties. Can also be a URL,
      e.g. file:/home/bela/default.xml

      -->



      <!-- UDP: if you have a multihomed machine,
      set the bind_addr attribute to the appropriate NIC IP address, e.g bind_addr="192.168.0.2"
      -->
      <!-- UDP: On Windows machines, because of the media sense feature
      being broken with multicast (even after disabling media sense)
      set the loopback attribute to true -->
      <UDP mcast_addr="228.1.2.3" mcast_port="48866" ip_ttl="64"
      ip_mcast="true" mcast_send_buf_size="150000"
      mcast_recv_buf_size="80000" ucast_send_buf_size="150000"
      ucast_recv_buf_size="80000" loopback="false" />
      <PING timeout="2000" num_initial_members="3" up_thread="false"
      down_thread="false" />
      <MERGE2 min_interval="10000" max_interval="20000" />
      <!-- <FD shun="true" up_thread="true" down_thread="true" />-->
      <FD_SOCK />
      <VERIFY_SUSPECT timeout="1500" up_thread="false"
      down_thread="false" />
      <pbcast.NAKACK gc_lag="50"
      retransmit_timeout="600,1200,2400,4800" max_xmit_size="8192"
      up_thread="false" down_thread="false" />
      <UNICAST timeout="600,1200,2400" window_size="100"
      min_threshold="10" down_thread="false" />
      <pbcast.STABLE desired_avg_gossip="20000" up_thread="false"
      down_thread="false" />
      <FRAG frag_size="8192" down_thread="false" up_thread="false" />
      <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
      shun="true" print_local_addr="true" />
      <pbcast.STATE_TRANSFER up_thread="true" down_thread="true" />




      <!--
      Whether or not to fetch state on joining a cluster
      NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
      -->
      true

      <!--
      The max amount of time (in milliseconds) we wait until the
      initial state (ie. the contents of the cache) are retrieved from
      existing members in a clustered environment
      -->
      20000

      <!--
      Number of milliseconds to wait until all responses for a
      synchronous call have been received.
      -->
      20000

      <!-- Max number of milliseconds to wait for a lock acquisition -->
      150


      <!-- Name of the eviction policy class. -->

      org.jboss.cache.eviction.LRUPolicy

      <!-- Specific eviction policy configurations. This is LRU -->


      5
      <!-- Cache wide default -->

      5000
      1000


      5000
      1000


      5
      4





      <!--
      Indicate whether to use region based marshalling or not. Set this to true if you are running under a scoped
      class loader, e.g., inside an application server. Default is "false".
      -->
      false




      <!-- Uncomment to get a graphical view of the TreeCache MBean above -->
      <!-- -->
      <!-- jboss.cache:service=TreeCache-->
      <!-- jboss.cache:service=TreeCache-->
      <!-- -->




      Can you please give us any solution / suggestion?

      --Rahul

        • 1. Re: JBoss Cache Issue
          manik

          I don't see anything wrong with this. This is expected behaviour.

          You have a reference to an object (a List) and you make some changes to it. Everyone who has a reference to that object will see those changes.

          In JBC, changes are not replicated or persisted until you call cache.put().

          • 2. Re: JBoss Cache Issue

            If you see the test case i have previous post.

            I am persisting a list(l1) into cache using cache.put method and retrieving the list from the cache using the cache.get method and modify the state of the object. The modified list is NOT persisted back to the cache, but the state of the object in the cache is automatically getting modified even though i have not explicitly called the cache .put method.

            • 3. Re: JBoss Cache Issue
              manik

              There is no magic here - just Java object references. :-) It is not the cache's role to provide defensive copies. If you need a defensive copy, I'd suggest you make your own defensive copy - though this may be expensive depending on list size.

              • 4. Re: JBoss Cache Issue

                TreeCache is a tree-structured, replicated, transactional cache from JBoss Cache.

                Being a transactional cache the state of the object in the cache should not be changed until we call cache.put method which should be part of the transaction and transaction is successful.

                Where as we pass the object reference from the service-tier to web-tier and state of the object is changed in the web-tier transaction where the tree cache is not a part of it and the state of the object changes in the cache also.

                Is this expected behavior?