Re: calling 'equals' on a proxy?

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Mark Struberg
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?

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?
5.) Should we at least specify that 'non portable behaviour results'?


LieGrue,
strub



----- Original Message -----

> From: Pete Muir <[hidden email]>
> To: Mark Struberg <[hidden email]>
> Cc: [hidden email]; Stuart Douglas <[hidden email]>
> 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
>>  [hidden email]
>>  https://lists.jboss.org/mailman/listinfo/cdi-dev
>


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Stuart Douglas-2

If the 'other' instance is also a proxy, then both proxies will by definition be equal, as they will always resolve to the same underlying bean (as they are both being accessed by the same thread, that will have the same contexts active).

Anything we specify here is going to break the transitive behaviour of equals, consider we have a proxy A and normal class instantiated with new B.

The normal class B has absolutely no knowledge of proxies, so will always compare the proxy instances fields directly, if we have the proxy forwarding the equals call to the underlying bean then you may end up with a situation where A.equals(B) is true, but B.equals(A) is false.

HashCode has similar problems, if the proxy forwards it to the underlying bean, then the hash code will change as the underlying bean changes.

I think we should specify that non-portable behaviour results, and tell people not to put proxies into a HashMap.

Stuart
 

On 19/10/2011, at 4:17 AM, Mark Struberg 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?
>
> 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?
> 5.) Should we at least specify that 'non portable behaviour results'?
>
>
> LieGrue,
> strub
>
>
>
> ----- Original Message -----
>> From: Pete Muir <[hidden email]>
>> To: Mark Struberg <[hidden email]>
>> Cc: [hidden email]; Stuart Douglas <[hidden email]>
>> 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
>>>   [hidden email]
>>>   https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Rick Hightower
In reply to this post by Mark Struberg
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...)

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.

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


On Tue, Oct 18, 2011 at 10:17 AM, Mark Struberg <[hidden email]> 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?

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?
5.) Should we at least specify that 'non portable behaviour results'?


LieGrue,
strub



----- Original Message -----
> From: Pete Muir <[hidden email]>
> To: Mark Struberg <[hidden email]>
> Cc: [hidden email]; Stuart Douglas <[hidden email]>
> 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
>>  [hidden email]
>>  https://lists.jboss.org/mailman/listinfo/cdi-dev
>


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev



--
Rick Hightower
(415) 968-9037
Profile 


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Pete Muir
Administrator

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 <[hidden email]> 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 <[hidden email]>
> > To: Mark Struberg <[hidden email]>
> > Cc: [hidden email]; Stuart Douglas <[hidden email]>
> > 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
> >>  [hidden email]
> >>  https://lists.jboss.org/mailman/listinfo/cdi-dev
> >
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>
>
> --
> Rick Hightower
> (415) 968-9037
> Profile
>


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Rick Hightower
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]>
> > To: Mark Struberg <[hidden email]>
> > Cc: [hidden email]; Stuart Douglas <[hidden email]>
> > 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
> >>  [hidden email]
> >>  https://lists.jboss.org/mailman/listinfo/cdi-dev
> >
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>
>
> --
> Rick Hightower
> <a href="tel:%28415%29%20968-9037" value="+14159689037">(415) 968-9037
> Profile
>




--
Rick Hightower
(415) 968-9037
Profile 


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Rick Hightower
In reply to this post by Stuart Douglas-2


On Tue, Oct 18, 2011 at 12:06 PM, Stuart Douglas <[hidden email]> wrote:

If the 'other' instance is also a proxy, then both proxies will by definition be equal, as they will always resolve to the same underlying bean (as they are both being accessed by the same thread, that will have the same contexts active).

They are not comparing two normal objects they are comparing an object and an instance. We are defining how proxies equals work, which is to get the underlying real object and compare it to the incoming real object or the real object from the proxy.
 

Anything we specify here is going to break the transitive behaviour of equals, consider we have a proxy A and normal class instantiated with new B.

The normal class B has absolutely no knowledge of proxies, so will always compare the proxy instances fields directly, if we have the proxy forwarding the equals call to the underlying bean then you may end up with a situation where A.equals(B) is true, but B.equals(A) is false.

Good point. So to not break this contract, we would only say that proxies can compare against other proxies. If they want to compare a proxy to a normal object they would have to use the utility methods I described earlier to unpack it. We could add an equals static method to this utility as well.

 

HashCode has similar problems, if the proxy forwards it to the underlying bean, then the hash code will change as the underlying bean changes.

But not within a Request scope or within a Session scope. I think this is ok actually. Much more so than the equals case. At least in the way people will actually use this in a web app. :)
 

I think we should specify that non-portable behaviour results, and tell people not to put proxies into a HashMap.

Stuart

Summary:


equals should only work with other client proxies, it should unpack and call equals on unpacked.

hashCode should just work, it should unpack and call hashCode on underlying object (contextual instance in spec speak right?)




 


On 19/10/2011, at 4:17 AM, Mark Struberg 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?
>
> 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?
> 5.) Should we at least specify that 'non portable behaviour results'?
>
>
> LieGrue,
> strub
>
>
>
> ----- Original Message -----
>> From: Pete Muir <[hidden email]>
>> To: Mark Struberg <[hidden email]>
>> Cc: [hidden email]; Stuart Douglas <[hidden email]>
>> 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
>>>   [hidden email]
>>>   https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev



--
Rick Hightower
(415) 968-9037
Profile 


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Stuart Douglas-2

On 19/10/2011, at 8:17 AM, Rick Hightower wrote:



On Tue, Oct 18, 2011 at 12:06 PM, Stuart Douglas <[hidden email]> wrote:

If the 'other' instance is also a proxy, then both proxies will by definition be equal, as they will always resolve to the same underlying bean (as they are both being accessed by the same thread, that will have the same contexts active).

They are not comparing two normal objects they are comparing an object and an instance. We are defining how proxies equals work, which is to get the underlying real object and compare it to the incoming real object or the real object from the proxy.
 

Anything we specify here is going to break the transitive behaviour of equals, consider we have a proxy A and normal class instantiated with new B.

The normal class B has absolutely no knowledge of proxies, so will always compare the proxy instances fields directly, if we have the proxy forwarding the equals call to the underlying bean then you may end up with a situation where A.equals(B) is true, but B.equals(A) is false.

Good point. So to not break this contract, we would only say that proxies can compare against other proxies. If they want to compare a proxy to a normal object they would have to use the utility methods I described earlier to unpack it. We could add an equals static method to this utility as well.

 

HashCode has similar problems, if the proxy forwards it to the underlying bean, then the hash code will change as the underlying bean changes.

But not within a Request scope or within a Session scope. I think this is ok actually. Much more so than the equals case. At least in the way people will actually use this in a web app. :)
 

I think we should specify that non-portable behaviour results, and tell people not to put proxies into a HashMap.

Stuart

Summary:


equals should only work with other client proxies, it should unpack and call equals on unpacked.

This also breaks the contract for equals. Also this behaviour is useless, as two client proxies will always resolve to the same underlying object. 


hashCode should just work, it should unpack and call hashCode on underlying object (contextual instance in spec speak right?)



No, a mutable hashCode is much worse than a unspecified one IMHO. The main point of hashCode is to allow objects to work in HashMaps, and this will result in completely broken behaviour. 

The way we deal with this in Weld is to use the client proxies class hashCode for hashCode (i.e. MyObject$$Proxy.class.hashCode() ), and consider proxies equal if they are both proxies for the same Bean.

Stuart



 


On 19/10/2011, at 4:17 AM, Mark Struberg 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?
>
> 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?
> 5.) Should we at least specify that 'non portable behaviour results'?
>
>
> LieGrue,
> strub
>
>
>
> ----- Original Message -----
>> From: Pete Muir <[hidden email]>
>> To: Mark Struberg <[hidden email]>
>> Cc: [hidden email]; Stuart Douglas <[hidden email]>
>> 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
>>>   [hidden email]
>>>   https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev



--
Rick Hightower
(415) 968-9037
Profile 



_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Pete Muir
Administrator
In reply to this post by Rick Hightower
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]>
> > > To: Mark Struberg <[hidden email]>
> > > Cc: [hidden email]; Stuart Douglas <[hidden email]>
> > > 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
> > >>  [hidden email]
> > >>  https://lists.jboss.org/mailman/listinfo/cdi-dev
> > >
> >
> >
> > _______________________________________________
> > cdi-dev mailing list
> > [hidden email]
> > https://lists.jboss.org/mailman/listinfo/cdi-dev
> >
> >
> >
> > --
> > Rick Hightower
> > (415) 968-9037
> > Profile
> >
>
>
>
>
> --
> Rick Hightower
> (415) 968-9037
> Profile
>


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Arne Limburg
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: [hidden email] [mailto:[hidden email]] Im Auftrag von Pete Muir
Gesendet: Mittwoch, 19. Oktober 2011 14:03
An: Rick Hightower
Cc: Stuart Douglas; [hidden email]
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]>
> > > To: Mark Struberg <[hidden email]>
> > > Cc: [hidden email]; Stuart Douglas <[hidden email]>
> > > 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
> > >>  [hidden email]
> > >>  https://lists.jboss.org/mailman/listinfo/cdi-dev
> > >
> >
> >
> > _______________________________________________
> > cdi-dev mailing list
> > [hidden email]
> > https://lists.jboss.org/mailman/listinfo/cdi-dev
> >
> >
> >
> > --
> > Rick Hightower
> > (415) 968-9037
> > Profile
> >
>
>
>
>
> --
> Rick Hightower
> (415) 968-9037
> Profile
>


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Stuart Douglas-2

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: [hidden email] [mailto:[hidden email]] Im Auftrag von Pete Muir
> Gesendet: Mittwoch, 19. Oktober 2011 14:03
> An: Rick Hightower
> Cc: Stuart Douglas; [hidden email]
> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]>
>>>> To: Mark Struberg <[hidden email]>
>>>> Cc: [hidden email]; Stuart Douglas <[hidden email]>
>>>> 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
>>>>> [hidden email]
>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>
>>>
>>>
>>> _______________________________________________
>>> cdi-dev mailing list
>>> [hidden email]
>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>
>>>
>>>
>>> --
>>> Rick Hightower
>>> (415) 968-9037
>>> Profile
>>>
>>
>>
>>
>>
>> --
>> Rick Hightower
>> (415) 968-9037
>> Profile
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Mark Struberg
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 <[hidden email]>
> To: Arne Limburg <[hidden email]>
> Cc: "[hidden email]" <[hidden email]>
> 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: [hidden email]
> [mailto:[hidden email]] Im Auftrag von Pete Muir
>>  Gesendet: Mittwoch, 19. Oktober 2011 14:03
>>  An: Rick Hightower
>>  Cc: Stuart Douglas; [hidden email]
>>  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 <[hidden email]>
> 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
> <[hidden email]> 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 <[hidden email]>
>>>>>  To: Mark Struberg <[hidden email]>
>>>>>  Cc: [hidden email]; Stuart Douglas
> <[hidden email]>
>>>>>  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
>>>>>>  [hidden email]
>>>>>>  https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>
>>>>
>>>>
>>>>  _______________________________________________
>>>>  cdi-dev mailing list
>>>>  [hidden email]
>>>>  https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>
>>>>
>>>>
>>>>  --
>>>>  Rick Hightower
>>>>  (415) 968-9037
>>>>  Profile
>>>>
>>>
>>>
>>>
>>>
>>>  --
>>>  Rick Hightower
>>>  (415) 968-9037
>>>  Profile
>>>
>>
>>
>>  _______________________________________________
>>  cdi-dev mailing list
>>  [hidden email]
>>  https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>>  _______________________________________________
>>  cdi-dev mailing list
>>  [hidden email]
>>  https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev
>

