Springfox 3.0.0 is not working with Spring Boot 2.6.0 [duplicate]
Asked Answered
I

8

66

Springfox 3.0.0 is not working with Spring Boot 2.6.0, after upgrading I am getting the following error

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)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
    at com.enkindle.AntivirusApplication.main(AntivirusApplication.java:16)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
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)
    at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113)
    at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89)
    at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:473)
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
    at java.base/java.util.TimSort.sort(TimSort.java:234)
    at java.base/java.util.Arrays.sort(Arrays.java:1307)
    at java.base/java.util.ArrayList.sort(ArrayList.java:1721)
    at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107)
    at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91)
    at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100)
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
    ... 19 common frames omitted
Imine answered 1/12, 2021 at 2:9 Comment(2)
I have this issue with SpringBoot 2.6.1 too (springfox-boot-starter 3.0.0)Plagioclase
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-duplicateKerato
K
61

I know this does not solve your problem directly, but consider moving to springdoc which most recent release supports Spring Boot 2.6.0. Springfox is so buggy at this point that is a pain to use. I've moved to springdoc 2 years ago because of its Spring WebFlux support and I am very happy about it. Additionally, it also supports Kotlin Coroutines, which I am not sure Springfox does.

If you decide to migrate, springdoc even has a migration guide.

Kendallkendell answered 1/12, 2021 at 2:17 Comment(2)
If I could I would have voted up 100 times :) We have made exactly the same decision and we got rid of (almost) all the stupid problems we had with springfox!Semidiurnal
Voted, KIV-ed and following this answer (I dont have a need for springdoc now, as i am using a lower version of Spring Boot, but probably will)Cwmbran
J
69

Only adding @EnableWebMvc in main class resolved the problem:

@EnableWebMvc
@SpringBootApplication
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class);
    }
}
Jardiniere answered 13/1, 2022 at 21:3 Comment(2)
I like solutions that are less than 2 lines of code. Good one.Blowsy
While this solves this current issue, adding this annotation has by-effects. For example, it affects Jackson marshalling in terms of encoding by meHwu
K
61

I know this does not solve your problem directly, but consider moving to springdoc which most recent release supports Spring Boot 2.6.0. Springfox is so buggy at this point that is a pain to use. I've moved to springdoc 2 years ago because of its Spring WebFlux support and I am very happy about it. Additionally, it also supports Kotlin Coroutines, which I am not sure Springfox does.

If you decide to migrate, springdoc even has a migration guide.

Kendallkendell answered 1/12, 2021 at 2:17 Comment(2)
If I could I would have voted up 100 times :) We have made exactly the same decision and we got rid of (almost) all the stupid problems we had with springfox!Semidiurnal
Voted, KIV-ed and following this answer (I dont have a need for springdoc now, as i am using a lower version of Spring Boot, but probably will)Cwmbran
B
30

Up to now, Springfox 3.0.0 only works with Spring 2.6.0-M2 but not with versions above. See the open Springfox issue https://github.com/springfox/springfox/issues/3462. There you will also find some workarounds you may use until the issue is fixed.

E.g. add this Bean to your Swagger configuration:

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

EDIT: The server starts, but no API info is returned:

No operations defined in spec!

What a mess.

EDIT 2: As mentioned by @Héctor, spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER must be added to application.properties as well, and the operations are displayed again. However, I don't know, if setting this property is possible in any cases, as it may interfere with other constraints.

Baroda answered 9/12, 2021 at 6:49 Comment(4)
I found in this URL, the last solution: Add "spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER" to your application.properties. That's AllUralite
@Héctor: Thanks for your input. However, I needed to define the BeanPostProcessor and to add ANT_PATH_MATCHER. Only adding ANT_PATH_MATCHER lead to the same error as stated by @Thirumal.Baroda
Moving back to 2.5.3 worksSabian
Unfortunately this configuration removes the Swagger docs for the Actuator Controller /actuator/health and /actuator/prometueus completely. If you need these controllers in your Springfox JSON doc, use this workaround: github.com/springfox/springfox/issues/… Worked for me with Spring 2.6.6 and Springfox 2.9.2Eternity
A
17

for springfox 3.0.0 and springboot 2.6.1 use this config and add this tag @Configuration @EnableWebMvc

public class SpringFoxConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                .paths(PathSelectors.any())
                .build().apiInfo(getApiInfo());
    }
    
    private ApiInfo getApiInfo() {
        return new ApiInfo(
                "Api Usuarios",
                "prueba global logic",
                "1",
                "TERMS OF SERVICE URL",
                new Contact("Gabriel Hernández","URL","[email protected]"),
                "LICENSE",
                "LICENSE URL",
                Collections.emptyList()
        );
    }
    
    @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);
                }
            }
        };
    }    
}
Alvin answered 17/12, 2021 at 2:2 Comment(1)
Then you can access the Swagger UI on http://localhost:<port>/swagger-ui/index.htmlGangster
W
11

A possible solution is to:

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

2- Add the following bean to your SwaggerConfig class:

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

Credits to hhhhsw

Wolver answered 3/2, 2022 at 19:41 Comment(2)
This helps, thanks a lot. But could you explain a bit what this magic does, please?Dambro
Hey @AndriySlobodyanyk like stated in the post, this is originally from github.com/hhhhsw. I didn't have a chance to explore why it worked with his fix.Wolver
A
4

I faced the same issue in the last project and it seems that Springfox dependency got issue with the spring 2.6.x. I found out what is the issue it's about the Springfox dependency all the spring developers facing the same issue after spring 2.6.X

so all of them give the recommendation to migrate to springdoc. you can find everything here:

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

Allix answered 11/1, 2022 at 11:20 Comment(0)
A
3

Migration Steps:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
  1. Maintain only above dependency.
  2. Remove library inclusions of earlier releases. Specifically remove springfox-swagger2 and springfox-swagger-ui inclusions.
  3. Remove the @EnableSwagger2 annotations
  4. Add the springfox-boot-starter
  5. Springfox 3.x removes dependencies on guava and other 3rd party libraries (not zero dep yet! depends on spring plugin and open api libraries for annotations and models) so if you used guava predicates/functions those will need to transition to java 8 function interfaces
  6. If you are using WebMvc and it's a non-springboot project, but you don’t use the @EnableWebMvc annotation yet, add this annotation.

source: doc_link

Acculturation answered 1/12, 2021 at 2:33 Comment(3)
For the vast majority of people, adding @EnableWebMvc to a Spring Boot app is the wrong thing to do as it will disable Spring Boot's auto-configuration of Spring MVC.Hame
Using SNAPSHOT versions of external dependencies is not a good idea. This makes build unrepeatable in potentially very surprising ways.Swastika
I agree until point number 5. You need to add this property to your application.properties: spring.mvc.pathmatch.matching-strategy=ant_path_matcher You can read about that here: github.com/spring-projects/spring-boot/issues/28874 spring.io/blog/2020/06/30/…Phalange
S
0

I put the dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

And remove:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Here resolved!

Scarabaeus answered 22/1, 2022 at 0:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.