Thirumal
Springfox 3.0.0 no funciona con Spring Boot 2.6.0, después de actualizar recibo el siguiente 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
ℛɑƒaeĿᴿᴹᴿ
solo agregando @EnableWebMvc
en la clase principal resolvió el problema:
@EnableWebMvc
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class);
}
}
-
Me gustan las soluciones que tienen menos de 2 líneas de código. bueno
– coretechie
12 de agosto de 2022 a las 9:04
Sé que esto no resuelve su problema directamente, pero considere mudarse a springdoc cual lanzamiento más reciente es compatible con Spring Boot 2.6.0. Springfox tiene tantos errores en este punto que es un dolor de usar. me he mudado a springdoc
Hace 2 años debido a su soporte Spring WebFlux y estoy muy feliz por eso. Además, también es compatible con Kotlin Coroutines, que no estoy seguro de que Springfox lo haga.
Si decide migrar, springdoc
incluso tiene un guía de migración.
-
Si pudiera, habría votado a favor 100 veces 🙂 ¡Tomamos exactamente la misma decisión y nos deshicimos de (casi) todos los estúpidos problemas que tuvimos con Springfox!
– Honza Zidek
3 de febrero de 2022 a las 22:54
-
Votado, KIV-ed y siguiendo esta respuesta (no necesito springdoc ahora, ya que estoy usando una versión inferior de Spring Boot, pero probablemente lo haré)
– mono_saltando
9 de febrero de 2022 a las 6:14
pedro keller
Hasta ahora, Springfox 3.0.0 solo funciona con Spring 2.6.0-M2 pero no con las versiones anteriores. Ver el número abierto de Springfox https://github.com/springfox/springfox/issues/3462. Allí también encontrará algunas soluciones alternativas que puede usar hasta que se solucione el problema.
Por ejemplo, agregue esto Bean
a su configuración de Swagger:
@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);
}
}
};
}
EDITAR: El servidor se inicia, pero no se devuelve información de la API:
¡No hay operaciones definidas en las especificaciones!
Que desastre.
EDITAR 2: Como lo menciona @Héctor, spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
debe agregarse a application.properties
también, y las operaciones se muestran de nuevo. Sin embargo, no sé si establecer esta propiedad es posible en cualquier caso, ya que puede interferir con otras restricciones.
-
Encontré en esta URL, la última solución: agregue “spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER” a su aplicación.propiedades. Eso es todo
– Héctor
15 de diciembre de 2021 a las 14:32
-
@Héctor: Gracias por tu aporte. Sin embargo, necesitaba definir el
BeanPostProcessor
y para agregarANT_PATH_MATCHER
. solo agregandoANT_PATH_MATCHER
conducir al mismo error que lo declarado por @Thirumal.– Peter Keller
20 de diciembre de 2021 a las 7:01
-
Volver a 2.5.3 funciona
– dgupta3091
4 de febrero de 2022 a las 9:24
-
Desafortunadamente, esta configuración elimina los documentos de Swagger para Actuator Controller /actuator/health y /actuator/prometueus por completo. Si necesita estos controladores en su documento Springfox JSON, use esta solución alternativa: github.com/springfox/springfox/issues/… Trabajó para mí con Spring 2.6.6 y Springfox 2.9.2
– electrobabe
19 de abril de 2022 a las 10:34
gabriel hernandez
para springfox 3.0.0 y springboot 2.6.1 use esta configuración y agregue esta etiqueta @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);
}
}
};
}
}
huguinho27
Una posible solución es:
1- Configuración spring.mvc.pathmatch.matching-strategy: ant_path_matcher
en application.properties
2- Agregue el siguiente bean a su clase SwaggerConfig:
@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));
}
Créditos para hhhhsw
-
Esto ayuda, muchas gracias. Pero, ¿podría explicar un poco qué hace esta magia, por favor?
–Andriy Slobodyanyk
25 de julio de 2022 a las 16:10
-
Hola @AndriySlobodyanyk como se indica en la publicación, esto es originalmente de github.com/hhhhsw. No tuve la oportunidad de explorar por qué funcionó con su solución.
– huguinho27
26 de julio de 2022 a las 12:20
Mohamad J. Alanbaki
Enfrenté el mismo problema en el último proyecto y parece que la dependencia de Springfox tuvo un problema con Spring 2.6.x. Descubrí cuál es el problema: se trata de la dependencia de Springfox. Todos los desarrolladores de Spring enfrentan el mismo problema después de Spring 2.6.X.
por lo que todos dan la recomendación de migrar a springdoc. Puedes encontrar todo aquí:
-
Esto ayuda, muchas gracias. Pero, ¿podría explicar un poco qué hace esta magia, por favor?
–Andriy Slobodyanyk
25 de julio de 2022 a las 16:10
-
Hola @AndriySlobodyanyk como se indica en la publicación, esto es originalmente de github.com/hhhhsw. No tuve la oportunidad de explorar por qué funcionó con su solución.
– huguinho27
26 de julio de 2022 a las 12:20
Pasos de migración:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
- Mantener sólo por encima de la dependencia.
- Eliminar las inclusiones de biblioteca de versiones anteriores. Elimine específicamente las inclusiones springfox-swagger2 y springfox-swagger-ui.
- Eliminar las anotaciones @EnableSwagger2
- Agregue el iniciador de arranque springfox
- Springfox 3.x elimina las dependencias de guayaba y otras bibliotecas de terceros (¡todavía no hay una dependencia cero! Depende del complemento Spring y bibliotecas API abiertas para anotaciones y modelos), por lo que si usó predicados/funciones de guayaba, necesitarán hacer la transición a las interfaces de funciones de Java 8
- Si está usando WebMvc y es un proyecto que no es springboot, pero aún no usa la anotación @EnableWebMvc, agregue esta anotación.
fuente: doc_link
-
Para la gran mayoría de las personas, agregar
@EnableWebMvc
a una aplicación Spring Boot es lo incorrecto, ya que deshabilitará la configuración automática de Spring MVC de Spring Boot.–Andy Wilkinson
1 de diciembre de 2021 a las 11:32
-
Usar versiones SNAPSHOT de dependencias externas no es una buena idea. Esto hace que la compilación sea irrepetible de maneras potencialmente muy sorprendentes.
– Henning
4 de diciembre de 2021 a las 20:24
-
Estoy de acuerdo hasta el punto número 5. Debe agregar esta propiedad a su aplicación.propiedades: spring.mvc.pathmatch.matching-strategy=ant_path_matcher Puede leer sobre eso aquí: github.com/spring-projects/spring-boot/issues/28874 spring.io/blog/2020/06/30/…
– Tomás Pinto
2 de junio de 2022 a las 14:29
También tengo este problema con SpringBoot 2.6.1 (springfox-boot-starter 3.0.0)
– Nicolás
9 dic 2021 a las 17:12
Solo agregue @EnableWebMvc en la clase principal resolvió el problema. stackoverflow.com/a/70703081/5626568
– ℛɑƒæĿᴿᴹᴿ
16 de marzo de 2022 a las 11:01