I want to establish a communication between a client and server application using Springs new reactive webflux extension.
For dependency management I use gradle. My build.gradle file on the server, as well as on the client side basically is:
buildscript { repositories { mavenCentral() maven { url "https://repo.spring.io/snapshot" } } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.BUILD-SNAPSHOT") } } repositories { mavenCentral() maven { url "https://repo.spring.io/snapshot" } } apply plugin: 'java' apply plugin: 'org.springframework.boot' apply plugin: "io.spring.dependency-management" dependencies { compile("org.springframework.boot:spring-boot-starter-webflux") }
(It should be noted that 2.0.0.BUILD-SNAPSHOT is a moving target and the problem at hand may just vanish one day due to changes inside the dependency)
When I start the server side application everything starts up well, including the start of an embedded netty server.
But when start the client application also a netty server is started, causing a "java.net.BindException: Address already in use", because the clientside netty server listens on the same port as the serverside netty server.
My question is: Why is netty started on the client side in the first place and how can I prevent it?
According to the Spring-Boot Documentation Spring tries to determine if Web support is required and configures the Spring Application context accordingly.
And according to the Docs this can be overridden by a call to setWebEnvironment(false). My client startup code then looks like:
@SpringBootApplication(scanBasePackages = { "com.tatics.flux.main" }) public class Client { public static void main(String[] args) throws Exception { SpringApplication app = new SpringApplication(Client.class); app.setWebEnvironment(false); app.run(Client.class, args); WebClient webClient = WebClient.create(); Mono<String> result = webClient .post() .uri("http://localhost:8080/fluxService") // This does not work any more: .body("Hallo") // and must be replaced by: .body(BodyInserters.fromObject("Hallo")) .accept(MediaType.TEXT_PLAIN) .exchange() .flatMap(response -> response.bodyToMono(String.class)); } }
Unfortunately netty is still started. Also I note that setWebEnvironment(false) is marked as deprecated.
Any help on how to prevent netty from starting but otherwise preserve all webflux-dependencies is appreciated.
Here is an excerpt from the auto-configuration Report:
========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- ... ReactiveWebServerAutoConfiguration matched: - found ReactiveWebApplicationContext (OnWebApplicationCondition) ReactiveWebServerAutoConfiguration#defaultReactiveWebServerCustomizer matched: - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.reactive.DefaultReactiveWebServerCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) ReactiveWebServerConfiguration.ReactorNettyAutoConfiguration matched: - @ConditionalOnClass found required class 'reactor.ipc.netty.http.server.HttpServer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) - @ConditionalOnMissingBean (types: org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; SearchStrategy: all) did not find any beans (OnBeanCondition) ReactorCoreAutoConfiguration matched: - @ConditionalOnClass found required classes 'reactor.core.publisher.Mono', 'reactor.core.publisher.Flux'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) ... Negative matches: ----------------- ... ReactiveWebServerConfiguration.JettyAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition) ReactiveWebServerConfiguration.TomcatAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition) ReactiveWebServerConfiguration.UndertowAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition) ... ReactiveWebServerConfiguration.JettyAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition) ReactiveWebServerConfiguration.TomcatAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition) ReactiveWebServerConfiguration.UndertowAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)
Spring WebFlux is a part of the Spring framework and provides reactive programming support for web applications. If we're using WebFlux in a Spring Boot application, Spring Boot automatically configures Reactor Netty as the default server.
The default Embedded Web Servers in Spring-Boot is Tomcat , but you can easily change it to others.
Addition to @Brian_Clozel answer:
You can disable Netty (or any other server) by specifying inside an application.yml:
spring.main.web-application-type: none
or application.properties:
spring.main.web-application-type=none
The main issue with your code is that you're currently creating a SpringApplication
, then you customize it - to finally drop everything and run the static method run(Object primarySource, String... args)
.
The following should work:
@SpringBootApplication public class Client { public static void main(String[] args) throws Exception { SpringApplication app = new SpringApplication(Client.class); app.setWebApplicationType(WebApplicationType.NONE); app.run(args); } @Bean public CommandLineRunner myCommandLineRunner() { return args -> { // we have to block here, since command line runners don't // consume reactive types and simply return after the execution String result = WebClient.create("http://localhost:8080") .post() .uri("/fluxService") .body("Hallo") .accept(MediaType.TEXT_PLAIN) .retrieve() .bodyToMono(String.class) .block(); // print the result? }; } }
If not, please run your application using the --debug
flag and add to your question the relevant parts of the auto-configuration report, especially the auto-configurations dealing with servers.
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