All,
 
We ran into a problem where our Entity cache was getting corrupted and findBy's were returning a bean other than the one we queried for.  With "Optimized" set to true in standardjboss.xml, we were re-using a PrimaryKey for multiple findByPrimaryKey calls. 
 
// pseudo code
---begin transaction
 
public ArrayList getMoney(long[] listOfIds)
{
ArrayList rtn = new ArrayList();
MoneyPK pk = new MoneyPK(0);  // create an instance of a primary key
for (int i = 0; i < listOfIds.length; i++)
{
    pk.id = listOfIds[i];
    Money m = home.findByPrimaryKey(pk);
    rtn.add(m);
}
}
 
// end pseudo code
 
Because parameters are not being copied(Optimized = false), the instance of the PrimaryKey I pass into findByPrimaryKey is being shared by multiple different CacheKeys that are supposed to reference different Entities.  This same instance of PrimaryKey is being shared by CacheKey.id and EnterpriseContext.id.  So when I loop in the code about, the shared primary key is changed with each loop of our code.
 
This problem could be avoided if the CacheKey constructor made a copy of the id passed into it.
 
    public CacheKey(Object id) {
      
       if (id == null) throw new Error("id may not be null");
        
       this.id = null;
       
  try {
   
   // Equals rely on the MarshalledObject itself
   mo =  new MarshalledObject(id);
   this.id = mo.get(); // make copy of id   
   // Precompute the hashCode (speed)
         hashCode = mo.hashCode();
     }
  catch (Exception e) {e.printStackTrace();}
 }
 
IMHO, this is the right and safe way to do it.  I'm going to change CacheKey, test changes, and commit if no one objects.  I'm also going to change CacheKey so that it's member variables are immutable(make variable private and provide only get methods).
 
Regards,
Bill

Reply via email to