NoClassDefFoundError: NestedIOException when running tests with Spring Boot 3.0.0-M4 / Spring 6.0.0-M5

14.5k Views Asked by At

I have a Java-17 project using Spring Boot which I'm trying to modularize. To take full advantage of the modularization, I'm porting it to Spring Boot 3 milestone 4 and Spring 6 milestone 5.

The project is managed my Maven. I was able to get the project to compile. However, it fails to execute the standard contextLoads() test as generated by Spring Boot. The specific error message is:

[main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Could not load default TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes available.
java.lang.NoClassDefFoundError: jakarta/servlet/ServletContext

This error message is repeated twice more with different TestExecutionListener implementations, namely TransactionalTestExecutionListener and SqlScriptsTestExecutionListener, but Spring ultimately loads a number of TestExecutionListeners and tries to execute the test. However, the test fails:

java.lang.NoClassDefFoundError: org/springframework/beans/factory/aot/BeanFactoryInitializationAotProcessor
    [...series of java.base frames...]
    at [email protected]/org.springframework.context.annotation.AnnotationConfigUtils.registerAnnotationConfigProcessors(AnnotationConfigUtils.java:165)
    at [email protected]/org.springframework.context.annotation.AnnotationConfigUtils.registerAnnotationConfigProcessors(AnnotationConfigUtils.java:138)
    at [email protected]/org.springframework.context.annotation.AnnotatedBeanDefinitionReader.<init>(AnnotatedBeanDefinitionReader.java:88)
    at [email protected]/org.springframework.context.annotation.AnnotatedBeanDefinitionReader.<init>(AnnotatedBeanDefinitionReader.java:71)
    at [email protected]/org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:69)
    at [email protected]/org.springframework.boot.ApplicationContextFactory.lambda$static$0(ApplicationContextFactory.java:55)
    at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$1(SpringBootContextLoader.java:120)
    at [email protected]/org.springframework.boot.SpringApplication.createApplicationContext(SpringApplication.java:566)
    at [email protected]/org.springframework.boot.SpringApplication.run(SpringApplication.java:309)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:123)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)
    at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$8(ClassBasedTestDescriptor.java:363)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$9(ClassBasedTestDescriptor.java:363)
    [...many more frames, mostly from junit and surefire...]
Caused by: java.lang.ClassNotFoundException: org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)

This problem is probably caused by some error in my module-info.java. The Spring modules I'm using are:

    requires spring.beans;
    requires spring.context;
    requires spring.boot.autoconfigure;
    requires spring.core;
    requires spring.boot;
    requires spring.oxm;
    requires spring.web;
    requires spring.ws.core;
    [...]
    opens [my module] to spring.core;
    exports [my module] to spring.beans, spring.context;

What am I missing? The application compiles and works fine with Spring 5.3 / Spring Boot 2.7, but I need to modularize it to be able to create an installer.

1

There are 1 best solutions below

1
ahuemmer On

The problem seems to be related with org.springframework:spring-beans:5.3.25, which does not include the required class yet. By accident, we had this version pinned in our build.gradle when migrating to Spring 3.0. This should not be necessary any more.

Thus, you could try removing spring-beans from your build.gradle or pom.xml, depending on whether you use Gradle oder Maven. This should already be sufficient. If not, you could try gradle dependencies or mvn dependency:tree (having the related plugin installed) to find out, if/where the old version is pulled in. Alternatively, you could explicitly include the newest version in your build.gradle or pom.xml.