Skip to content

Spring Boot 2.6.0: Fixing Springfox 'documentationPluginsBootstrapper' Startup Failure

Problem Statement

When upgrading to Spring Boot 2.6.0 with Springfox 3, applications may fail to start with the error:

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

This occurs due to a compatibility issue between Springfox and Spring Boot's new default path matching strategy introduced in version 2.6.0.

Root Cause

Spring Boot 2.6.0 changed the default path matching strategy from Ant-based (AntPathMatcher) to PathPattern-based parsing. Springfox 3.0.0 makes assumptions about Spring MVC's configuration that are no longer valid with this change, causing the NullPointerException during startup.

Solutions

Solution 1: Switch Back to Ant Path Matcher (Simple Applications)

For applications not using Spring Boot Actuator, the simplest fix is to revert to the previous path matching strategy:

properties
# application.properties
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

Solution 2: Complete Configuration for Actuator Compatibility

For applications using Spring Boot Actuator, a more comprehensive solution is required:

  1. Add the path matching configuration:
properties
# application.properties
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
  1. Create a configuration class:
java
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 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 SpringFoxConfig {

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

Solution 3: Alternative Bean Configuration

Another approach that works well with JDK 17 and Spring Boot 2.6+:

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

Solution 4: Downgrade Spring Boot (Temporary Fix)

If immediate compatibility is needed, consider downgrading to Spring Boot 2.5.x:

gradle
// build.gradle
plugins {
    id 'org.springframework.boot' version '2.5.6'
    // other plugins
}

WARNING

This should be considered a temporary solution. Spring Boot 2.5.x reached end-of-life in November 2022.

Consider migrating from Springfox to Springdoc OpenAPI, which is better maintained and fully compatible with Spring Boot 2.6+:

gradle
// build.gradle
implementation "org.springdoc:springdoc-openapi-ui:1.6.4"
java
@SpringBootApplication
@OpenAPIDefinition
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Access Swagger UI at: http://localhost:8080/swagger-ui/index.html

Configuration Examples

Gradle Dependencies for Springfox

gradle
dependencies {
    implementation "io.springfox:springfox-boot-starter:3.0.0"
    implementation "org.springframework.boot:spring-boot-starter-web"
    implementation "org.springframework.boot:spring-boot-starter-webflux"
    // other dependencies
}

Complete Springfox Configuration

java
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    
    @Bean
    public Docket apiDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo());
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("API Documentation")
                .description("API description")
                .version("1.0.0")
                .build();
    }
}

Best Practices and Recommendations

  1. Prefer Springdoc over Springfox: Springdoc OpenAPI is actively maintained and has better Spring Boot 2.6+ compatibility
  2. Test thoroughly: After applying any fix, test all API endpoints and Swagger UI functionality
  3. Consider future upgrades: The PathPattern-based matcher offers performance improvements, so consider adapting rather than reverting

INFO

Spring Boot's Actuator endpoints always use PathPattern-based parsing regardless of the matching-strategy configuration, which is why additional configuration is needed for Springfox compatibility.

Troubleshooting

If you continue to experience issues:

  1. Check that all Springfox-related beans are properly configured
  2. Verify that no conflicting web server configurations exist
  3. Ensure consistent versioning across all Spring Boot and Springfox dependencies
  4. Review application logs for additional error messages that might provide more context

By implementing one of these solutions, you should be able to resolve the documentationPluginsBootstrapper startup failure and successfully use Springfox with Spring Boot 2.6.0 and later versions.