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

Missing native-image reflection hint for org.springframework.data.mongodb.core.aggregation.AggregationOperation #4637

Closed
anguzo opened this issue Feb 13, 2024 · 14 comments
Labels
for: external-project For an external project and not something we can fix status: feedback-provided Feedback has been provided

Comments

@anguzo
Copy link

anguzo commented Feb 13, 2024

Environment

  • Spring Boot Starter Parent 3.2.2
  • Spring Security 6.2.2-SNAPSHOT (6.2.1 has error related to issue)
  • Spring Data Bom 2023.1.3-SNAPSHOT (2023.1.2 has error related to issue)
  • BellSoft Liberica NIK 21.0.2

Problem

I was exploring Spring Native capabilities on a project created using this settings in Spring Initializr.
Got an error:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'healthContributorRegistry': Unsatisfied dependency expressed through method 'healthContributorRegistry' parameter 2: Error creating bean wit
h name 'mongoHealthContributor': Unsatisfied dependency expressed through method 'mongoHealthContributor' parameter 0: Error creating bean with name 'mongoTemplate': Type org.springframework.data.mongodb.core.aggregation.AggregationOpera
tion not present
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveAutowiredArgument(BeanInstanceSupplier.java:344) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:264) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:204) ~[na:na]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:949) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1216) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[demo.exe:6.1.3]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:959) ~[demo.exe:6.1.3]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[demo.exe:6.1.3]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[demo.exe:3.2.2]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[demo.exe:3.2.2]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[demo.exe:3.2.2]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[demo.exe:3.2.2]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[demo.exe:3.2.2]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[demo.exe:3.2.2]
        at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[demo.exe:na]
        at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH) ~[na:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mongoHealthContributor': Unsatisfied dependency expressed through method 'mongoHealthContributor' parameter 0: Error creating bea
n with name 'mongoTemplate': Type org.springframework.data.mongodb.core.aggregation.AggregationOperation not present
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveAutowiredArgument(BeanInstanceSupplier.java:344) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:264) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:204) ~[na:na]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:949) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1216) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1689) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1653) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeanMap(DefaultListableBeanFactory.java:1575) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1514) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1392) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:907) ~[na:na]
        at org.springframework.beans.factory.support.RegisteredBean.resolveAutowiredArgument(RegisteredBean.java:229) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveAutowiredArgument(BeanInstanceSupplier.java:341) ~[na:na]
        ... 22 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate': Type org.springframework.data.mongodb.core.aggregation.AggregationOperation not present
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:606) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1689) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1653) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeanMap(DefaultListableBeanFactory.java:1575) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1514) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1392) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:907) ~[na:na]
        at org.springframework.beans.factory.support.RegisteredBean.resolveAutowiredArgument(RegisteredBean.java:229) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveAutowiredArgument(BeanInstanceSupplier.java:341) ~[na:na]
        ... 43 common frames omitted
Caused by: java.lang.TypeNotPresentException: Type org.springframework.data.mongodb.core.aggregation.AggregationOperation not present
        at [email protected]/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:117) ~[na:na]
        at [email protected]/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125) ~[na:na]
        at [email protected]/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) ~[na:na]
        at [email protected]/sun.reflect.generics.visitor.Reifier.visitArrayTypeSignature(Reifier.java:159) ~[na:na]
        at [email protected]/sun.reflect.generics.tree.ArrayTypeSignature.accept(ArrayTypeSignature.java:42) ~[na:na]
        at [email protected]/sun.reflect.generics.repository.ConstructorRepository.computeParameterTypes(ConstructorRepository.java:111) ~[demo.exe:na]
        at [email protected]/sun.reflect.generics.repository.ConstructorRepository.getParameterTypes(ConstructorRepository.java:87) ~[demo.exe:na]
        at [email protected]/java.lang.reflect.Executable.getGenericParameterTypes(Executable.java:313) ~[demo.exe:na]
        at [email protected]/java.lang.reflect.Method.getGenericParameterTypes(Method.java:337) ~[demo.exe:na]
        at org.springframework.core.BridgeMethodResolver.isResolvedTypeMatch(BridgeMethodResolver.java:178) ~[na:na]
        at org.springframework.core.BridgeMethodResolver.isBridgeMethodFor(BridgeMethodResolver.java:168) ~[na:na]
        at org.springframework.core.BridgeMethodResolver.searchCandidates(BridgeMethodResolver.java:147) ~[na:na]
        at org.springframework.core.BridgeMethodResolver.resolveBridgeMethod(BridgeMethodResolver.java:109) ~[na:na]
        at org.springframework.core.BridgeMethodResolver.getMostSpecificMethod(BridgeMethodResolver.java:90) ~[na:na]
        at org.springframework.aop.support.AopUtils.getMostSpecificMethod(AopUtils.java:206) ~[na:na]
        at org.springframework.aop.aspectj.AspectJExpressionPointcut.getTargetShadowMatch(AspectJExpressionPointcut.java:427) ~[na:na]
        at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:291) ~[na:na]
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:258) ~[na:na]
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:295) ~[na:na]
        at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:327) ~[na:na]
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:128) ~[demo.exe:6.1.3]
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:97) ~[demo.exe:6.1.3]
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:78) ~[demo.exe:6.1.3]
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:366) ~[demo.exe:6.1.3]
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:318) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:437) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1776) ~[demo.exe:6.1.3]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[demo.exe:6.1.3]
        ... 58 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.data.mongodb.core.aggregation.AggregationOperation
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:122) ~[na:na]
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:86) ~[na:na]
        at [email protected]/java.lang.Class.forName(DynamicHub.java:1356) ~[demo.exe:na]
        at [email protected]/java.lang.Class.forName(DynamicHub.java:1345) ~[demo.exe:na]
        at [email protected]/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114) ~[na:na]
        ... 85 common frames omitted
        ```
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 13, 2024
@christophstrobl
Copy link
Member

If you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

@christophstrobl christophstrobl added the status: waiting-for-feedback We need additional information before we can continue label Feb 14, 2024
@anguzo
Copy link
Author

anguzo commented Feb 14, 2024

Sure, here is a minimal example. If I remove mongodb from dependencies then project does not throw the mentioned exception when running native executable.

demo.zip

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 14, 2024
@christophstrobl
Copy link
Member

Thank you @anguzo for the reproducer - GraalVM decides to not include AggregationOperation in the image. However the core framework tries to inspect all methods when creating a proxy for the mongo template. This involves reading method signatures via BridgeMethodResolver and fails because of the removed AggregationOperation.
@sdeleuze is there a way BridgeMethodResolver could be more lenient when resolving parameter types?

@christophstrobl christophstrobl added for: external-project For an external project and not something we can fix and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Feb 20, 2024
@sdeleuze
Copy link
Contributor

Spring Framework is unlikely to change this code path which could introduce regressions on JVM side. I would suggest to add related hints on Spring Data side (and maybe check if other *Operation types are impacted, included outside spring-data-mongodb).

@christophstrobl
Copy link
Member

Given the number of projects potentially having both reactive and imperative variants manually adding those hints sounds quite cumbersome and error prone. Before we do that, do we know candidates for proxy creation during the AOT phase? If so, we could hook into the processing to add missing types based on method signatures.

@sdeleuze
Copy link
Contributor

@snicoll Could you please share with Christoph if that's possible (I am not sure it is)?

@mp911de mp911de added the status: waiting-for-feedback We need additional information before we can continue label Feb 28, 2024
@spring-projects-issues
Copy link

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Mar 6, 2024
@snicoll
Copy link
Member

snicoll commented Mar 6, 2024

Sorry, I overlooked this. I'll check with Christoph.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue labels Mar 6, 2024
@mmuthukrishnan
Copy link

I'm facing the same issue with my project. Any temp solutions are fine too. @snicoll
BTW is this issue not occur with previous spring boot versions ? @christophstrobl

@christophstrobl
Copy link
Member

@mmuthukrishnan you can always provide additional hints yourself if needed, which may help you proceed for now.

Meanwhile I had another look at the sample project and once the org.springframework.cloud dependencies are removed things work as expected. @mmuthukrishnan are you also using spring-cloud? If so that would narrow down the component creating the proxy.

@OlgaMaciaszek
Copy link

The difference when spring-cloud-starter-openfeign is added is that it brings along spring-boot-starter-aop which adds AspectJ to the classpath. As a result, a different, AspectJ-specific, AbstractAdvisorAutoProxyCreator implementation is used and the class for which the hint is missing is being processed by one of its advisors causing the issue.

@mmarimuthu
Copy link

@mmuthukrishnan you can always provide additional hints yourself if needed, which may help you proceed for now.

Meanwhile I had another look at the sample project and once the org.springframework.cloud dependencies are removed things work as expected. @mmuthukrishnan are you also using spring-cloud? If so that would narrow down the component creating the proxy.

@christophstrobl
Yes I use it with spring cloud function with aws adapter.

@OlgaMaciaszek
Copy link

The dependency has now also been removed from spring-cloud-starter-openfeign, so after switching to Spring Cloud 2023.0.2 once it's been released, the problem won't occur with the setup from the demo.

@christophstrobl
Copy link
Member

Thank you @OlgaMaciaszek! Closing this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix status: feedback-provided Feedback has been provided
Projects
None yet
Development

No branches or pull requests

9 participants