Spring Boot 2.6.0 / Spring fox 3 - Failed to start bean 'documentationPluginsBootstrapper'
Asked Answered
Z

15

112

I'm trying to initiate a Spring Boot project using OpenJDK 15, Spring Boot 2.6.0, Springfox 3.

We are working on a project that replaced Netty as the web server and used Jetty instead, because we do not need a non-blocking environment.

In the code we depend primarily on Reactor API (Flux, Mono), so we can not remove org.springframework.boot:spring-boot-starter-webflux dependencies.

I replicated the problem that we have in a new project: https://github.com/jvacaq/spring-fox.

I figured out that these lines in our build.gradle file are the origin of the problem.

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

Here is the build.gradle file:

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

I issued the command gradle clean bootrun. The result is this error:

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

How can I solve it?

Zoara answered 19/11, 2021 at 15:9 Comment(7)
Consider migration to springdocLithomarge
Thanks, I migrated to Springdoc. I can not wait for a solution from Springfox team.Zoara
Only add @EnableWebMvc in main class resolved the problem. https://mcmap.net/q/195651/-springfox-3-0-0-is-not-working-with-spring-boot-2-6-0-duplicateBriard
It's not a trivial endeavor to migrate a springfox setup to springdoc if you have some complexity in your configuration.Beckwith
Also migrated to springdoc. The complexity of that task will likely depend on your project, but it did solve my problem and put me on a library that was updated a month ago instead of a year and a half ago.Neutrino
Checkout this post. It explains for both Maven and Gradle. youtu.be/1gEoiMVULt4Gatepost
Does this answer your question? Spring boot 3 doesn't work with springfox 3.0Lawman
F
139

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.

Faefaeces answered 19/11, 2021 at 15:49 Comment(11)
Thanks for your answer. But adding following line in application.properties didn't work. And I got the same exception. spring.mvc.pathmatch.matching-strategy=ant_path_matcherZippy
On version Swagger 2 (2.9.2) this solution works fine too thanks a lotMiffy
I've noticed that this solution EXCEPT it is not compatible with spring-boot-starter-actuator. Once that is factored out all my submodules worked with the ant_path_matcher solution.Codpiece
As Paul commented above, spring-boot-starter-actuator also need to be kicked out.Wingate
@YangLiu The last three sentences of the answer already note that setting the property will only work if you are not using Spring Boot's Actuator. If you think this could be written more clearly, please propose an edit to the answer.Faefaeces
@Andy Wilkinson If I use actuator - is version rollback the only way ?Frida
@Frida I believe so, yes. Until there's a new Springfox release, you either need to downgrade to Spring Boot 2.5 or move away from Springfox to an alternative such as Springdoc. Sadly, Springfox doesn't seem to be as active as it once was so I would recommend considering alternatives anyway.Faefaeces
It worked for me! Spring Boot 2.6.6, springfox-boot-starter:3.0.4.Brockington
@ImanAliabdi I can't see the mentioned version of springfox-boot-starter, instead of 3.0.4, it has 3.0.0 on mvn repoEdmonton
springdoc.org works for me that need keep springboot actuator workingSheppard
Actuator works well with a solution provided below: https://mcmap.net/q/193853/-spring-boot-2-6-0-spring-fox-3-failed-to-start-bean-39-documentationpluginsbootstrapper-39Georgiannegeorgic
W
68

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:

Widely answered 28/1, 2022 at 10:21 Comment(5)
Thank you! This seems like the best answer if you dont wan't to downgrade spring or it is too much work to switch to springdocKarlotte
The application works after adding this, but swagger isn't working. I guess I'll switch to springdocMerrygoround
Best answer in my opinion! Especially if the requirement is to not degrade springboot and resolve vulnerabilities.Lossa
both this and @EnableWebMvc together worked for me on spring-boot 2.7.5 + springfox 3.0.0 and did NOT change matching-strategy property.Interdictory
When i added this bean, i can not expose actuator on different port with management.server.port config.Gymno
B
38

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);
    }
}
Beaut answered 27/2, 2022 at 21:25 Comment(7)
TBH I've just tried and it didn't work. That's why I downvoted.Liquescent
Thank you so much, many comments about Swagger or Spring's version that didn't solved, only adding @EnableWebMvc worked for me!Wynd
This fixed the issue for me. I am using spring boot version 2.7.0Sung
Be careful with @EnableWebMvcGeorgiannegeorgic
This worked . But i am afraid what can go wrong when this annotation is around :DCodie
This has worked. However it has affected JSON marshalling (Jackson) encoding somehow... Only Latin symbols are shown, the rest is ?????Rappee
https://mcmap.net/q/195910/-spring-boot-not-using-configured-jackson-objectmapper-with-enablewebmvcBriard
G
20

Not a solution but...

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

Guadalcanal answered 20/11, 2021 at 8:36 Comment(5)
Still a solution thoughAspiration
If you are upgrading to fix the security vulnerabilities, it will not work because the dependent libraries pulled by the spring boot will still show vulnerabilityHolub
Its better to follow what Andy or Anatoly suggested. Downgrading core framework's version is not a better option. :)Cuneate
If anyone goes down this path, use 2.5.8 or newer instead of 2.5.6!Maximilianus
I am using 2.7.1 so In that case downgrade is not an option for me. what should I do in that case ? @MaximilianusRegulable
A
9

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.

Apraxia answered 16/1, 2022 at 2:22 Comment(3)
Does open API work just like swagger? UI and everything else? Do we need to change anything else?Cartage
Yes same as swagger.Apraxia
Thanks, for your answer. works like a charm. easy and handyKelikeligot
B
4

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

Berber answered 4/8, 2022 at 6:52 Comment(1)
not working as a solution...still same errorRubierubiginous
M
2

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.

Moretta answered 16/3, 2022 at 12:32 Comment(0)
C
2

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.

Cruz answered 8/9, 2022 at 7:29 Comment(0)
H
2

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://mcmap.net/q/195911/-application-fails-to-start-after-trying-to-add-swagger-configuration-to-send-authorization-header-with-requests

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
Heulandite answered 18/11, 2022 at 12:51 Comment(0)
W
1

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

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurationSupport {}
Watanabe answered 2/12, 2022 at 10:6 Comment(0)
F
0

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

Fabliau answered 16/4, 2022 at 19:16 Comment(0)
S
0

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

Sensual answered 28/7, 2022 at 10:29 Comment(0)
F
0

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
Forelli answered 22/9, 2022 at 12:32 Comment(0)
G
0

First i added InternalResourceViewResolver and WebMvcEndpointHandlerMapping beans. I can run application without exception. But,when i try to expose actuator on different with management.server.port config, i faced below exception.

*************************** APPLICATION FAILED TO START


Description:

Parameter 4 of method webEndpointServletHandlerMapping in com.XXX.SwaggerBaseConfiguration required a bean of type 'org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties' that could not be found.

Action:

Consider defining a bean of type 'org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties' in your configuration.

Finally, i removed my custom WebMvcEndpointHandlerMappingand bean and my config class is like below. With this, i can run actutor on same port and different port,too.

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

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

@Configuration
public class SwaggerBaseConfiguration {

    @Bean
    public InternalResourceViewResolver defaultViewResolver() {
        return new InternalResourceViewResolver();
    }

    @Bean
    public 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");
                    if (Objects.isNull(field)) {
                        return new ArrayList<>();
                    }
                    field.setAccessible(true);
                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
        };
    }

}
Gymno answered 22/8, 2023 at 8:23 Comment(0)
D
-3

Remove anotations

@EnableSwagger2
@SpringBootApplication
@EnableSwagger2
public class Application {}
Dancer answered 29/1, 2022 at 21:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.