computerluca / lambdaj

Automatically exported from code.google.com/p/lambdaj
1 stars 0 forks source link

Wrong implementation of hashCode in InvocationSequence #63

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
We have encountered a problem that I suspect, after briefly reviewing the 
relevant workflow, may be triggered by a wrong implementation of hashCode in 
InvocationSequence.

The contract for hashCode includes the following axiom:

http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()

"If two objects are equal according to the equals(Object) method, then calling 
the hashCode method on each of the two objects must produce the same integer 
result.".

See the testcase in the attached patch, it demonstratest this violation. With 
that said, I would suggest to fix this issue by using the rootInvokedClass as 
an additional field in the equals-relation.

This violation of contract may cause the wrong invocationsequence to be 
returned here:

ArgumentFactory.createArgument :

T placeholder = (T) PLACEHOLDER_BY_INVOCATION.get(invocationSequence);

If two InvactionSequence points to the same bucket, they will return the same 
placeholder, regardless of them belonging to different root-classes. I Would 
consider to change the cache-key to make the code more readable?

Nevertheless, we have encontererd this error in our test-system (I have changed 
the real names due to NDA with client):

Caused by: ch.lambdaj.function.argument.InvocationException: Failed invocation 
of public org.joda.time.LocalDate ClassA.getDate() on object ClassB@3f73e02f 
caused by: object is not an instan
ce of declaring class
        at ch.lambdaj.function.argument.Invocation.invokeOn(Invocation.java:65)
        at ch.lambdaj.function.argument.Argument.evaluate(Argument.java:36)
        at ch.lambdaj.function.convert.ArgumentConverter.convert(ArgumentConverter.java:36)
        at ch.lambdaj.function.convert.ConverterIterator.next(ConverterIterator.java:37)
        at ch.lambdaj.Lambda.convert(Lambda.java:883)
        at ch.lambdaj.Lambda.collect(Lambda.java:202)

As can be seen above, the method it is trying to execute clearky belongs to a 
different class.  The error was provoked by running code like this:

Collection<ClassB> myValues = ...
return selectDistinct(collect(myValues, on(ClassB.class).getValue()));

ClassA.class is also referenced in a couple of differemt places as part of an 
on() clause.

Original issue reported on code.google.com by bjerk...@gmail.com on 15 Apr 2011 at 10:37

Attachments:

GoogleCodeExporter commented 9 years ago
Fixed in release 2.3.3

Original comment by mario.fu...@gmail.com on 22 Apr 2011 at 8:22