0 Replies Latest reply on Apr 12, 2002 6:18 AM by paulnicklin

    CMP Finders methods not "concurrency Safe"? (2.4.3)

    paulnicklin

      Hi all,
      We're seeing an occasional problem where two calls to finder methods made 'simultaneously' from different instances of a session bean result in each being returned a different remote object, but referring to the same data.

      This would not ordinarily be a big problem (you're concurrency/ optimistic locking system will prevent the second update conflicting)

      But in our case this entity bean is supporting the High-Low pattern for giving out unique IDs, so two Customers with the same key fails! (Won't go into detail, but basically you have a table with "UniqueID Name", "Unique ID NextValue" and you use this and another number to give all your objects a unique ID - I'd give you a URL but I don't have one- sorry!)

      A bit of digging in the entity cache code (Isn't open source wonderful!) says to me that if the row isn't in the cache then two threads will run through the code saying...

      "Is the row in the cache?"
      "NO! - I'll go fetch it"
      "Here's the row from the database, lets put it in the cache"
      "Here you go client, have a reference to the entity"

      now, both call the getNextValue method and get the next value and update the database - but because they are not the same instance in they both update the database to the same next value.

      (Extract from CMPPersistenceManager.java)

      public Object findEntity(Method finderMethod, Object[] args, EntityEnterpriseContext ctx)
      throws Exception {
      // For now only optimize fBPK
      if (finderMethod.getName().equals("findByPrimaryKey"))
      {
      Object key = ctx.getCacheKey();
      if (key == null)
      {
      key = ((EntityCache)con.getInstanceCache()).createCacheKey(args[0]);
      }
      if (con.getInstanceCache().isActive(key))
      {
      return key; // Object is active -> it exists -> no need to call finder
      }
      }

      // The store will find the entity and return the primaryKey
      Object id = store.findEntity(finderMethod, args, ctx);

      // We return the cache key
      return ((EntityCache) con.getInstanceCache()).createCacheKey(id);
      }


      I'd suggest we check after calling the finder that the object is STILL Not in the cache, reducing the window of opportunity for duplication...


      Thanks for your perseverance in reading this far - any comments? Am I completely up the wrong tree?

      Suggestions welcome...

      Paul Nicklin