Gene,
This is very interesting. I had forgotten that many EJB containers use
the equals() and hashCode() methods for primary key comparison. We do
not do this, and thus the difference. So, you may ask, why don't we
use these methods, and what do we do differently?
We don't use the user's implementation of equals() and hashCode() because
I don't trust developers to write these methods correctly. As is evidenced
by a number of threads on this topic, writing these methods correctly is
quite hard. In particular, the result of calling hashCode needs to be uniformly
distributed for optimal dictionary lookup. Particularly when dealing with
numbers, it is easy to write a hashCode method which is very much non-
uniform. For example, simply OR'ing together your numeric fields makes for
a terrible hash, typically.
(Also, as I have pointed out in a previous thread, it is legal in EJB to have
a Entity object reference as a CMP field, and thus it is legal to have such
a reference in a primary key field, and yet it is not possible to write the
hashCode/equals method on a class containing such a field.)
What do we do instead? We serialize the primary key to a chunk of bytes,
and then use internal hashCode/equals functions which runs against that
chunk of bytes. This is much faster than calling the equals/hashCode
methods, and results in a truly uniform distribution, resulting in fast
dictionary lookups, etc.
So, a question arises: which of us is breaking the rules?
I would say that you have broken a rule by writing a primary key class
which has hashCode/equals methods which are not written according to the
Java language specification. That is the equals method you have
implemented does not actually test the equality of the objects, but
only the equality of a subset of the fields. (And I admit that this
is a thin argument.)
On the other hand, you might argue that we are not compliant with the EJB
specification, in that we do not use on the user's implementation of hashCode
and equals (bugs and all), but instead use serialization for comparison
purposes. (I don't see anything in the spec to preclude what we do, of
course.)
One last point, on the use of FatKeys. What would happen if you called the
multi-object finder in one transaction, and then used the object references
in another transaction. Previously, you said that you need to clear out
the data fields in your ejbLoad method, so that ejbLoad is only called
once. This is good. But what about if ejbLoad is never called in the
finder's transaction, but only in a subsequent transaction. Here, you would
still be loading the (potentially obsolete) state. Sound like the design
pattern is still broken, but for different reasons.
-jkw
Gene Chuang wrote:
>
> Hi Jonathan,
>
> I see your concern; however I don't think my FatKey will break PrimaryKey
> comparison... the reason why I say that is I believe it comes down to how I
> implement the overloaded functions of PrimaryKey.hashCode() and
> PrimaryKey.equals()... For my "regular" custom primary key classes, these
> are overloaded to compare or hash the actual field value of the internal pk
> (longs, in my case.) My FatKeys, which extend my CustomPrimaryKey, do NOT
> overload these functions. Hence even if the "values" of my FatKeys change,
> their comparison identity does not change.
>
> Based on my logic above, I am assuming that server vendors implement
> EJBObject.isIdentical the following way:
>
> class EJBObject
> {
> boolean isIdentical(EJBObject aOtherObject)
> {
> return this.getPrimaryKey().equals(aOtherObject.getPrimaryKey());
> }
> }
>
> I think its a pretty logical assumption that most if not all vendors
> implement isIdentical this way... at least I believe Weblogic does because
> I have implemented the FatKey pattern in my architecture and aside from the
> significant performance boost, I have not witnessed any strange
> side-effects.
>
> Gene Chuang
> Teach the world. Join Kiko!
> http://www.kiko.com/profile/join.jsp?refcode=TAF-gchuang
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".