NoSuchFieldError: pathPatternParser in WebMvcEndpointManagementContextConfiguration after upgrade from spring-boot 2.5.5 to 2.6.1 - spring-boot

When upgrading to Spring-Boot from 2.5.5 to 2.6.1, I encounter the following error:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping]: Factory method 'webEndpointServletHandlerMapping' threw exception; nested exception is java.lang.NoSuchFieldError: pathPatternParser
I use Spring Boot Actuator, which uses class WebMvcEndpointManagementContextConfiguration in the autoconfigure dependency (spring-boot-actuator-autoconfigure). On line 68 (decompiled class), the WebMvcAutoConfiguration.pathPatternParser field is used, which to my understanding causes the exception.
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, WebMvcAutoConfiguration.pathPatternParser);
If I check the WebMvcAutoConfiguration class, I can only see the following usage of the PathPatternParser class, but no field declaration.
public void configurePathMatch(PathMatchConfigurer configurer) {
if (this.mvcProperties.getPathmatch().getMatchingStrategy() == MatchingStrategy.PATH_PATTERN_PARSER) {
configurer.setPatternParser(new PathPatternParser());
}
Is this a bug?
I will try to use Spring-Boot 2.6.0, 2.5.7 and 2.5.6 and see what the behavior on those versions is. I will update this issue with the information

Related

Spring tries to initialize AutoConfiguration beans using default constructor

We are having issues starting up our Spring Boot Web application. The main problem to properly diagnose the startup is that it only seems to happen in 1% of the startups. In 99% of the startup procedures all works fine and we end up having a properly working spring boot application. However in those 1% of those cases we see issues like this:
WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'errorPageFilterRegistration' defined in org.springframework.boot.web.servlet.support.Error
PageFilterConfiguration: Unsatisfied dependency expressed through method 'errorPageFilterRegistration' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorPageFilter' defined in org.springframework.boot.web.servlet.support.ErrorPageFilterConfiguration: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.spring
framework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigu
re.web.servlet.error.ErrorMvcAutoConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration.<init>() []
For some reason it tries to initialize AutoConfiguration beans by using a default constructor which obviously is not present. There is a constructor present which should be autowired.
Also the AutoConfiguration that is in the stacktrace can be different. Sometimes it is another one like e.g. org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
Any help or ideas on why this could be happening is appreciated. As this happens very occasionally this is hard to debug as we cannot relyably reproduce. Note that the stacktrace does not contain any custom code. Our application is quite big and we rely mostly on #Configuration classes to do configure the Beans.
Why would spring attempt to initialize an AutoConfiguration bean with a default constructor ?
The errorPageFilterConfiguration source of spring looks like this:
#Configuration(proxyBeanMethods = false)
class ErrorPageFilterConfiguration {
#Bean
ErrorPageFilter errorPageFilter() {
return new ErrorPageFilter();
}
#Bean
FilterRegistrationBean<ErrorPageFilter> errorPageFilterRegistration(ErrorPageFilter filter) {
FilterRegistrationBean<ErrorPageFilter> registration = new FilterRegistrationBean<>(filter);
registration.setOrder(filter.getOrder());
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
return registration;
}
}
According to the stack on creation of the errorPageFilter it is initializing the ErrorMvcAutoConfiguration as a prerequisite ? Why ?
We are not initializing these beans manually. The only relevant code for error page handling that we have is this following:
#Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> webServerFactoryCustomizer() {
return webServerFactory -> {
ErrorPage errorPage = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error");
webServerFactory.addErrorPages(errorPage);
};
}
This is a bug in Spring framework, introduced in version 5.3 in AbstractBeanFactory.
BeanPostProcessorCacheAwareList and accesses to the beanPostProcessors instance are not Thread safe. If multiple Threads are running during initialization and a Thread calls getBeanPostProcessorCache() while another Thread is calling addBeanPostProcessors, you can create a cache which does not contain all BeanPostProcessor instances and thus doesn't find the appropriate constructor.
I will submit a bug for this to spring-framework.
https://github.com/spring-projects/spring-framework/blob/16ea4692bab551800b9ba994ac08099e8acfd6cd/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java#L964
Issue created : https://github.com/spring-projects/spring-framework/issues/29299

Spring Security OAuth2 v5 : NoSuchBeanDefinitionException: 'org.springframework.security.oauth2.jwt.JwtDecoder'

I have a SpringBoot application that I am trying to update from the older Spring Security OAuth 2.x library to the newer Spring Security 5.5.x. Initially my configuration class was using the #EnableResourceServer annotation, but this was replaced with the Spring Security oauth2ResourceServer DSL method, as per the migration guide.
I have added in a custom JWT authentication converter, but am now getting the following warning on startup:
09:30:51.591 [, , ] [main] WARN %->5level org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' available
I can't see where this JwtDecoder is used in the filter chain yet, but it's stopping my application from starting up.
#Configuration
#Order(OAuthTokenApiSecurityConfig.ORDER)
public class OAuthTokenApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception { // NOPMD
// #formatter:off
http
.requestMatcher(new OAuth2RequestMatcher())
...
...
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(customTokenAuthenticationConverter());
// #formatter:on
}
#Bean
public CustomTokenAuthenticationConverter customTokenAuthenticationConverter() {
return new CustomTokenAuthenticationConverter();
}
#Bean
public JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter() {
return new JwtGrantedAuthoritiesConverter();
}
}
dependecies {
api("org.springframework.security:spring-security-oauth2-resource-server")
api("org.springframework.security:spring-security-oauth2-core")
api("org.springframework.security:spring-security-oauth2-jose")
api("com.nimbusds:nimbus-jose-jwt")
}
springBootVersion=2.5.3
springSecurity=5.5.1
Is there some dependency that I am missing, or is there some config or something else?
The JwtDecoder is used within the Jwt Configuration to decode, and validate the incoming token against the public keys.
There's multiple ways of building the bean provided via some factory methods in the JwtDecoders class.
Specifically,
JwtDecoders.fromIssuerUri(...) and JwtDecoders.fromOidcIssuerUri(...) and I believe theres now a third method for pointing directly at a key.
The decoder it self can be explicitly set on the decoder method on the jwt configuration if you want/need to build one manually e.g. want to more add validations to the JwtDecoder.
If you read the javadoc of the OAuth2ResourceServerConfigurer there's also the option to set the Jwk Set URI via the jwkSetUri method which would also build a decoder.
The exact point the JwtDecoder is used is within the JwtAuthenticationProvider which will eventually be called from the BearerTokenAuthenticationFilter

Spring looking for PostgreSql driver, but I'm using JTDS

Loading a spring cloud dataflow app fails with this log:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: org.postgresql.Driver
But configuration is:
spring.jpa.database=sybase
spring.datasource.url=jdbc:jtds:sybase://xxx:X000/xxxx;autoCommit=false;appName=dataflow
spring.datasource.username=xx
spring.datasource.password=xxx
spring.datasource.driver-class-name=net.sourceforge.jtds.jdbc.Driver
spring.datasource.hikari.driver-class-name=net.sourceforge.jtdatasource.jdbc.Driver
spring.datasource.hikari.pool-name=datasource-pool
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.maximum-pool-size=2
spring.datasource.hikari.minimum-idle=0
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.auto-commit=false
spring.datasource.hikari.transaction-isolation=TRANSACTION_READ_COMMITTED
Dependency:
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
PostgreSql is never specified.
Using spring boot 2.3.3
Update:
I think something in spring dataflow context is setting the driver, because it works if I create my own configuration class and don't use spring.datasource prefix:
#Configuration
public class DataSourceConfiguration {
#Bean
#Primary
#ConfigurationProperties("spring.ds")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.ds.hikari")
public HikariDataSource sybaseDataSource() {
return dataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}

Springboot upgrade 1.5.8 to 2.0 release getting exception "org.springframework.beans.factory.NoSuchBeanDefinitionException"

Gradle dependency related to kubernetes:
"io.fabric8:spring-cloud-kubernetes-core:0.1.6",
"io.fabric8:spring-cloud-starter-kubernetes:0.1.6",
"org.springframework.cloud:spring-cloud-starter-sleuth:1.2.4.RELEASE",
Getting the below exception while upgrading springboot 1.5.6 to 2.0.0.Release
Parameter 2 of method configurationUpdateStrategy in
io.fabric8.spring.cloud.kubernetes.reload.ConfigReloadAutoConfiguration$ConfigReloadAutoConfigurationBeans required a bean of type 'org.springframework.cloud.context.restart.RestartEndpoint' that could not be found.
Bean method 'restartEndpoint' not loaded because #ConditionalOnClass did not find required class 'org.springframework.integration.monitor.IntegrationMBeanExporter'
Bean method 'restartEndpointWithoutIntegration' in 'RestartEndpointWithoutIntegrationConfiguration' not loaded because #ConditionalOnEnabledEndpoint found property management.endpoint.restart.enabled with value false
You can do either of following, depending on your requirements:
Disable ConfigReloadAutoConfiguration if you don't need it:
#SpringBootApplication(exclude = ConfigReloadAutoConfiguration.class)
public class SomeApplication {
...
}
Add the following into your application.properties, just as the error message says:
management.endpoint.restart.enabled = true

Usage of Spring #ConfigurationProperties gives nullpointer when running tests, JHipster app

I have implemented a simple file upload routine using Spring Boot ConfigurationProperties annotation so I can load the directory from my YAML configuration file:
Service:
#Service
public class FileSystemStorageService implements StorageService {
private final Logger log = LoggerFactory.getLogger(FileSystemStorageService.class);
private final Path pictureLocation;
#Autowired
public FileSystemStorageService(StorageProperties storageProperties) {
pictureLocation = Paths.get(storageProperties.getUpload());
}
And the StorageProperties:
#Component
#ConfigurationProperties("nutrilife.meals")
public class StorageProperties {
private String upload;
public String getUpload() {
return upload;
}
public void setUpload(String upload) {
this.upload= upload;
}
}
In the yaml file I have:
nutrilife:
meals:
upload: /$full_path_to_my_upload_dir
This works perfectly in normal Spring Boot runtime but the problem starts when I try to run my integration tests, it throws the error:
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fileSystemStorageService' defined in file [/home/mmaia/git/nutrilife/build/classes/main/com/getnutrilife/service/upload/FileSystemStorageService.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.getnutrilife.service.upload.FileSystemStorageService]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:279)
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.getnutrilife.service.upload.FileSystemStorageService]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154)
So basically during tests the YAML file configuration looks like it's not being properly picked up. I am new to Spring. How can I fix it?
try adding the #value annotation :
#Value("upload")
private String upload;
The above answer is valid for application.properties config.
it also works with yaml as well.
You may find your correct correct yaml config here :
24.6 Using YAML instead of Properties

Resources