You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
the inspection of the instance returned for the generic entity type will still see Object, not Person. If the implementation had been declared as new BeforeSaveCallback<Person>() { … }, the generics information would be available.
This lack of type information impedes selecting the correct set of entity callbacks on invocation. We currently work around this by invoking all listeners that take Object as parameters (i.e. the ones declared as lambdas) and handle the ClassCastException resulting from a potentially invalid invocation. As a CCE can also result from the callback execution in general, we have to deeply inspect the exception, which requires Java version-specific handling and has caused trouble supporting newer Java versions as apparently the internals of a CCE change frequently.
Solution
When we look up the EntityCallback instances from the BeanFactory we can fall back to inspecting the BeanDefinition for its generic type, and as that resolves to the return type used on the bean's factory method, we can use that instead of only seeing Object.
The text was updated successfully, but these errors were encountered:
odrotbohm
changed the title
Improve handling of EntityCallback bean declaration declared as lambdas
Improve handling of EntityCallback bean declarations declared as lambdas
Apr 4, 2023
In case an EntityCallback is declared as lambda expression, the JVM does not expose any generics information about the target entity type the callback shall be applied to. This commit changes the callback lookup and processing so that in case the generics information is not detectable on the type, we fall back to the BeanDefinition's resolvable type (fed by the factory method's return type which carries the necessary reflection information). That generics information is then kept in the newly introduce EntityCallbackAdapter and the code inspecting the actual entity type for matches then uses the resolvable type held in that. Also, the actual callback invocation is done on the adapter's delegate.
Removed the ability of the discoverer to register EntityCallbacks by bean name as that was not used in the public API at all and it avoids duplicating the bean definition type detection. A couple of minor additional cleanups (records for cache key, methods static where possible and with lower visibility etc.)
Fixes#2812.
Problem
In contrast to anonymous classes, lambda expressions do not carry generics information. If an entity callback is declared as Spring bean like this:
the inspection of the instance returned for the generic entity type will still see
Object
, notPerson
. If the implementation had been declared asnew BeforeSaveCallback<Person>() { … }
, the generics information would be available.This lack of type information impedes selecting the correct set of entity callbacks on invocation. We currently work around this by invoking all listeners that take
Object
as parameters (i.e. the ones declared as lambdas) and handle theClassCastException
resulting from a potentially invalid invocation. As aCCE
can also result from the callback execution in general, we have to deeply inspect the exception, which requires Java version-specific handling and has caused trouble supporting newer Java versions as apparently the internals of a CCE change frequently.Solution
When we look up the
EntityCallback
instances from theBeanFactory
we can fall back to inspecting theBeanDefinition
for its generic type, and as that resolves to the return type used on the bean's factory method, we can use that instead of only seeingObject
.The text was updated successfully, but these errors were encountered: