Spring 5.3/Spring Boot 2.4 support

(Original URL)

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

-        requestMapping.getPatternsCondition());
+        requestMapping.getActivePatternsCondition());

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

Comments (84)

+77
  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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));
    }
+36

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);
            }
        }
    };
}
+26

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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());
+13

In my case shifting to SpringDoc worked like charm

+10

The following workaround works with both spring.mvc.pathmatch.matching-strategy options and with/without actuator dependency. (My preference is to avoid overriding Spring Boot’s opinionated default values when possible.)


@Bean
public InitializingBean removeSpringfoxHandlerProvider(DocumentationPluginsBootstrapper bootstrapper) {
    return () -> bootstrapper.getHandlerProviders().removeIf(WebMvcRequestHandlerProvider.class::isInstance);
}

@Bean
public RequestHandlerProvider customRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) {
    String contextPath = servletContext.map(ServletContext::getContextPath).orElse(Paths.ROOT);
    return () -> handlerMappings.stream()
        .filter(mapping -> !mapping.getClass().getSimpleName().equals("IntegrationRequestMappingHandlerMapping"))
        .map(mapping -> mapping.getHandlerMethods().entrySet())
        .flatMap(Set::stream)
        .map(entry -> new WebMvcRequestHandler(contextPath, methodResolver, tweakInfo(entry.getKey()), entry.getValue()))
        .sorted(byPatternsCondition())
        .collect(toList());
}

RequestMappingInfo tweakInfo(RequestMappingInfo info) {
    if (info.getPathPatternsCondition() == null) return info;
    String[] patterns = info.getPathPatternsCondition().getPatternValues().toArray(String[]::new);
    return info.mutate().options(new BuilderConfiguration()).paths(patterns).build();
}
+10

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。

+9

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.

+7

Not working with Spring Boot 2.6.6

+6

Is there any update on this issue? Should we wait for a new version soon?

I suggest you migrate to springdoc.

+6

Not working with Spring Boot 2.6.0

+5

I did a half-baked PR to fix this but I also gave up on it. It was easier just to switch to SpringDoc

+4

@RamyaIndudhar first of all I was wrong: you need both changes as it was declared in the original post. If you do only bullet 2 the service will startup correctly but the swagger documentation won’t show up in the related html page.

About the piece of code, you just need to add it in your project into a @Configuration class. And as said, don’t forget to add also this line in your application properties configuration file: spring.mvc.pathmatch.matching-strategy: ant_path_matcher

+3

I think we will move to springdoc eventually, this springfox is starting to take more time to keep working with new updates, than it would be to just migrate :S

I bit the bullet a while ago and updated all our micro services and libraries to SpringDoc. Since we didn’t use a lot of fancy stuff, and were quite consistent in how we documented our APIs, I was actually able to script >90% of the changes to be automatically applied too all our sources (I’m pretty good with Perl and regex 😉).

In the end I’m very happy with the result and in fact have been able to improve the final outcome quite a bit (e.g. I added authentication so we can in finally try out secured APIs directly from the Swagger documentation).

+3

Just migrate to SpringDoc SpringFox is deprecated and abandoned

https://springdoc.org/migrating-from-springfox.html

+3

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.

+3

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.

+2
  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties

    1. 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));
    }

Thank you so much !! This solution works fine with spring fox 3.0.0 and spring boot 2.6.4.

+2

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);
    }
+2

👍 Better than mine.

+2

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.

+2

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.

+1

Step 1 : Change the springboot version in pom.xml file of Comet Service org.springframework.boot spring-boot-starter-parent 2.5.12 Note: Springboot 2.5.12 internally downloads and uses spring-core 5.3.18 dependency.

Step 2: Comment/Remove springfox’s below 2 old dependencies in pom.xml:

Step 3: Add below new dependency of springfox: io.springfox springfox-boot-starter 3.0.0

Step 4: change request mapping in SwaggerHomeController.java file @RequestMapping(“/”) public String home() { //return “redirect:swagger-ui.html”; --old return “redirect:swagger-ui/”;

   }

Step 5: Try accessing localhost: localhost:9034 in the browser which should automatically redirect to this URL http://localhost:9034/swagger-ui/

+1
  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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?

You can added in your SwaggerConfig

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);
            }
        }
    };
}

Working like charm, Thanks a lot

Make sure to use springfox 3.x http://springfox.github.io/springfox/docs/current/#migrating-from-existing-2-x-version

I solved the above problem by manually creating an instance of CorsEndpointProperties.

  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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));
    }

@WilliamZhai / @hhhhsw Could you please explain whats above piece of code is doing.

springfox have to use patternsCondition in RequestMappingInfo: org.springframework.web.servlet.mvc.method.RequestMappingInfo#

spring and spring actuator use pathPatternsCondition in RequestMappingInfo by default: org.springframework.web.servlet.mvc.method.RequestMappingInfo#pathPatternsCondition

two steps above make spring and spring actuator do not set default pathPatternsCondition.

I have added this bean and it works fine in IDEA, but running on the server throws the following exception:

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/opt/xxxx-services.jar!/BOOT-INF/lib/springfox-spring-web-2.9.2.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/opt/xxx-services.jar!/BOOT-INF/lib/springfox-spring-web-2.9.2.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webEndpointServletHandlerMapping' defined in class path resource [com/xxx/webconfig/ActuatorConfig.class]: Unsatisfied dependency expressed through method 'webEndpointServletHandlerMapping' parameter 4; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} image

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);
            }
        }
    };
}

Working like charm, Thanks a lot

I used this config and it works for CloudFoundry container with/or not actuator.

yaml config : spring: mvc: pathmatch: matching-strategy: ant_path_matcher

` import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.util.ReflectionUtils; import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;

import java.lang.reflect.Field; import java.util.List; import java.util.stream.Collectors;

… … @Bean public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { return new BeanPostProcessor() {

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof WebMvcRequestHandlerProvider) {
			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);
		}
	}
};

}`

Happy to do not need to add : management: cloudfoundry: enabled: false

这是另一种解决方法:

  1. 将匹配策略 spring.mvc.pathmatch.matching-strategy 还原为 ant-path-matcher
  2. 将此 bean 添加到您的应用程序中:
@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);
            }
        }
    };
}

牛逼,thank you !

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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());

This hack worked for me, thank you🙌

On JDK17 + Boot 2.6.3 + Springfox 3.0.0, this @Bean provider works for me because the only controllers I wanted in Swagger were annotated @RequestMapping:

    @Bean
    public WebMvcRequestHandlerProvider webMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) {
        handlerMappings = handlerMappings.stream().filter(rh -> rh.getClass().getName().contains("RequestMapping")).toList();
        return new WebMvcRequestHandlerProvider(servletContext, methodResolver, handlerMappings);
    }

I can see a few handlerMappings entries being passed into the method. The only one I need is an instance of RequestMappingHandlerMapping, and it cooperates with Springfox. The problem(s) came from one of the other handlerMappings entries describing Actuator endpoints.

I started from the @hhhhsw workaround above, but it didn’t work reliably in a CloudFoundry container, for reasons I could not figure out.

For CloudFoundry, the code responsible can be found in “CloudFoundryActuatorAutoConfiguration”. Unfortunately, you cannot override the Bean. However you can disable the actuator part “management.cloudfoundry.enabled” false. Just take a look at (https://docs.spring.io/spring-boot/docs/1.5.22.RELEASE/reference/html/production-ready-cloudfoundry.html) for implications of doing such a change.

  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties

    1. 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));
    }

Thank you so much !! This solution works fine with spring fox 3.0.0 and spring boot 2.6.4.

its working for me as well

Not working with Spring Boot 2.6.6

The bean workaround in 3th answer at https://stackoverflow.com/questions/70178343/springfox-3-0-0-is-not-working-with-spring-boot-2-6-0 helped me with this problem.

(also the " matching-strategy: ant_path_matcher"-thing that is mentioned in comment was not needed in this one api I am working with now, but it has often helped in other apis i have updated. Think it depends on springfox 2 vs 3)

