Open MiniDigger opened 4 years ago
I am also running into this same issue. Is there a ETA for Spring 5.3 support?
I also have the same problem。 I find this:spring boot 2.6.0-M2 is support,but spring boot 2.6.0-M3 not support spring framwork 5.3.9 support, but spring framwork 5.3.10 not support now I am find what problem cause。
and I want to know if this project not continue maintenance。it has 12 month not update。
Are you planning on adding support for Spring Boot 2.6.0-M3?
Confirming that I have encountered this issue in Spring Boot 2.6.0-M3 also.
I also have the same problem。 I find this:spring boot 2.6.0-M2 is support,but spring boot 2.6.0-M3 not support spring framwork 5.3.9 support, but spring framwork 5.3.10 not support now I am find what problem cause。
and I want to know if this project not continue maintenance。it has 12 month not update。
I also have the same proplem. And the reason is this. Thanks!
Are you planning on adding support for Spring Boot 2.6.0-M3?
I wait springfox official to fix this problem。or hope spring boot 2.6.0 release can support old version。when I have time, I alse want to support affter Spring Boot 2.6.0-M3?
The same problem still happens with Spring Boot 2.6.0-RC1.
Hacky workaround (don't know what that breaks, I don't use Documentation):
Remove @Component from springfox-spring-web/src/main/java/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.java
My app launches afterwards and works.
Not working with Spring Boot 2.6.0
I find this in the Spring Boot Release-Notes, But it seems not works for me. https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes#pathpattern-based-path-matching-strategy-for-spring-mvc
I find this in the Spring Boot Release-Notes, But it seems not works for me. https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes#pathpattern-based-path-matching-strategy-for-spring-mvc
yeah it didn't work
From the perspective of debugging, the condition content of the old version has value / {???} / {???} But the new version is empty
Workaround for Spring Boot 2.6.x
spring.mvc.pathmatch.matching-strategy
to ant-path-matcher
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver,
List<RequestMappingInfoHandlerMapping> handlerMappings) {
this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
how you hack it?
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
How exactly is this "hack"? Can you help us with some more complete info?
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
How exactly is this "hack"? Can you help us with some more complete info?
Copy WebMvcRequestHandlerProvider.java
to your project main source directory, then modify this line, that's why I call it hack not workaround.
Thanks for the answer, but this option does not work for me. It comes with more issues such as:
Failed to process import candidates for configuration class [springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'webMvcRequestHandlerProvider' for bean class [springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider] conflicts with existing, non-compatible bean definition of same name and class [test.com.WebMvcRequestHandlerProvider]
Thanks for the answer, but this option does not work for me. It comes with more issues such as:
Failed to process import candidates for configuration class [springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'webMvcRequestHandlerProvider' for bean class [springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider] conflicts with existing, non-compatible bean definition of same name and class [test.com.WebMvcRequestHandlerProvider]
You shouldn't change the package name to your own test.com
.
Thanks @quaff but I put "test.com" just to not add here all package of my private project.
springfox.documentation.spring.web.plugins
I mean you should keep the original package name springfox.documentation.spring.web.plugins
, not your own.
It worked =) Thanks a lot.
Hope SpringFox can release a new version soon to remove the workaround solution.
I don't have a lot of time today but I started this PR https://github.com/springfox/springfox/pull/3936 it's definitely not great because I think a lot of dependencies should be upgraded but it does build and all the tests pass.
I am not sure what @dilipkrish wants to do here, if you upgrade spring you will be forced to upgrade gradle/groovy and some other things.
Hi, will this be patched to SpringFox 2.9.x or would we need to upgrade to SpringFox 3.0.x?
Here is another work-around:
add this bean to your app:
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
👍 Better than mine.
Here is another work-around:
- revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
- add this bean to your app:
@Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) { List<T> copy = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(copy); } @SuppressWarnings("unchecked") private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) { try { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); field.setAccessible(true); return (List<RequestMappingInfoHandlerMapping>) field.get(bean); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } } }; }
Can you explain how I need to add this bean to my code? Sorry I am new to all of this. I added the bean to my SwaggerConfig class but getting an error "Cannot resolve method 'findField(java.lang.Class<capture<? extends java.lang.Object>>, java.lang.String)'" at this line: Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
Is there any update on this issue? Should we wait for a new version soon?
Is there any update on this issue? Should we wait for a new version soon?
I suggest you migrate to springdoc
.
so this project is not maintained anymore?
Honestly, I am thinking to migrate also, as I am facing several issue on my 2 projects (even though it worked for 1 project), and the project itself its a bit confusing, as basic example we never know which URL we must to use, and when has a migration, they change the ULR.
Here is another work-around:
- revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
- add this bean to your app:
@Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) { List<T> copy = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(copy); } @SuppressWarnings("unchecked") private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) { try { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); field.setAccessible(true); return (List<RequestMappingInfoHandlerMapping>) field.get(bean); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } } }; }
This way can really solve the problem I'm having right now, thank you!
Here is another work-around:
- revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
- add this bean to your app:
@Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) { List<T> copy = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(copy); } @SuppressWarnings("unchecked") private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) { try { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); field.setAccessible(true); return (List<RequestMappingInfoHandlerMapping>) field.get(bean); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } } }; }
Can you explain how I need to add this bean to my code? Sorry I am new to all of this. I added the bean to my SwaggerConfig class but getting an error "Cannot resolve method 'findField(java.lang.Class<capture<? extends java.lang.Object>>, java.lang.String)'" at this line: Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
Hi, you just have to put that bean in a class annotated with @Configuration like this:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.*;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.builders.*;
import springfox.documentation.service.*;
import springfox.documentation.spi.*;
import springfox.documentation.spring.web.plugins.*;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;
@Configuration
public class Swagger2Config {
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider
|| bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(
List<T> mappings) {
List<T> copy =
mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}
Here is another work-around:
- revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
- add this bean to your app:
@Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) { List<T> copy = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(copy); } @SuppressWarnings("unchecked") private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) { try { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); field.setAccessible(true); return (List<RequestMappingInfoHandlerMapping>) field.get(bean); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } } }; }
Can you explain how I need to add this bean to my code? Sorry I am new to all of this. I added the bean to my SwaggerConfig class but getting an error "Cannot resolve method 'findField(java.lang.Class<capture<? extends java.lang.Object>>, java.lang.String)'" at this line: Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
Hi, you just have to put that bean in a class annotated with @configuration like this:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.*; import org.springframework.util.ReflectionUtils; import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; import springfox.documentation.builders.*; import springfox.documentation.service.*; import springfox.documentation.spi.*; import springfox.documentation.spring.web.plugins.*; import java.lang.reflect.Field; import java.util.List; import java.util.stream.Collectors; @Configuration public class Swagger2Config { @Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings( List<T> mappings) { List<T> copy = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(copy); } @SuppressWarnings("unchecked") private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) { try { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); field.setAccessible(true); return (List<RequestMappingInfoHandlerMapping>) field.get(bean); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } } }; } }
The above solution worked for me, Thanks
Workaround worked for startup problems - but no swagger api documentation will be found anymore.
Anyway for anyone who needs it in Kotlin
@Configuration
class SwaggerBeanPostProcessor {
@Bean
fun springfoxHandlerProviderBeanPostProcessor(): BeanPostProcessor {
return object : BeanPostProcessor {
@Throws(BeansException::class)
override fun postProcessAfterInitialization(bean: Any, beanName: String): Any {
if (bean is WebMvcRequestHandlerProvider || bean is WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean))
}
return bean
}
private fun <T : RequestMappingInfoHandlerMapping?> customizeSpringfoxHandlerMappings(mappings: MutableList<T>) {
val copy = mappings.filter { mapping -> mapping?.patternParser == null }
mappings.clear()
mappings.addAll(copy)
}
@Suppress("UNCHECKED_CAST")
private fun getHandlerMappings(bean: Any): MutableList<RequestMappingInfoHandlerMapping> {
return try {
val field = ReflectionUtils.findField(bean.javaClass, "handlerMappings")
field?.setAccessible(true)
field?.get(bean) as MutableList<RequestMappingInfoHandlerMapping>
} catch (e: Exception) {
throw IllegalStateException(e)
}
}
}
}
}
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
Have you set spring.mvc.pathmatch.matching-strategy
to ant-path-matcher
?
Please Refer: https://github.com/springfox/springfox#migrating-from-earlier-snapshot In application.properties add: spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
In pom.xml add:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
It's ok.
The customizeSpringfoxHandlerMappings
method in the workaround can be simplified with:
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
mappings.removeIf(mapping -> mapping.getPatternParser() != null);
}
Please Refer: https://github.com/springfox/springfox#migrating-from-earlier-snapshot In application.properties add: spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
In pom.xml add:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
It's ok.
To add to this if you are still having the issue it seems to not work if you have the actuator dependency in your project found in this stackoverflow
Just to add this will not work if spring boot actuator dependency is there. I had to remove the actuator dependency (losing the actuator endpoints of course). and after adding this property with swagger version(s) up to 3.0.0 this worked – M. Amer Dec 19 at 18:00
Here is another work-around:
1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher 2. add this bean to your app:
@Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); } return bean; } private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) { List<T> copy = mappings.stream() .filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList()); mappings.clear(); mappings.addAll(copy); } @SuppressWarnings("unchecked") private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) { try { Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); field.setAccessible(true); return (List<RequestMappingInfoHandlerMapping>) field.get(bean); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } } }; }
In my case (Spring Boot 2.6.2 / Springfox 3.0.0) adding this bean was enough, I didn't need to revert matching strategy. Thank you.
In my case shifting to SpringDoc worked like charm
I did a half-baked PR to fix this but I also gave up on it. It was easier just to switch to SpringDoc
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
我下载了springfox的源码,按你说的修改了WebMvcRequestHandlerProvider 这个类,重新打个定制版的springfox-spring-webmvc-3.0.0.jar替换官方的jar, 项目成功启动,哈哈
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
我下载了springfox的源码,按你说的修改了WebMvcRequestHandlerProvider 这个类,重新打个定制版的springfox-spring-webmvc-3.0.0.jar替换官方的jar, 项目成功启动,哈哈
@laohuihui178 可以试试替换成springdoc
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
我下载了springfox的源码,按你说的修改了WebMvcRequestHandlerProvider 这个类,重新打个定制版的springfox-spring-webmvc-3.0.0.jar替换官方的jar, 项目成功启动,哈哈
@laohuihui178 可以试试替换成springdoc
我是通过knife4j 使用的swagger, 换成springdoc怕是又要一堆奇奇怪怪的异常
In my case shifting to SpringDoc worked like charm
I can confirm.
Tried most of the workarounds listed here, as far as I understand you cannot make it work if you have spring-boot-starter-actuator
in your stack.
I can confirm moving to latest org.springframework.boot
= 2.6.2 and springdoc-openapi-ui
= 1.6.3 solved the issue. For me, it was a clean solution.
Workaround for Spring Boot 2.6.x
- revert matching strategy
spring.mvc.pathmatch.matching-strategy
toant-path-matcher
- hack springfox WebMvcRequestHandlerProvider to filter out actuator controllers which don't respect
spring.mvc.pathmatch.matching-strategy
public WebMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) { this.handlerMappings = handlerMappings.stream().filter(mapping -> mapping.getPatternParser() == null) .collect(Collectors.toList());
我下载了springfox的源码,按你说的修改了WebMvcRequestHandlerProvider 这个类,重新打个定制版的springfox-spring-webmvc-3.0.0.jar替换官方的jar, 项目成功启动,哈哈
@laohuihui178 可以试试替换成springdoc
我是通过knife4j 使用的swagger, 换成springdoc怕是又要一堆奇奇怪怪的异常
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
Same error with Spring Boot 2.6.2 and Spring Fox 3.0.0. See hack in https://github.com/spring-petclinic/spring-petclinic-rest and its related commit https://github.com/spring-petclinic/spring-petclinic-rest/commit/517a399cabe4dd7a40c07a81facd599df3cbf9cd Same behavior in my company. Could you please fix this issue?
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
}
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}
- set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
- add this bean
@Bean public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) { List<ExposableEndpoint<?>> allEndpoints = new ArrayList(); Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints(); allEndpoints.addAll(webEndpoints); allEndpoints.addAll(servletEndpointsSupplier.getEndpoints()); allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints()); String basePath = webEndpointProperties.getBasePath(); EndpointMapping endpointMapping = new EndpointMapping(basePath); boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath); return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null); } private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) { return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT)); }
I have actuator and this worked, Thanks a lot! I'm using Spring boot 2.6.2, springfox 3.0.0, and actuator 2.6.2.
- set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
- add this bean
@Bean public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) { List<ExposableEndpoint<?>> allEndpoints = new ArrayList(); Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints(); allEndpoints.addAll(webEndpoints); allEndpoints.addAll(servletEndpointsSupplier.getEndpoints()); allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints()); String basePath = webEndpointProperties.getBasePath(); EndpointMapping endpointMapping = new EndpointMapping(basePath); boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath); return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null); } private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) { return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT)); }
I have actuator and this worked, Thanks a lot! I'm using Spring boot 2.6.2, springfox 3.0.0, and actuator 2.6.2.
Where should I add the bean?
If you enable the new PathPatternParser (https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc), springfox fails with an NPE
Details
``` org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:913) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:570) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.4.0-M1.jar:2.4.0-M1] at me.minidigger.hangar.HangarApplication.main(HangarApplication.java:10) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.0-M1.jar:2.4.0-M1] Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0] at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113) ~[springfox-core-3.0.0.jar:3.0.0] at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89) ~[springfox-spi-3.0.0.jar:3.0.0] at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) ~[na:na] at java.base/java.util.TimSort.binarySort(TimSort.java:296) ~[na:na] at java.base/java.util.TimSort.sort(TimSort.java:239) ~[na:na] at java.base/java.util.Arrays.sort(Arrays.java:1306) ~[na:na] at java.base/java.util.ArrayList.sort(ArrayList.java:1720) ~[na:na] at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392) ~[na:na] at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na] at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na] at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na] at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na] at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81) ~[springfox-spring-webmvc-3.0.0.jar:3.0.0] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na] at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1624) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na] at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107) ~[springfox-spring-web-3.0.0.jar:3.0.0] at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91) ~[springfox-spring-web-3.0.0.jar:3.0.0] at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82) ~[springfox-spring-web-3.0.0.jar:3.0.0] at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100) ~[springfox-spring-web-3.0.0.jar:3.0.0] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) ~[spring-context-5.3.0-M1.jar:5.3.0-M1] ... 19 common frames omitted ```I thought it was fixed by this line https://github.com/springfox/springfox/blob/master/springfox-spring-webmvc/src/main/java/springfox/documentation/spring/web/WebMvcRequestHandler.java#L83
but I couldn't get this to work in 5 minutes, this prolly needs larger refactors.
for reference: https://github.com/spring-projects/spring-framework/blob/b572f7618f01897b611a47376c538b88be4dff80/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java#L219
edit: if you face this issue, you should consider upgrading to springdoc since this lib seems dead: https://springdoc.org/migrating-from-springfox.html