SpringBoot2.6.0/Springfox3-启动 bean‘ documentationPluginsBootstrapper’失败

我正在尝试使用 OpenJDK15、 SpringBoot2.6.0、 Springfox3启动一个 SpringBoot 项目。

我们正在开发一个项目,该项目取代了 Netty作为 Web 服务器,而使用了 Jetty,因为我们不需要非阻塞环境。

在代码中,我们主要依赖于反应堆 API (Flux,Mono) ,所以我们不能删除 org.springframework.boot:spring-boot-starter-webflux依赖项。

我复制了我们在一个新项目中遇到的问题: https://github.com/jvacaq/spring-fox

我发现 建造,分级文件中的这些行是问题的根源。

compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")

这是 建造,分级文件:

plugins {
id 'org.springframework.boot' version '2.6.0'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}


group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'


repositories {
mavenCentral()
}


dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
implementation 'org.springframework.boot:spring-boot-starter-webflux'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
implementation "io.springfox:springfox-boot-starter:3.0.0"
}


test {
useJUnitPlatform()
}

我发出了命令 gradle clean bootrun。结果是这个错误:

gradle clean bootrun


> Task :bootRun FAILED


.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::                (v2.6.0)


2021-11-19 09:41:06.665  INFO 16666 --- [           main] c.e.springfox.SpringFoxApplication       : Starting SpringFoxApplication using Java 15.0.2 on advance-Inspiron-5379 with PID 16666 (/home/advance/projects/spring-fox/build/classes/java/main started by advance in /home/advance/projects/spring-fox)
2021-11-19 09:41:06.666  INFO 16666 --- [           main] c.e.springfox.SpringFoxApplication       : No active profile set, falling back to default profiles: default
2021-11-19 09:41:07.294  INFO 16666 --- [           main] org.eclipse.jetty.util.log               : Logging initialized @1132ms to org.eclipse.jetty.util.log.Slf4jLog
2021-11-19 09:41:07.396  INFO 16666 --- [           main] o.s.b.w.e.j.JettyServletWebServerFactory : Server initialized with port: 8080
2021-11-19 09:41:07.398  INFO 16666 --- [           main] org.eclipse.jetty.server.Server          : jetty-9.4.44.v20210927; built: 2021-09-27T23:02:44.612Z; git: 8da83308eeca865e495e53ef315a249d63ba9332; jvm 15.0.2+7-27
2021-11-19 09:41:07.417  INFO 16666 --- [           main] o.e.j.s.h.ContextHandler.application     : Initializing Spring embedded WebApplicationContext
2021-11-19 09:41:07.417  INFO 16666 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 713 ms
2021-11-19 09:41:07.474  INFO 16666 --- [           main] org.eclipse.jetty.server.session         : DefaultSessionIdManager workerName=node0
2021-11-19 09:41:07.474  INFO 16666 --- [           main] org.eclipse.jetty.server.session         : No SessionScavenger set, using defaults
2021-11-19 09:41:07.475  INFO 16666 --- [           main] org.eclipse.jetty.server.session         : node0 Scavenging every 660000ms
2021-11-19 09:41:07.480  INFO 16666 --- [           main] o.e.jetty.server.handler.ContextHandler  : Started o.s.b.w.e.j.JettyEmbeddedWebAppContext@6aa3bfc{application,/,[file:///tmp/jetty-docbase.8080.2024342829220941812/, jar:file:/home/advance/.gradle/caches/modules-2/files-2.1/io.springfox/springfox-swagger-ui/3.0.0/1e665fbe22148f7c36fa8a08e515a0047cd4390b/springfox-swagger-ui-3.0.0.jar!/META-INF/resources],AVAILABLE}
2021-11-19 09:41:07.480  INFO 16666 --- [           main] org.eclipse.jetty.server.Server          : Started @1318ms
2021-11-19 09:41:07.920  INFO 16666 --- [           main] o.e.j.s.h.ContextHandler.application     : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-11-19 09:41:07.920  INFO 16666 --- [           main] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-11-19 09:41:07.921  INFO 16666 --- [           main] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2021-11-19 09:41:07.931  INFO 16666 --- [           main] o.e.jetty.server.AbstractConnector       : Started ServerConnector@2643d762{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2021-11-19 09:41:07.932  INFO 16666 --- [           main] o.s.b.web.embedded.jetty.JettyWebServer  : Jetty started on port(s) 8080 (http/1.1) with context path '/'
2021-11-19 09:41:07.934  WARN 16666 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: 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
2021-11-19 09:41:07.949  INFO 16666 --- [           main] o.e.jetty.server.AbstractConnector       : Stopped ServerConnector@2643d762{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2021-11-19 09:41:07.950  INFO 16666 --- [           main] org.eclipse.jetty.server.session         : node0 Stopped scavenging
2021-11-19 09:41:07.951  INFO 16666 --- [           main] o.e.j.s.h.ContextHandler.application     : Destroying Spring FrameworkServlet 'dispatcherServlet'
2021-11-19 09:41:07.951  INFO 16666 --- [           main] o.e.jetty.server.handler.ContextHandler  : Stopped o.s.b.w.e.j.JettyEmbeddedWebAppContext@6aa3bfc{application,/,[file:///tmp/jetty-docbase.8080.2024342829220941812/, jar:file:/home/advance/.gradle/caches/modules-2/files-2.1/io.springfox/springfox-swagger-ui/3.0.0/1e665fbe22148f7c36fa8a08e515a0047cd4390b/springfox-swagger-ui-3.0.0.jar!/META-INF/resources],STOPPED}
2021-11-19 09:41:07.958  INFO 16666 --- [           main] ConditionEvaluationReportLoggingListener :


Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-11-19 09:41:07.970 ERROR 16666 --- [           main] o.s.boot.SpringApplication               : Application run failed


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:181) ~[spring-context-5.3.13.jar:5.3.13]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.13.jar:5.3.13]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.13.jar:5.3.13]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.13.jar:5.3.13]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.13.jar:5.3.13]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.13.jar:5.3.13]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.13.jar:5.3.13]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.0.jar:2.6.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-2.6.0.jar:2.6.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) ~[spring-boot-2.6.0.jar:2.6.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.0.jar:2.6.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.0.jar:2.6.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[spring-boot-2.6.0.jar:2.6.0]
at com.example.springfox.SpringFoxApplication.main(SpringFoxApplication.java:10) ~[main/:na]
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.countRunAndMakeAscending(TimSort.java:355) ~[na:na]
at java.base/java.util.TimSort.sort(TimSort.java:220) ~[na:na]
at java.base/java.util.Arrays.sort(Arrays.java:1306) ~[na:na]
at java.base/java.util.ArrayList.sort(ArrayList.java:1721) ~[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:1625) ~[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:178) ~[spring-context-5.3.13.jar:5.3.13]
... 14 common frames omitted




FAILURE: Build failed with an exception.


* What went wrong:
Execution failed for task ':bootRun'.
> Process 'command '/home/advance/.sdkman/candidates/java/15.0.2-open/bin/java'' finished with non-zero exit value 1


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.


* Get more help at https://help.gradle.org


Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.9.1/userguide/command_line_interface.html#sec:command_line_warnings


BUILD FAILED in 2s
5 actionable tasks: 5 executed

我该怎么解决呢?

104499 次浏览

This problem's caused by a bug in Springfox. It's making an assumption about how Spring MVC is set up that doesn't always hold true. Specifically, it's assuming that MVC's path matching will use the Ant-based path matcher and not the PathPattern-based matcher. PathPattern-based matching has been an option for some time now and is the default as of Spring Boot 2.6.

As described in Spring Boot 2.6's release notes, you can restore the configuration that Springfox assumes will be used by setting spring.mvc.pathmatch.matching-strategy to ant-path-matcher in your application.properties file. Note that this will only work if you are not using Spring Boot's Actuator. The Actuator always uses PathPattern-based parsing, irrespective of the configured matching-strategy. A change to Springfox will be required if you want to use it with the Actuator in Spring Boot 2.6 and later.

Not a solution but...

I downgraded spring-boot-starter-parent version from 2.6.0 to 2.5.6 and it started to work.

I will complete what Anatoly mentioned about using springdoc-openapi.

First add the springdoc-openapi dependency to your Gradle build.gradle (or Maven pom.xml):

// build.gradle
implementation "org.springdoc:springdoc-openapi-ui:1.6.4"

Add OpenAPIDefinition annotation to your main class:

@SpringBootApplication
@OpenAPIDefinition
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

Now you can go to {URI}/swagger-ui/index.html and it will work showing the swagger view.

The workaround mentioned in the below issue comment seems to be working for people with spring actuator as well. Just changing the path matcher won't work for projects using actuator.

  1. Set in application.properties file:

    spring.mvc.pathmatch.matching-strategy to ant_path_matcher

  2. Add the @Bean below:


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

Reference:

Remove anotations

@EnableSwagger2
@SpringBootApplication
@EnableSwagger2
public class Application {}

Only adding @EnableWebMvc in the main class should resolve the problem:

@EnableWebMvc
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class);
}
}

