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

Pete Muir pmuir at redhat.com
Thu Oct 20 07:22:56 EDT 2011


Good point.

Anyone want to take a stab at it?

On 20 Oct 2011, at 05:46, Mark Struberg wrote:

> Oki, I think the outcome and problematic is now pretty much clear, right?
> 
> I think we at least need to add some wording to make people aware of the problematic, isn't?
> 
> 
> LieGrue,
> strub
> 
> 
> 
> ----- Original Message -----
>> From: Stuart Douglas <sdouglas at redhat.com>
>> To: Arne Limburg <arne.limburg at openknowledge.de>
>> Cc: "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
>> Sent: Wednesday, October 19, 2011 11:50 PM
>> Subject: Re: [cdi-dev] calling 'equals' on a proxy?
>> 
>> 
>> On 20/10/2011, at 1:13 AM, Arne Limburg wrote:
>> 
>>> 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.
>> 
>> Considering that this is the main purpose of the equals() / hashCode() methods, 
>> I can't see what we gain by specifing them. A mutable hashCode is not really 
>> of any use to anyone, and I don't think that forcing people to implement 
>> their equals methods in a special way to satisfy CDI is a good idea either. 
>> Inexperienced java programmers already seem to have enough trouble implementing 
>> equals() properly as it is. 
>> 
>> I am not adverse to adding some kind of static method to unwrap proxies, this 
>> can also be useful for reading private fields from contextual references. 
>> 
>> Have their actually been any requests for this to be specified? I can't help 
>> thinking that if you are using contextual instances as hash map keys you are 
>> doing something wrong.
>> 
>> Stuart
>> 
>>> 
>>> 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
>>> 
>>> _______________________________________________
>>> 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
>> 
> 
> _______________________________________________
> 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