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();}
}
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