Hi Jonathan,

You make many great points, and I really like the feedback;  as I have
previously said in another post, my FatKey pattern is up and running on our
production site (kiko.com).  SUPERFICIALLY, I see nothing happening out of
the ordinary, but like you said, it's most likely because my pattern is
almost tailored to Weblogic's app server (hence I guess my pattern isn't
really vendor-neutral) AND my pattern is really tailored to my bean
architecture (hence my pattern may not be even implementation-neutral!)  But
I do want comments like yours to try to poke holes in my little
experiment... better to have us discover errors through discussion than
through practice, right?

I wholehearted agree with you that hashCode and equals functions are very
difficult to implement, and that most java developers THINK they know how to
implement these functions correctly or efficiently.  In fact, if you hop
over to newsgroups.bea.com (don't worry, I won't warn the BEA dudes that
they've got an Inprise interloper!)  you'll find that a large number of
posts have to do with users not implementing these 2 functions correctly (or
not implementing them at all!)

However, I believe this is something that developers need to learn.  If one
has programmed Java, C or C++ long enough, one has come across situations
where she MUST implement hashCode and equals:  the most blatant example that
comes to mind is using a custom key class for HashMap or HashSet.  I find it
disturbing that a lot of people who BARELY understand Java try to write
EJB's and use app servers;  I find this notion ridiculous!  EJB and app
servers is NOT for beginning Java programmers.  Sure a lot of vendors try to
advertise otherwise (the bottom line is to sell as many units as possible,
right?  :-)) by having snazzy GUI bean designers and deployers, but I think
EJB is a technology that suited for intermediate to advanced developers...
hence that's why we're paid the big bucks, right?  :-)

I can see the merits of Inprise alleviating the burden of Java developers
having to implement these 2 functions by using the serialized bytes of a pk
object to intrinsically implement hashCode and equals.    However, one can
also argue that you have stripped a power user the ability, even the option,
to define how she wants to do equality and hash comparisons!  And I think
that's what the creators of Java intended:  to allow users to implement
these two functions so they can define the way they want objects to behave
in a hash container such as HashMaps and HashSets, and in our case, EJB Key
comparisons!

Finally, you do drive a good point with your final observation:  a FatKey
can slip out of a transaction from which it was created without ejbLoad
being called on it (client can call EJBObject.getPrimaryKey() and serialize
it for later use, but NOT call any business methods that will result in a
ejbLoad), and this "dirty" FatKey can slip into a subsequent transaction.
But they way I see it, and correct me if I'm wrong, the only way a Primary
key can be "reused" in a subsequent transaction is through findByPrimaryKey,
right?  So here's how I get around the stale key problem:  In my
findByPrimaryKey implementation (as opposed to my findByXXXX
implementation), even though I get a FatKey passed in from the method
argument, I recreate the FatKey again regardless of what's in the argument
FatKey and return that to the container!  Hence I guess the only really
annoyance with a FatKey across transactions is that FatKey is, well, fat
(and takes up memory)!   But in my architecture I aways invoke business
methods from the collection of EJBObjects I get from a findByXXX, AND I
never really store a Primary Key for outside the transaction usage (I would
store the Handle instead), so I managed to avoid this possible "loophole".

Gene

-----Original Message-----
From: A mailing list for Enterprise JavaBeans development
To: [EMAIL PROTECTED]
Sent: 9/6/00 5:19 PM
Subject: Re: FatKey Pattern...  was:  Does it ever make sense to
putamulti-bean-retur ningfindmethodin an entity bean?

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".

===========================================================================
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".

Reply via email to