Spring-boot: Unable to use reactive WebClient without spring-boot-starter-reactor-netty

Created on 6 Jul 2017  路  8Comments  路  Source: spring-projects/spring-boot

This is probably more of a documentation issue but when developing a reactive application on Tomcat (and probably others) and you exclude starter-reactor-netty like this

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-reactor-netty</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>            
</dependency>

then WebClient won't work. The class is on the path but creating a new one with return WebClient.create("http://localhost:8080"); will fail:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.reactive.function.client.WebClient]: Factory method 'webClient' threw exception; nested exception is java.lang.NoClassDefFoundError: reactor/ipc/netty/http/client/HttpClient
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:182)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:575)
    ... 43 common frames omitted
Caused by: java.lang.NoClassDefFoundError: reactor/ipc/netty/http/client/HttpClient
    at org.springframework.http.client.reactive.ReactorClientHttpConnector.<init>(ReactorClientHttpConnector.java:47)
    at org.springframework.web.reactive.function.client.DefaultWebClientBuilder.initExchangeFunction(DefaultWebClientBuilder.java:139)
    at org.springframework.web.reactive.function.client.DefaultWebClientBuilder.build(DefaultWebClientBuilder.java:115)
    at org.springframework.web.reactive.function.client.WebClient.create(WebClient.java:173)
    at com.example.demo.NewClass$CustomConfig.webClient(NewClass.java:29)
    at com.example.demo.NewClass$CustomConfig$$EnhancerBySpringCGLIB$$7b5a2896.CGLIB$webClient$0(<generated>)
    at com.example.demo.NewClass$CustomConfig$$EnhancerBySpringCGLIB$$7b5a2896$$FastClassBySpringCGLIB$$783fa80e.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:359)
    at com.example.demo.NewClass$CustomConfig$$EnhancerBySpringCGLIB$$7b5a2896.webClient(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:155)
    ... 44 common frames omitted
Caused by: java.lang.ClassNotFoundException: reactor.ipc.netty.http.client.HttpClient
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
documentation

Most helpful comment

@dancingfrog You can set the web application type to none when creating your SpringApplication.

All 8 comments

Yes, indeed, reactor-netty is still required if you want to use the WebClient.

I'll turn this into a documentation improvement. Is there a particular piece of documentation that you find misleading? Or did you just apply the same reasoning that you'd use with spring-boot-starter-web?

I expected only the runtime plattform to change. I understand what's happening and I'd know how to fix it, but it's annoying and should be part of the docs. Something like: "if you want to use tc or undertow do this, but take care of including Reactor-Netty if you need web client"

This is actually a bigger issue in that if we include the spring-boot-starter-reactor-netty or spring-webflux dependencies in order to use WebClient in our application, then the application itself (@SpringBootApplication) will always start an embedded web server listening on port 8080. There seems to be no exclusion that will prevent this behavior and still allow the application to use WebClient or other reactive web classes. The cause is pretty well documented here: https://www.changchao.me/?p=316

@dancingfrog You can set the web application type to none when creating your SpringApplication.

@wilkinsona Thank you!
@bclozel Thanks for the answer you submitted on stack exchange https://stackoverflow.com/questions/43574234/how-to-prevent-embedded-netty-server-from-starting-with-spring-boot-starter-webf

How to use reactive webclient in an existing Spring Web Application which run on Tomcat ?

I cannot set the web application type to None

@rameshsunkara Please ask questions on stackoverflow or gitter. We prefer to use the issue tracker only for bugs and enhancements.

Please ask questions on stackoverflow

Thanks, I posted in stack overflow, Reactive WebClient Stack Overflow Question

Was this page helpful?
0 / 5 - 0 ratings