_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Pete Muir
Administrator
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 <[hidden email]>
>> To: Arne Limburg <[hidden email]>
>> Cc: "[hidden email]" <[hidden email]>
>> 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: [hidden email]
>> [mailto:[hidden email]] Im Auftrag von Pete Muir
>>> Gesendet: Mittwoch, 19. Oktober 2011 14:03
>>> An: Rick Hightower
>>> Cc: Stuart Douglas; [hidden email]
>>> 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 <[hidden email]>
>> 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
>> <[hidden email]> 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 <[hidden email]>
>>>>>> To: Mark Struberg <[hidden email]>
>>>>>> Cc: [hidden email]; Stuart Douglas
>> <[hidden email]>
>>>>>> 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
>>>>>>> [hidden email]
>>>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> cdi-dev mailing list
>>>>> [hidden email]
>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Rick Hightower
>>>>> (415) 968-9037
>>>>> Profile
>>>>>
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Rick Hightower
>>>> (415) 968-9037
>>>> Profile
>>>>
>>>
>>>
>>> _______________________________________________
>>> cdi-dev mailing list
>>> [hidden email]
>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>
>>> _______________________________________________
>>> cdi-dev mailing list
>>> [hidden email]
>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>>
>> _______________________________________________
>> cdi-dev mailing list
>> [hidden email]
>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Pete Muir
Administrator
In reply to this post by Arne Limburg
Arne, this is an excellent post.

It prompts me to ask Rick to expand on his use cases for wanting equals properly specified. Are they specific Rick? Or is this just a general feeling?

On 19 Oct 2011, at 15:13, 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.
>
> 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: [hidden email] [mailto:[hidden email]] Im Auftrag von Pete Muir
> Gesendet: Mittwoch, 19. Oktober 2011 14:03
> An: Rick Hightower
> Cc: Stuart Douglas; [hidden email]
> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]>
>>>> To: Mark Struberg <[hidden email]>
>>>> Cc: [hidden email]; Stuart Douglas <[hidden email]>
>>>> 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
>>>>> [hidden email]
>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>
>>>
>>>
>>> _______________________________________________
>>> cdi-dev mailing list
>>> [hidden email]
>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>
>>>
>>>
>>> --
>>> Rick Hightower
>>> (415) 968-9037
>>> Profile
>>>
>>
>>
>>
>>
>> --
>> Rick Hightower
>> (415) 968-9037
>> Profile
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev
Reply | Threaded
Open this post in threaded view
|

Re: calling 'equals' on a proxy?

Rick Hightower
I agree with Arne Limburg points, but not concerned enough about it to argue further (or rather I don't think I could come up with better points than Arne). I have no specific use case in mind just want the least surprise from a proxied object. I wont lose sleep if it stays as is.
 

On Thu, Oct 20, 2011 at 4:39 AM, Pete Muir <[hidden email]> wrote:
Arne, this is an excellent post.

It prompts me to ask Rick to expand on his use cases for wanting equals properly specified. Are they specific Rick? Or is this just a general feeling?

On 19 Oct 2011, at 15:13, 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.
>
> 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: [hidden email] [mailto:[hidden email]] Im Auftrag von Pete Muir
> Gesendet: Mittwoch, 19. Oktober 2011 14:03
> An: Rick Hightower
> Cc: Stuart Douglas; [hidden email]
> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]>
>>>> To: Mark Struberg <[hidden email]>
>>>> Cc: [hidden email]; Stuart Douglas <[hidden email]>
>>>> 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
>>>>> [hidden email]
>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>
>>>
>>>
>>> _______________________________________________
>>> cdi-dev mailing list
>>> [hidden email]
>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>
>>>
>>>
>>> --
>>> Rick Hightower
>>> <a href="tel:%28415%29%20968-9037" value="+14159689037">(415) 968-9037
>>> Profile
>>>
>>
>>
>>
>>
>> --
>> Rick Hightower
>> <a href="tel:%28415%29%20968-9037" value="+14159689037">(415) 968-9037
>> Profile
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev




--
Rick Hightower
(415) 968-9037
Profile 


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev