Hi - I noticed what I think is a regression on the GraalVM/AOT handling of scoped beans

This issue (errantly put in the spring boot tracker and closed) has the details of a reproducible example.

https://github.com/spring-projects/spring-boot/issues/33366

Comment From: jhoeller

Hey Josh, this is a variant of #29309 where we obviously fail to register the reflection hints for CGLIB proxy classes. As pointed out there by Ollie and Christoph, you can register those hints manually for the time being.

We detect CGLIB proxy classes by top-level bean inspection in GenericApplicationContext.preDetermineBeanTypes. Any internal exposure of CGLIB proxies is captured in terms of the generated classes (since that is a CGLIB-internal hook) but not visible for proxy hint registration (which happens at bean introspection level). The capture of generated classes is wider than proxy classes (also includes fast-class helpers etc), and only actual proxy classes need reflection hints on top. Our current hint registration aims to be minimal there, avoiding unnecessary hints, and being consistent with the discovery of JDK proxy classes.

So for such scenarios, it would be good to understand why GenericApplicationContext.preDetermineBeanTypes is not able to see the affected CGLIB proxy classes and therefore not registering the corresponding runtime hints. Note that it would also not reliably see JDK proxy classes that got created outside of top-level beans, so this is not inherently a CGLIB problem.

In your case, it seems that RequestContext itself is not a scoped proxy but rather a plain scoped bean that is then covered by a lazy resolution proxy for the ContextHttpController constructor. Lazy resolution proxies can be hard to discover for the framework there, despite our attempts to pre-resolve them for AOT. So if you turned your RequestContext bean into an actual scoped proxy (e.g. through using @RequestScope which defaults to a target-class scoped proxy) and therefore removed the @Lazy part on ContextHttpController, I suppose it would work out of the box, based on my current understanding?

Comment From: jhoeller

Alternatively, declaring the ContextHttpController constructor with an ObjectProvider<RequestContext> parameter instead should also work. I generally recommend avoiding proxies for lazy-resolution purposes since this can always be replaced with a lightweight ObjectProvider arrangement. Or in this case, with a full-scale scoped proxy bean which is more efficient as well (since it is not on-demand per constructor but rather shared application-wide).

Comment From: jhoeller

An update after some analysis: It seems that we do indeed have a gap in our attempts to pre-resolve lazy resolution proxies for AOT where we currently detect and register JDK proxies but not CGLIB proxies in some scenarios. I'll make this consistent for 6.0.3, closing that specific gap and therefore widening the scenarios that we can discover upfront.

This should also make the above scenario work as far as I can see. However, all the recommendations above stand nevertheless since it is generally a good idea to reduce unnecessary proxy requirements or make them exposed at the bean level at least.

Comment From: joshlong

I've made the changes you suggested, and this works. Thanks!

The only oddity is that it did work with the regular (non target-proxy) on the JRE. Each new request sees a new value for the uuid.