Skip to content

CGLIB proxy classes are no longer cached properly #31238

Closed
@danthe1st

Description

@danthe1st

Affects:

  • Spring 6.0.10 / Spring Boot 3.0.10
    • it also works when overwriting the Spring version to 6.0.11 using the property <spring-framework.version>6.0.12</spring-framework.version>
  • Spring 6.0.11 / Spring Boot 3.1.3
    • See branch 3.1 in the reproducer, build log here

When a Spring project using @Transactional and @DirtiesContext is running tests in native mode, it fails with an error like this:

CGLIB runtime enhancement not supported on native image. Make sure to include a pre-generated class on the classpath instead: io.github.danthe1st.spring_demo.SomethingWithTransactional$$SpringCGLIB$$6

Steps to reproduce:

  • Create a project with Spring Initializr
    • Spring Data JPA
    • GraalVM Native-Image support
  • Add H2 as a test database
  • Create a @Component with a @Transactional method.
  • Create a @SpringBootTest with a test method annotated with @DirtiesContext
  • Run the tests in native mode using mvn test -PnativeTest

This results in an error like the following when running the tests:

=> java.lang.IllegalStateException: Failed to load ApplicationContext for [AotMergedContextConfiguration@579f911b testClass = io.github.danthe1st.spring_demo.TestWithDirtiesContext, contextInitializerClass = io.github.danthe1st.spring_demo.TestWithDirti
   org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:143)
   org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:127)
   org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependenciesInAotMode(DependencyInjectionTestExecutionListener.java:148)
   org.springframework.test.context.support.DependencyInjectionTestExecutionListener.beforeTestMethod(DependencyInjectionTestExecutionListener.java:118)
   org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:288)
   [...]
   Suppressed: java.lang.IllegalStateException: Failed to load ApplicationContext for [AotMergedContextConfiguration@2ebc43f8 testClass = io.github.danthe1st.spring_demo.TestWithDirtiesContext, contextInitializerClass = io.github.danthe1st.spring_demo.T
     org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:143)
     org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:127)
     org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener.afterTestMethod(WebDriverTestExecutionListener.java:42)
     org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:440)
     org.springframework.test.context.junit.jupiter.SpringExtension.afterEach(SpringExtension.java:206)
     [...]
     Suppressed: java.lang.IllegalStateException: Failed to load ApplicationContext for [AotMergedContextConfiguration@6be801a testClass = io.github.danthe1st.spring_demo.TestWithDirtiesContext, contextInitializerClass = io.github.danthe1st.spring_demo.
       org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:143)
       org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:127)
       org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener.afterTestMethod(MockMvcPrintOnlyOnFailureTestExecutionListener.java:39)
       [...]
     Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'somethingWithTransactional': Unexpected AOP exception
       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:605)
       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
       org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
       org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
       org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
       [...]
     Caused by: org.springframework.aop.framework.AopConfigException: Unexpected AOP exception
       org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:228)
       org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:155)
       org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
       org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildProxy(AbstractAutoProxyCreator.java:517)
       org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:464)
       [...]
     Caused by: java.lang.UnsupportedOperationException: CGLIB runtime enhancement not supported on native image. Make sure to include a pre-generated class on the classpath instead: io.github.danthe1st.spring_demo.SomethingWithTransactional$$SpringCGLI
       org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
       org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
       org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
       org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
       java.base@20.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
       [...]
     Suppressed: java.lang.IllegalStateException: Failed to load ApplicationContext for [AotMergedContextConfiguration@42dfa7e6 testClass = io.github.danthe1st.spring_demo.TestWithDirtiesContext, contextInitializerClass = io.github.danthe1st.spring_demo
       org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:143)
       org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:127)
       org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener.afterTestMethod(MockRestServiceServerResetTestExecutionListener.java:40)
       [...]
     Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'somethingWithTransactional': Unexpected AOP exception
       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:605)
       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
       org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
       org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
       org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
       [...]
     Caused by: org.springframework.aop.framework.AopConfigException: Unexpected AOP exception
       org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:228)
       org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:155)
       org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
       org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildProxy(AbstractAutoProxyCreator.java:517)
       org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:464)
       [...]
     Caused by: java.lang.UnsupportedOperationException: CGLIB runtime enhancement not supported on native image. Make sure to include a pre-generated class on the classpath instead: io.github.danthe1st.spring_demo.SomethingWithTransactional$$SpringCGLI
       org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
       org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
       org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
       org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
       java.base@20.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
       [...]
   Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'somethingWithTransactional': Unexpected AOP exception
     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:605)
     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
     org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
     org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
     org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
     [...]
   Caused by: org.springframework.aop.framework.AopConfigException: Unexpected AOP exception
     org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:228)
     org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:155)
     org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
     org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildProxy(AbstractAutoProxyCreator.java:517)
     org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:464)
     [...]
   Caused by: java.lang.UnsupportedOperationException: CGLIB runtime enhancement not supported on native image. Make sure to include a pre-generated class on the classpath instead: io.github.danthe1st.spring_demo.SomethingWithTransactional$$SpringCGLIB$
     org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
     org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
     org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
     org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
     java.base@20.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
     [...]
 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'somethingWithTransactional': Unexpected AOP exception
   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:605)
   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
   org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
   org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
   org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
   [...]
 Caused by: org.springframework.aop.framework.AopConfigException: Unexpected AOP exception
   org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:228)
   org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:155)
   org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
   org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildProxy(AbstractAutoProxyCreator.java:517)
   org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:464)
   [...]
 Caused by: java.lang.UnsupportedOperationException: CGLIB runtime enhancement not supported on native image. Make sure to include a pre-generated class on the classpath instead: io.github.danthe1st.spring_demo.SomethingWithTransactional$$SpringCGLIB$$6
   org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
   org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
   org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
   org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
   java.base@20.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
   [...]

Reproducer: https://github.com/danthe1st/spring-dirty-cglib
failed run: https://github.com/danthe1st/spring-dirty-cglib/actions/runs/6190254596/job/16806115554
build log as file: 1_build.txt

native-image version:

native-image 17.0.7 2023-04-18
GraalVM Runtime Environment Oracle GraalVM 17.0.7+8.1 (build 17.0.7+8-LTS-jvmci-23.0-b12)
Substrate VM Oracle GraalVM 17.0.7+8.1 (build 17.0.7+8-LTS, serial gc, compressed references)

This issue might be related to #30939 but it occurs in a different Spring version and seems to be caused by different things.

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)theme: aotAn issue related to Ahead-of-time processingtype: regressionA bug that is also a regression

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions