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

Add support for SchedulerFactoryBean in native-image #28725

Closed
mhalbritter opened this issue Jun 29, 2022 · 2 comments
Closed

Add support for SchedulerFactoryBean in native-image #28725

mhalbritter opened this issue Jun 29, 2022 · 2 comments
Assignees
Labels
theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Milestone

Comments

@mhalbritter
Copy link
Contributor

When trying to use the SchedulerFactoryBean in a native image (for example with Spring Boot and including the spring-boot-starter-quartz starter), it fails at runtime with:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'quartzEndpoint': Unsatisfied dependency expressed through method 'quartzEndpoint' parameter 0: Error creating bean with name 'quartzScheduler': Failed to instantiate [org.quartz.impl.StdSchedulerFactory]: No default constructor found
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveArgument(AutowiredInstantiationArgumentsResolver.java:319) ~[na:na]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveArguments(AutowiredInstantiationArgumentsResolver.java:232) ~[na:na]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolve(AutowiredInstantiationArgumentsResolver.java:154) ~[na:na]
        at org.springframework.boot.actuate.autoconfigure.quartz.QuartzEndpointAutoConfiguration__BeanDefinitions.getQuartzEndpointInstance(QuartzEndpointAutoConfiguration__BeanDefinitions.java:43) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1223) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1209) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1156) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:566) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1141) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.lambda$createEndpointBean$1(EndpointDiscoverer.java:145) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer$EndpointBean.getBean(EndpointDiscoverer.java:447) ~[na:na]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.getFilterEndpoint(EndpointDiscoverer.java:307) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.isFilterMatch(EndpointDiscoverer.java:285) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.isExtensionExposed(EndpointDiscoverer.java:239) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.addExtensionBean(EndpointDiscoverer.java:170) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.addExtensionBeans(EndpointDiscoverer.java:159) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.discoverEndpoints(EndpointDiscoverer.java:124) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer.getEndpoints(EndpointDiscoverer.java:117) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration.getHealthEndpoint(HealthEndpointWebExtensionConfiguration.java:62) ~[actuator-aot:0.0.1-SNAPSHOT]
        at org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration$MvcAdditionalHealthEndpointPathsConfiguration.healthEndpointWebMvcHandlerMapping(HealthEndpointWebExtensionConfiguration.java:74) ~[actuator-aot:0.0.1-SNAPSHOT]
        at org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration_MvcAdditionalHealthEndpointPathsConfiguration__BeanDefinitions.lambda$getHealthEndpointWebMvcHandlerMappingInstance$0(HealthEndpointWebExtensionConfiguration_MvcAdditionalHealthEndpointPathsConfiguration__BeanDefinitions.java:44) ~[na:na]
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:63) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:51) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolve(AutowiredInstantiationArgumentsResolver.java:156) ~[na:na]
        at org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration_MvcAdditionalHealthEndpointPathsConfiguration__BeanDefinitions.getHealthEndpointWebMvcHandlerMappingInstance(HealthEndpointWebExtensionConfiguration_MvcAdditionalHealthEndpointPathsConfiguration__BeanDefinitions.java:44) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1223) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1209) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1156) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:566) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:930) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:926) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:592) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:729) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:428) ~[actuator-aot:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[actuator-aot:3.0.0-SNAPSHOT]
        at com.example.actuator_aot.ActuatorAotApplication.main(ActuatorAotApplication.java:29) ~[actuator-aot:0.0.1-SNAPSHOT]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzScheduler': Failed to instantiate [org.quartz.impl.StdSchedulerFactory]: No default constructor found
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1752) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:604) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1374) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1294) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveArgument(AutowiredInstantiationArgumentsResolver.java:302) ~[na:na]
        ... 46 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.quartz.impl.StdSchedulerFactory]: No default constructor found
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:146) ~[na:na]
        at org.springframework.scheduling.quartz.SchedulerFactoryBean.prepareSchedulerFactory(SchedulerFactoryBean.java:529) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:504) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1798) ~[actuator-aot:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1748) ~[actuator-aot:6.0.0-SNAPSHOT]
        ... 56 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.quartz.impl.StdSchedulerFactory.<init>()
        at java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[actuator-aot:na]
        at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754) ~[actuator-aot:na]
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141) ~[na:na]
        ... 60 common frames omitted

The factory bean tries to instantiate the SchedulerFactory via BeanUtils.instantiateClass which fails, because there are no reflection hints for the constructor of that class.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 29, 2022
@sdeleuze sdeleuze added type: enhancement A general enhancement theme: aot An issue related to Ahead-of-time processing and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 29, 2022
@sdeleuze sdeleuze added this to the 6.0.0-M6 milestone Jun 29, 2022
@sdeleuze sdeleuze self-assigned this Jun 29, 2022
@sdeleuze
Copy link
Contributor

I have began to add such support locally but Quartz is heavily reflection based so it will require more work on library side.

@sdeleuze
Copy link
Contributor

sdeleuze commented Aug 9, 2022

Related metadata issue: oracle/graalvm-reachability-metadata#19.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants