Does Swagger support Spring Reactive-Web?
I am trying to write a simple crud application with Reactive Web and Reactive Mongo. Everything works fine. But when I add Swagger to my project, Netty doesn't start.
Here is my controller class:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import uz.n0d1r.datas.Point;
import uz.n0d1r.repository.PointRepository;
@RestController(value = "/points")
public class PointController {
private final PointRepository pointRepository;
public PointController(PointRepository pointRepository) {
this.pointRepository = pointRepository;
}
@PostMapping
Mono<Void> create(@RequestBody Point point) {
return pointRepository.save(point).then();
}
@GetMapping
Flux<Point> list() {
return this.pointRepository.findAll();
}
}
Swagger Config:
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class TrackServiceSwaggerConfig {
@Bean
public Docket api() {
ParameterBuilder aParameterBuilder = new ParameterBuilder();
// aParameterBuilder.name("Authorization").modelRef(new ModelRef("string")).parameterType("header").required(true).build();
List<Parameter> header = new ArrayList<Parameter>();
header.add(aParameterBuilder.build());
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(paths())
.build()
.globalOperationParameters(header);
}
// Describe your apis
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Track-Service APIs")
.description("description goes here ")
.contact(new Contact("Nodirbek Sadullayev", "n0d1r.uz", "[email protected]"))
.version("1.0-SNAPSHOT")
.build();
}
// Only select apis that matches the given Predicates.
private Predicate<String> paths() {
// Match all paths except /error
return Predicates.and(
PathSelectors.regex("/.*"),
Predicates.not(PathSelectors.regex("/error.*"))
);
}
}
My dependencies list below:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
Error log:
org.springframework.context.ApplicationContextException: Unable to start reactive web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerConfiguration$ReactorNettyAutoConfiguration': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.onRefresh(ReactiveWebServerApplicationContext.java:59) ~[spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:44) ~[spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:751) [spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:387) [spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1245) [spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1233) [spring-boot-2.0.0.M6.jar:2.0.0.M6]
at uz.n0d1r.TrackServiceApplication.main(TrackServiceApplication.java:10) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerConfiguration$ReactorNettyAutoConfiguration': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:591) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:368) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1249) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1098) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.getWebServerFactory(ReactiveWebServerApplicationContext.java:117) ~[spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.createWebServer(ReactiveWebServerApplicationContext.java:82) ~[spring-boot-2.0.0.M6.jar:2.0.0.M6]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.onRefresh(ReactiveWebServerApplicationContext.java:56) ~[spring-boot-2.0.0.M6.jar:2.0.0.M6]
... 13 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter
at springfox.documentation.spring.web.ObjectMapperConfigurer.postProcessBeforeInitialization(ObjectMapperConfigurer.java:45) ~[springfox-spring-web-2.6.1.jar:2.6.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:423) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1696) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583) ~[spring-beans-5.0.1.RELEASE.jar:5.0.1.RELEASE]
... 30 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_65]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_65]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_65]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_65]
... 34 common frames omitted
Any suggestions ? thanks!
To enable the Swagger2 in Spring Boot application, you need to add the following dependencies in our build configurations file. For Gradle users, add the following dependencies in your build. gradle file. Now, add the @EnableSwagger2 annotation in your main Spring Boot application.
springfox (documentationProvider): Springfox is deprecated for removal in version 7.0. 0 of openapi-generator. The project seems to be no longer maintained (last commit is of Oct 14, 2020). It works with Spring Boot 2.5.
Springfox is a framework that acts as the “glue” between Swagger and Spring. It generates the specification (contract) based on your code and also deploys the Swagger UI client with your application, allowing you to immediately test your REST API.
Swagger 3 will be soon released, and it includes support for netty.
By that time, you can use the snapshot version:
{
repositories {
maven {
url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/'
}
}
dependencies {
compile 'io.springfox:springfox-swagger2:3.0.0-SNAPSHOT'
compile 'io.springfox:springfox-swagger-ui:3.0.0-SNAPSHOT'
compile 'io.springfox:springfox-spring-webflux:3.0.0-SNAPSHOT'
}
}
and you enable it with @EnableSwagger2WebFlux
source: https://github.com/springfox/springfox/issues/1773
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With