Though the workaround bean seems a bit unreadable. I think we will move to springdoc eventually, this springfox is starting to take more time to keep working with new updates, than it would be to just migrate :S

@mstephenson6

Thanks for the workaround, that’ll buy us some time before we migrate to SpringDoc. 😃

Had to change this a bit for our setup (Kotlin, Spring Boot 2.6.6, Springfox 2.9.2):

@Bean
    fun webMvcRequestHandlerProvider(
        methodResolver: HandlerMethodResolver,
        handlerMappings: List<RequestMappingInfoHandlerMapping>
    ): WebMvcRequestHandlerProvider {
        val newMappings = handlerMappings
            .filter { it.javaClass.name.contains("RequestMapping") }
            .toList()
        return WebMvcRequestHandlerProvider(methodResolver, newMappings)
    }

Also had to configure “spring.main.allow-bean-definition-overriding=true” for this to work.

  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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));
    }

@WilliamZhai / @hhhhsw

Could you please explain whats above piece of code is doing.

springfox have to use patternsCondition in RequestMappingInfo: org.springframework.web.servlet.mvc.method.RequestMappingInfo#

spring and spring actuator use pathPatternsCondition in RequestMappingInfo by default: org.springframework.web.servlet.mvc.method.RequestMappingInfo#pathPatternsCondition

two steps above make spring and spring actuator do not set default pathPatternsCondition.

On JDK17 + Boot 2.6.3 + Springfox 3.0.0, this @Bean provider works for me because the only controllers I wanted in Swagger were annotated @RequestMapping:

    @Bean
    public WebMvcRequestHandlerProvider webMvcRequestHandlerProvider(Optional<ServletContext> servletContext, HandlerMethodResolver methodResolver, List<RequestMappingInfoHandlerMapping> handlerMappings) {
        handlerMappings = handlerMappings.stream().filter(rh -> rh.getClass().getName().contains("RequestMapping")).toList();
        return new WebMvcRequestHandlerProvider(servletContext, methodResolver, handlerMappings);
    }

I can see a few handlerMappings entries being passed into the method. The only one I need is an instance of RequestMappingHandlerMapping, and it cooperates with Springfox. The problem(s) came from one of the other handlerMappings entries describing Actuator endpoints.

I started from the @hhhhsw workaround above, but it didn’t work reliably in a CloudFoundry container, for reasons I could not figure out.

Thanks for dependency information. After adding springfox-boot-starter swagger-ui came back but this time it says No operations defined in spec!. However, I am sure there is no code change in swagger spec.

Hmm, I don’t have a clue here; I didn’t need to make any changes – but I was already using 3.0.0 with DocumentationType.SWAGGER_2 (I’m now actually on DocumentationType.OAS_30). When I upgraded springfox to 3.0.0, I did need to make changes as far as I remember.

Googled and found a workaround. Going with .paths(PathSelectors.any()) works and take swagger back as it was. But I have no idea now whether it will lead to some unexpected event.

Thanks for dependency information. After adding springfox-boot-starter swagger-ui came back but this time it says No operations defined in spec!. However, I am sure there is no code change in swagger spec.

Hmm, I don’t have a clue here; I didn’t need to make any changes – but I was already using 3.0.0 with DocumentationType.SWAGGER_2 (I’m now actually on DocumentationType.OAS_30). When I upgraded springfox to 3.0.0, I did need to make changes as far as I remember.

Oh yes, I needed to upgrade to latest version of both spring-boot(v2.6.2) and springfox-swagger-ui, springfox-swagger2 to v3.0.0. Both /swagger-ui/index.html and /swagger-ui/ doesn’t work.

Have you updated your security settings accordingly? It should contain "/swagger*/**" and some others, depending on the documentation mode (e.g. for DocumentationType.OAS_30, you need "/v3/api-docs" as well).

This is the dependency I use:

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

Thanks for dependency information. After adding springfox-boot-starter swagger-ui came back but this time it says No operations defined in spec!. However, I am sure there is no code change in swagger spec.

Oh yes, I needed to upgrade to latest version of both spring-boot(v2.6.2) and springfox-swagger-ui, springfox-swagger2 to v3.0.0. Both /swagger-ui/index.html and /swagger-ui/ doesn’t work.

Have you updated your security settings accordingly? It should contain "/swagger*/**" and some others, depending on the documentation mode (e.g. for DocumentationType.OAS_30, you need "/v3/api-docs" as well).

This is the dependency I use:

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

Workaround for Spring Boot 2.6.x

1. revert matching strategy `spring.mvc.pathmatch.matching-strategy` to `ant-path-matcher`

2. hack springfox [WebMvcRequestHandlerProvider](https://github.com/springfox/springfox/blob/master/springfox-spring-webmvc/src/main/java/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.java#L63) to filter out actuator controllers which don't respect `spring.mvc.pathmatch.matching-strategy`

This worked, but response to swagger-ui.html returns 404.

Have you updated to a more recent springfox by any chance? The new version uses swagger-ui/ (mind the final slash) or swagger-ui/index.html.

Oh yes, I needed to upgrade to latest version of both spring-boot(v2.6.2) and springfox-swagger-ui, springfox-swagger2 to v3.0.0. Both /swagger-ui/index.html and /swagger-ui/ doesn’t work.

Nope, they will tell you to migrate to SpringDoc.

Workaround for Spring Boot 2.6.x

1. revert matching strategy `spring.mvc.pathmatch.matching-strategy` to `ant-path-matcher`

2. hack springfox [WebMvcRequestHandlerProvider](https://github.com/springfox/springfox/blob/master/springfox-spring-webmvc/src/main/java/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.java#L63) to filter out actuator controllers which don't respect `spring.mvc.pathmatch.matching-strategy`

This worked, but response to swagger-ui.html returns 404.

Have you updated to a more recent springfox by any chance? The new version uses swagger-ui/ (mind the final slash) or swagger-ui/index.html.

does @springfox accept PRs, so the “hack” could make it into a real fix?

@teodoracornea ensure you have the right import: import org.springframework.util.ReflectionUtils;

Thank you very much, now my actuator works ❤️

@teodoracornea ensure you have the right import: import org.springframework.util.ReflectionUtils;

Cannot resolve method 'findField What should I do?

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.

@danparisi Could you please explain what above piece of code is doing

  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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));
    }

@WilliamZhai / @hhhhsw

Could you please explain whats above piece of code is doing.

  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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?

  1. set spring.mvc.pathmatch.matching-strategy: ant_path_matcher in application.properties
  2. 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.

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?

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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怕是又要一堆奇奇怪怪的异常

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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, 项目成功启动,哈哈

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
  1. spring.mvc.pathmatch.matching-strategy to ant-path-matcher

Have you set spring.mvc.pathmatch.matching-strategy to ant-path-matcher?

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)
                }
            }
        }
    }

}

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);
            }
        }
    };
}

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

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);
            }
        }
    };
}

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:

  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);
            }
        }
    };
}

This way can really solve the problem I’m having right now, thank you!

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.

so this project is not maintained anymore?

Is there any update on this issue? Should we wait for a new version soon?

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);
            }
        }
    };
}

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, will this be patched to SpringFox 2.9.x or would we need to upgrade to SpringFox 3.0.x?

It worked =) Thanks a lot.

Hope SpringFox can release a new version soon to remove the workaround solution.

springfox.documentation.spring.web.plugins

I mean you should keep the original package name springfox.documentation.spring.web.plugins, not your own.

Thanks @quaff but I put “test.com” just to not add here all package of my private project.

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]

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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.

Workaround for Spring Boot 2.6.x

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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

  1. revert matching strategy spring.mvc.pathmatch.matching-strategy to ant-path-matcher
  2. 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?

From the perspective of debugging, the condition content of the old version has value / {???} / {???} But the new version is empty

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

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.

The same problem still happens with Spring Boot 2.6.0-RC1.

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?

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!

Confirming that I have encountered this issue in Spring Boot 2.6.0-M3 also.

Are you planning on adding support for Spring Boot 2.6.0-M3?

I am also running into this same issue. Is there a ETA for Spring 5.3 support?