Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request-scoped bean with @Lazy fails in native image (due to missing detection of CGLIB lazy resolution proxies) #29584

Closed
joshlong opened this issue Nov 26, 2022 · 4 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Milestone

Comments

@joshlong
Copy link
Member

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.

spring-projects/spring-boot#33366

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 26, 2022
@jhoeller
Copy link
Contributor

jhoeller commented Nov 26, 2022

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?

@jhoeller
Copy link
Contributor

jhoeller commented Nov 26, 2022

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

@jhoeller jhoeller changed the title Error when using request-scoped bean in a GraalVM / AOT CGLIB error when using plain request-scoped bean with @Lazy in a native image Nov 26, 2022
@jhoeller jhoeller self-assigned this Nov 26, 2022
@jhoeller
Copy link
Contributor

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.

@jhoeller jhoeller added type: bug A general bug in: core Issues in core modules (aop, beans, core, context, expression) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 26, 2022
@jhoeller jhoeller added this to the 6.0.3 milestone Nov 26, 2022
@jhoeller jhoeller changed the title CGLIB error when using plain request-scoped bean with @Lazy in a native image Plain request-scoped bean with @Lazy fails in a native image (missing detection of CGLIB lazy resolution proxies) Nov 26, 2022
@jhoeller jhoeller changed the title Plain request-scoped bean with @Lazy fails in a native image (missing detection of CGLIB lazy resolution proxies) Plain request-scoped bean with @Lazy fails in a native image (due to missing detection of CGLIB lazy resolution proxies) Nov 26, 2022
@jhoeller jhoeller added the theme: aot An issue related to Ahead-of-time processing label Nov 26, 2022
@jhoeller jhoeller changed the title Plain request-scoped bean with @Lazy fails in a native image (due to missing detection of CGLIB lazy resolution proxies) request-scoped bean with @Lazy fails in native image (due to missing detection of CGLIB lazy resolution proxies) Nov 26, 2022
@joshlong
Copy link
Member Author

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.

plamentotev added a commit to Mosquito-Bytes/CarbonCritters that referenced this issue Nov 19, 2023
Spring AOT (used to help Java native build) does not
recognize proxies created by proxy. Use ObjectProvider instead.
It is recommended anyway (even if no Java native build is used).

See spring-projects/spring-framework#29584
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants