[cdi-dev] calling 'equals' on a proxy?

Arne Limburg arne.limburg at openknowledge.de
Wed Oct 19 10:13:47 EDT 2011


Hi,

What never will work is putting a contextual reference into a HashSet (or HashMap as key) and assuming it is a contextual instance. And maybe this should be made clear in the spec.

However the contract of java.lang.Object#hashCode() does allow that hashCode() changes its return value: The same value only must be returned "provided no information used in equals(Object) comparisons on the object is modified". Since a change of the underlying contextual instance would modify the information used in equals(Object), it would be perfectly valid, that the returned hash code would change.

So if we specify the behavior of equals and hashCode to delegate to the contextual instance the only thing we need to be aware of is the symmetric behavior of equals, so whatever we specify, the following must be true:
For any x and y, if x.equals(y) is true y.equals(x) must be true as well.
And this makes things wired, because of the following case:
Let x be the current contextual instance of the contextual reference y, then
y.equals(x) would be true, assuming the call to equals is delegated
y.equals(y) would be true, assuming the call to equals is delegated and the parameter is unproxied
x.equals(x) would be true, assuming the developer correctly implemented equals. Nothing to do here for CDI since no proxy involved.
x.equals(y) is the wired case since we are not able to unproxy y here. So for this case it depends on the implementation of equals, if the result is true. If equals only uses public methods of y then it should work otherwise it likely will return false. But according to the definition of java.lang.Object#equals (and the defined symmetry) if this returns false, y.equals(x) has to return false, too.
So the only way how this could be achieved, would be to modify the case where y.equals(x) is handled: If we would return x.equals(y) for that case, we would delegate the problem to the user implementing equals correct (with no field-access). So either we have to specify it that way (and can specify hashCode() to be delegated to the contextual instance) or we should leave it unspecified.

In addition we should provide a static method CDI.getContextualInstance(Object), so that users can handle that case where they want to put objects into HashSets or HashMaps. This method could then be used to correctly implement equals on contextual instances like:
public boolean equals(Object object) {
    object = CDI.getContextualInstance(object);
    //implement equals using field access.
}
Wdyt?

Regards,
Arne

-----Ursprüngliche Nachricht-----
Von: cdi-dev-bounces at lists.jboss.org [mailto:cdi-dev-bounces at lists.jboss.org] Im Auftrag von Pete Muir
Gesendet: Mittwoch, 19. Oktober 2011 14:03
An: Rick Hightower
Cc: Stuart Douglas; cdi-dev at lists.jboss.org
Betreff: Re: [cdi-dev] calling 'equals' on a proxy?

100% agreed ;-)

However, my issue is that not around the "will work in 99% of cases", it's around that pesky remaining 1%. If it simply didn't work in those 1% of cases, then I would be much more amenable. However, what we actually have is it *actively and knowingly breaching* the rules laid down by another specification, on which we build, in that 1% of cases, which I think it is a totally different situation. And this is not just any spec, it's the Java Language Spec, on which *everything* builds. Remaining consistent with the language is of utmost importance IMO, and users will not  forgive us for breaking the rules they use every day.

On 18 Oct 2011, at 22:08, Rick Hightower wrote:

> I would argue (and probably lose) that something that worked in 99% of cases as expected would be better than something that never does.
> 
> I will reread Stuarts arguments, but it seems to me that we can specify how equals works with client proxies.
> 
> On Tue, Oct 18, 2011 at 1:56 PM, Pete Muir <pmuir at redhat.com> wrote:
> 
> On 18 Oct 2011, at 21:42, Rick Hightower wrote:
> 
> > Currently the docs say this.... 5.4.2.
> >
> > .Behavior of all methods declared by java.lang.Object, except for 
> > toString(), is undefined for a client proxy .Portable applications 
> > should not invoke any method declared by java.lang.Object, except 
> > for toString(), on a client proxy
> >
> > I so don't agree with what is in the spec. now on this subject.
> > (Realizing that it is a work in progress...)
> 
> Not really, this is unchanged since 1.0. We don't currently have plans to change this.
> 
> >
> > I think we should change this and call the underlying implementation for these methods.
> > Also equals and hashCode should work by unpacking and comparing the contextual instance.
> 
> Please take a look at Stuart's follow up to Mark's email, he has investigated the options thoroughly, and found there is no solution that can correctly obey the rules for equals. For this reason it's better to keep it unspecified, as it warns people not to rely on this behavior.
> 
> >
> > Off topic....
> >
> > It would be nice if there was a utility API that implementations had 
> > to implement that had these methods
> >
> >
> > isProxy (lets you know if an object is a client proxy) 
> > getUnproxiedVersion (gives you the underlying unproxied version of 
> > the object)
> >
> >
> > (It may exist already.)
> 
> I don't believe there is, so file a CDI issue and we can discuss / add it. It should be relatively trivial (require any client proxy to implement an interface e.g. ClientProxy and provide a method on getUnderlying() or similar).
> 
> >
> >
> > On Tue, Oct 18, 2011 at 10:17 AM, Mark Struberg <struberg at yahoo.de> wrote:
> > Hi folks!
> >
> > There is a problem still in the chain which is a bit more trickier. It's about equals() on contextual references.
> >
> > If the 'other' instance which gets compared with is a proxy as well, then we would first need to 'unpack' it and pass the underlying contextual instance into the comparison implementation. Otherwise accessing private fields from the 'other' will actually only hit the proxy, and not the 'real' target.
> >
> > But otherwise it should work fine.
> >
> >
> > Wdyt?
> >
> > 1.) Should we specify this?
> 
> See Stuart's response, I would be very leery of requiring behavior which broke the fundamental contract of equals(). If we can't fully support the correct behavior, it's better to leave it unportable.
> 
> >
> > 2.) What is the expected behaviour?
> >
> > 3.) Do we like to specify equals() for beans at all?
> > 4.) Is there some established behaviour in other frameworks which heavily uses proxies?
> 
> Not AFAIK. We played around for ages with this in Seam and Weld, and have something that gives you 99% correct behavior, but there are still edge cases.
> 
> > 5.) Should we at least specify that 'non portable behaviour results'?
> 
> We do, see Rick's reference above.
> 
> >
> >
> > LieGrue,
> > strub
> >
> >
> >
> > ----- Original Message -----
> > > From: Pete Muir <pmuir at redhat.com>
> > > To: Mark Struberg <struberg at yahoo.de>
> > > Cc: cdi-dev at lists.jboss.org; Stuart Douglas <sdouglas at redhat.com>
> > > Sent: Monday, March 14, 2011 12:52 PM
> > > Subject: Re: [cdi-dev] calling 'equals' on a proxy?
> > >
> > > Stuart, you had this one worked out right? I believe the spec says 
> > > the behaviour is unspecified.
> > >
> > > On 7 Mar 2011, at 15:52, Mark Struberg wrote:
> > >
> > >>  Hi Pete, others!
> > >>
> > >>  Do you remember our discussion about what should happen if 
> > >> equals() gets
> > > called on a proxy?
> > >>
> > >>  Should it route to the equals method of the currently proxied instance?
> > >>
> > >>  LieGrue,
> > >>  strub
> > >>
> > >>
> > >>
> > >>  _______________________________________________
> > >>  cdi-dev mailing list
> > >>  cdi-dev at lists.jboss.org
> > >>  https://lists.jboss.org/mailman/listinfo/cdi-dev
> > >
> >
> >
> > _______________________________________________
> > cdi-dev mailing list
> > cdi-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/cdi-dev
> >
> >
> >
> > --
> > Rick Hightower
> > (415) 968-9037
> > Profile
> >
> 
> 
> 
> 
> --
> Rick Hightower
> (415) 968-9037
> Profile
> 


_______________________________________________
cdi-dev mailing list
cdi-dev at lists.jboss.org
https://lists.jboss.org/mailman/listinfo/cdi-dev



More information about the cdi-dev mailing list