Skip to content

Class Proxy not working with native-image #28729

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

Closed
marcusdacoregio opened this issue Jun 29, 2022 · 4 comments
Closed

Class Proxy not working with native-image #28729

marcusdacoregio opened this issue Jun 29, 2022 · 4 comments
Labels
status: duplicate A duplicate of another issue theme: aot An issue related to Ahead-of-time processing type: bug A general bug

Comments

@marcusdacoregio
Copy link
Contributor

marcusdacoregio commented Jun 29, 2022

I am adding support for the @PreAuthorize, @PreFilter, @PostAuthorize, and @PostFilter annotations from Spring Security.

The hints are being added using a PrePostSecuredBeanRegistrationAotProcessor and PrePostSecuredBeanRegistrationAotContribution, which can be seen here, that's pretty much what we had before in the native repository.

However, the application fails when running on native with the following stacktrace:

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'greetingServiceImpl' is expected to be of type 'com.example.methodsecurity.GreetingService' but was actually of type 'jdk.proxy4.$Proxy235'
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1800) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1777) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1340) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1294) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveArgument(AutowiredInstantiationArgumentsResolver.java:302) ~[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 com.example.methodsecurity.MainController__BeanDefinitions.getMainControllerInstance(MainController__BeanDefinitions.java:30) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1223) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1209) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1156) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:566) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:930) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:926) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:592) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:729) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:428) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[security-method:3.0.0-SNAPSHOT]
        at com.example.methodsecurity.MethodSecurityApplication.main(MethodSecurityApplication.java:19) ~[security-method:0.0.1-SNAPSHOT]

It runs fine in AOT only.

To Reproduce:

Run the build.sh script from this sample.

@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: bug A general bug 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 30, 2022
@sdeleuze sdeleuze added this to the 6.0.0-M5 milestone Jun 30, 2022
@sbrannen
Copy link
Member

sbrannen commented Jul 1, 2022

@sbrannen sbrannen added the status: waiting-for-feedback We need additional information before we can continue label Jul 1, 2022
@marcusdacoregio
Copy link
Contributor Author

Hi @sbrannen, if I remove that line the error changes to this:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'controller2': Proxy class defined by interfaces [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.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:611) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:930) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:926) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:592) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:729) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:428) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[security-method:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[security-method:3.0.0-SNAPSHOT]
        at com.example.methodsecurity.MethodSecurityApplication.main(MethodSecurityApplication.java:19) ~[security-method:0.0.1-SNAPSHOT]
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: Proxy class defined by interfaces [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 com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) ~[na:na]
        at com.oracle.svm.reflect.proxy.DynamicProxySupport.getProxyClass(DynamicProxySupport.java:158) ~[na:na]
        at java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:48) ~[security-method:na]
        at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037) ~[security-method:na]
        at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:126) ~[na:na]
        at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110) ~[na:na]
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:480) ~[security-method:0.0.1-SNAPSHOT]
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:344) ~[security-method:0.0.1-SNAPSHOT]
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293) ~[security-method:0.0.1-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:440) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1756) ~[security-method:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:604) ~[security-method:6.0.0-SNAPSHOT]
        ... 15 common frames omitted

@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 Jul 1, 2022
@sbrannen
Copy link
Member

sbrannen commented Jul 1, 2022

Thanks for trying it out and reporting back.

Both of the errors point to the same underlying issue.

The first error tells us that you got back a dynamic proxy instead of class-based proxy.

The second error tells us that a dynamic proxy could not be created for the interfaces SpringProxy, Advised, and DecoratingProxy, but Spring should never attempt to create a JDK dynamic proxy based solely on those three interfaces. Rather, the dynamic proxy must implement the user's interface(s) as well.

Controller2 does not implement any interfaces. So in order to proxy it for @PreAuthorize support, Spring has to create a class-based proxy.

I have not debugged your application, but both of these errors point to org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(AdvisedSupport).

Specifically, if NativeDetector.inNativeImage() returns true, DefaultAopProxyFactory will create a JdkDynamicAopProxy instead of a ObjenesisCglibAopProxy.

In summary, I think this is effectively a duplicate of #28115, but I will leave it open for @jhoeller to assess once he addresses #28115.

@snicoll snicoll changed the title JDK Proxy not working with native-image Class Proxy not working with native-image Jul 1, 2022
@jhoeller jhoeller modified the milestones: 6.0.0-M5, 6.0.0-M6 Jul 8, 2022
@snicoll
Copy link
Member

snicoll commented Aug 1, 2022

@marcusdacoregio please subscribe to #28115 and try again when it's fixed. If it turns out to be another issue, we can always reopen this one.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Aug 1, 2022
@snicoll snicoll added status: duplicate A duplicate of another issue and removed status: feedback-provided Feedback has been provided labels Aug 1, 2022
@snicoll snicoll removed this from the 6.0.0-M6 milestone Aug 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants