Skip to content

ProxyFactoryBean on AuthenticationManager does not work in native mode #12367

@marcusdacoregio

Description

@marcusdacoregio

If we don’t find an AuthenticationManager bean during configuration, we create a ProxyFactoryBean to lazily initialize the bean when used.

private <T> T lazyBean(Class<T> interfaceName) {
LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource();
String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.applicationContext,
interfaceName);
if (beanNamesForType.length == 0) {
return null;
}
String beanName = getBeanName(interfaceName, beanNamesForType);
lazyTargetSource.setTargetBeanName(beanName);
lazyTargetSource.setBeanFactory(this.applicationContext);
ProxyFactoryBean proxyFactory = new ProxyFactoryBean();
proxyFactory = this.objectPostProcessor.postProcess(proxyFactory);
proxyFactory.setTargetSource(lazyTargetSource);
return (T) proxyFactory.getObject();
}

This does not work when running an application in native mode, since some proxy hints are necessary in order to find the bean.
Instead, we should delay the initialization of the bean and provide a delegate instead of a lazy bean, something like AuthenticationConfiguration#LazyPasswordEncoder.

Stacktrace:

2022-11-28T23:48:23.496+01:00 ERROR 29336 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through field 'httpSecurity': Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity': Instantiation of supplied bean failed
        at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:195) ~[na:na]
        at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveAndSet(AutowiredFieldValueResolver.java:167) ~[na:na]
        at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration__Autowiring.apply(WebSecurityConfiguration__Autowiring.java:20) ~[na:na]
        at org.springframework.beans.factory.support.InstanceSupplier$1.get(InstanceSupplier.java:82) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961) ~[demo.exe:6.0.2]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915) ~[demo.exe:6.0.2]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[demo.exe:6.0.2]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[demo.exe:3.0.0]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[demo.exe:3.0.0]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[demo.exe:3.0.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[demo.exe:3.0.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[demo.exe:3.0.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[demo.exe:3.0.0]
        at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[demo.exe:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity': Instantiation of supplied bean failed
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1236) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:344) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:189) ~[na:na]
        ... 22 common frames omitted
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: Proxy class defined by interfaces [interface org.springframework.security.authentication.AuthenticationManager, interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised, interface org.springframework.core.DecoratingProxy] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) ~[na:na]
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.reflect.proxy.DynamicProxySupport.getProxyClass(DynamicProxySupport.java:171) ~[na:na]
        at java.base@17.0.5/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:47) ~[demo.exe:na]
        at java.base@17.0.5/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037) ~[demo.exe:na]
        at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:123) ~[na:na]
        at org.springframework.aop.framework.ProxyFactoryBean.getProxy(ProxyFactoryBean.java:348) ~[na:na]
        at org.springframework.aop.framework.ProxyFactoryBean.getSingletonInstance(ProxyFactoryBean.java:306) ~[na:na]
        at org.springframework.aop.framework.ProxyFactoryBean.getObject(ProxyFactoryBean.java:253) ~[na:na]
        at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.lazyBean(AuthenticationConfiguration.java:166) ~[demo.exe:na]
        at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationManagerBean(AuthenticationConfiguration.java:196) ~[demo.exe:na]
        at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationManager(AuthenticationConfiguration.java:123) ~[demo.exe:na]
        at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.authenticationManager(HttpSecurityConfiguration.java:132) ~[demo.exe:na]
        at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity(HttpSecurityConfiguration.java:108) ~[demo.exe:na]
        at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration__BeanDefinitions.lambda$getHttpSecurityInstanceSupplier$0(HttpSecurityConfiguration__BeanDefinitions.java:31) ~[na:na]
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:63) ~[demo.exe:6.0.2]
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:51) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$withGenerator$0(BeanInstanceSupplier.java:173) ~[na:na]
        at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:68) ~[demo.exe:6.0.2]
        at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:54) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$2(BeanInstanceSupplier.java:208) ~[na:na]
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:59) ~[demo.exe:6.0.2]
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:47) ~[demo.exe:6.0.2]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:220) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:208) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[demo.exe:6.0.2]
        ... 32 common frames omitted

This was initially reported by @nkonev in #12366.

Metadata

Metadata

Labels

in: coreAn issue in spring-security-coretype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions