Version: 2.2.[0|1].RELEASE
Context:
- Custom starter library has webflux and webmvc at "provided" scope
- Custom starter has auto-configuration that has a conditional nested configuration on each tech
- Consuming webmvc based application includes starter (has no webflux dep)
Behavior in 2.1.x.RELEASE was that the webflux gated config would be excluded and all was well.
Behavior w/ 2.2.x.RELEASE is startup fails w/ following:
java.lang.NoClassDefFoundError: org/springframework/web/reactive/config/WebFluxConfigurer
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_102]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_102]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_102]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_102]
at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_102]
at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_102]
at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_102]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_102]
at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_102]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_102]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_102]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_102]
at java.lang.Class.getDeclaringClass0(Native Method) ~[na:1.8.0_102]
at java.lang.Class.getDeclaringClass(Class.java:1235) ~[na:1.8.0_102]
at java.lang.Class.getEnclosingClass(Class.java:1277) ~[na:1.8.0_102]
at org.springframework.core.annotation.AnnotationsScanner.processClassHierarchy(AnnotationsScanner.java:233) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.AnnotationsScanner.processClassHierarchy(AnnotationsScanner.java:194) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.AnnotationsScanner.processClass(AnnotationsScanner.java:130) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.AnnotationsScanner.process(AnnotationsScanner.java:107) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.AnnotationsScanner.scan(AnnotationsScanner.java:97) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.AnnotationsScanner.scan(AnnotationsScanner.java:78) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.TypeMappedAnnotations.scan(TypeMappedAnnotations.java:242) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.core.annotation.TypeMappedAnnotations.isPresent(TypeMappedAnnotations.java:98) ~[spring-core-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBindConstructorProvider.isConstructorBindingAnnotatedType(ConfigurationPropertiesBindConstructorProvider.java:81) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBindConstructorProvider.getBindConstructor(ConfigurationPropertiesBindConstructorProvider.java:49) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBean$BindMethod.forType(ConfigurationPropertiesBean.java:311) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator.validate(ConfigurationPropertiesBeanDefinitionValidator.java:61) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator.postProcessBeanFactory(ConfigurationPropertiesBeanDefinitionValidator.java:44) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:286) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) [classes/:na]
Caused by: java.lang.ClassNotFoundException: org.springframework.web.reactive.config.WebFluxConfigurer
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_102]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_102]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_102]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_102]
... 39 common frames omitted
Starter snippet pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>provided</scope>
</dependency>
Starter auto-config
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(DemoProperties.class)
public class DemoAutoConfiguration {
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(WebMvcConfigurer.class)
@Configuration
static class DemoWebMvcConfiguration implements WebMvcConfigurer {
@PostConstruct
public void init() {
System.out.println("DemoWebMvcConfiguration.init()");
}
}
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@Configuration
static class DemoWebFluxConfiguration implements WebFluxConfigurer {
@PostConstruct
public void init() {
System.out.println("DemoWebFluxConfiguration.init()");
}
}
}
Consuming app pom.xml snippet
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>demolib</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
NOTE: If I comment out the DemoWebMvcConfiguration the conditional behaves and the webflux gated config is excluded and all is well. It seems that when they are both present the config properties annotation scan tries to load the classes.
Version:
2.2.[0|1].RELEASEContext:
Behavior in
2.1.x.RELEASEwas that the webflux gated config would be excluded and all was well.Behavior w/
2.2.x.RELEASEis startup fails w/ following:Starter snippet pom.xml
Starter auto-config
Consuming app pom.xml snippet
NOTE: If I comment out the
DemoWebMvcConfigurationthe conditional behaves and the webflux gated config is excluded and all is well. It seems that when they are both present the config properties annotation scan tries to load the classes.