The popular workaround overriding a definition of WebMvcEndpointHandlerMapping was not working for me in some environments with JDK 17, Boot+Actuator 2.6, Springfox 3.

This, however, is working for me everywhere I need it (local development and CloudFoundry containers):

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

I wrote a little more about it on the GitHub thread.

Just if someone is having difficulties with this setup, here is my config which is setup for actuator and spring boot 2.6.6:

In my application.yaml:

swagger:
title: ^project.name^
description: ^project.description^
version: ^project.version^
termsOfServiceUrl: \#
contactName: Your name
contactUrl: \#
contactEmail: email
license: License of API
licenseUrl: \#

Make sure that in your pom.xml within <properties> you place:

<properties>
<resource.delimiter>^</resource.delimiter>
</properties>

The above is important for following config:

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Getter
@Setter
@Configuration
@EnableSwagger2
@ConfigurationProperties(prefix = "swagger")
public class SwaggerFoxConfig {


private String title;
private String description;
private String version;
private String termsOfServiceUrl;
private String license;
private String licenseUrl;
private String contactName;
private String contactUrl;
private String contactEmail;


@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.select()
.apis(RequestHandlerSelectors.basePackage("path.to.base.package"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
}


private ApiInfo apiInfo() {
System.out.println(this.title);
return new ApiInfo(
this.title,
this.description,
this.version,
this.termsOfServiceUrl,
new Contact(this.contactName, this.contactUrl, this.contactEmail),
this.license,
this.licenseUrl,
Collections.emptyList());
}


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

Also in your .yaml or .properties have this setup:

spring:
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
jpa:
bla..
    

    

springfox:
documentation:
swagger-ui:
baseUrl: scheduler-service

Back to pom.xml, have your Spring Boot version and Actuator setup:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version> <!-- lookup parent from repository -->
<relativePath/>
</parent>


...


<properties>
<spring.fox.version>3.0.4</spring.fox.version>
</properties>
   

<dependencies>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${spring.fox.version}</version>
</dependency>
</dependencies>

You can find Swagger UI at:

http://localhost:8080/your-service-name-from-tag-'name'-in-pom-xml/swagger-ui/index.html

I already had a working system on Spring Boot 1.5.5.RELEASE and things stopped working when I upgraded to Spring Boot version 2.7.2 and 3.0.0 of SpringFox. Followed all steps of Migration Steps but that doesn't solved issue.

Had to do two additional things,

  1. In swagger config class - new Docket(DocumentationType.OAS_30) instead of new Docket(DocumentationType.SWAGGER_2)

  2. @EnableOpenApi on swagger config class

Swagger is finally coming at a new url than previous versions ( /swagger-ui.html )

/swagger-ui/index.html

Other than the mentioned answer took help from

Also, its a REST API project for me so I don't use EnableWebMvc

Just add this to your application.properties file:spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER.

Path matching policy switch back to ant_path_matcher Add the below line to the application.properties file

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

Add the following definition of the bean

public class SpringBootApplication {


public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
@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 used the first method and solved the problem after adding just one configuration. If you’ve encountered this problem recently, I hope this article helps you.

I have similar issue where I am getting the error like this:

springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper: Unable to scan documentation context default

With NullPointerException

This issue I solved by modifying couple of changes.

  1. Instead of this

.apis(RequestHandlerSelectors.basePackage(basePackage))

 I used this-

.apis(RequestHandlerSelectors.any())

  1. Another change I made is: Add url pattern to get the specific urls only(This is subjective by the way)

.paths(PathSelectors.ant("/external/**"))

The tech stack is:

  • Spring-Boot:2.5.0
  • Swagger:3.0.0

These steps worked for me with SpringBoot version > 2.6
One thing to note it that dependency io.springfox:springfox-boot-starter:3.0.0 doesnt works well with SpringBoot v > 2.6
See this for more info: https://stackoverflow.com/a/64333853
If your springboot version is less than 2.6 follow this answer :
https://stackoverflow.com/a/74433644/16769477

Step 1: Added following dependencies in build.gradle for springfox.

implementation "io.springfox:springfox-swagger-ui:2.9.2"
implementation "io.springfox:springfox-swagger2:2.9.2"
implementation "io.springfox:springfox-schema:2.9.2"

Step 2: Added this property in application.properties

spring.mvc.pathmatch.matching-strategy = "ANT_PATH_MATCHER"

Step 3: Created a config file as

@EnableSwagger2
@Configuration
public class SpringFoxSwaggerConfig {


@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(metadata());
}


private ApiInfo metadata() {
return new ApiInfoBuilder()
.title("")
.description("")
.version("")
.version("2.0")
.contact(new Contact(null, null, "this.developer"))
.build();
}
}

clean and build the project
Swagger endpoint should be accessible at these endpoints

http://host-name/servlet-context/v2/api-docs
http://host-name/servlet-context/swagger-ui/index.html

Just create or modify configuration file with adding @EnableWebMvc annotation, sth like this:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurationSupport {}