Only adding @EnableWebMvc
in main class resolved the problem:
@EnableWebMvc @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class); } }
ID : 131322
viewed : 7
Tags : javaspring-bootswaggerspringfoxspring-boot-2.6.0java
97
Only adding @EnableWebMvc
in main class resolved the problem:
@EnableWebMvc @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class); } }
83
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.
70
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.
65
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","gabriel.hernandez.u@gmail.com"), "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); } } }; } }
53
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