Issue
So I have a old working application which uses Spring MVC and not spring boot. I have added gradle dependency of spring-webflux in my project and start using webclient for calling external APIs from my project. This is my webclient handler class:
@Service
public class WebclientHandler {
private final WebClient webClient;
public WebclientHandler (WebClient.Builder builder) {
this.webClient = builder.baseUrl("baseurl").build();
}
}
Now I am getting this error after when I call this code through my API:
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.web.reactive.function.client.WebClient$Builder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
It seems like my application is not able to find Webclient.builder and constructor injection does not occur. Is this because I am not using spring boot?
This is my Gradle dependency:
compile(group: 'org.springframework', name: 'spring-webflux', version: '5.3.15')
I am new to spring-webflux reactive programming.
EDIT
I have tried to create Webclient bean using configuration also:
@Configuration
public class WebClientHandler {
@Bean
public WebClient myWebClient() {
WebClient client = WebClient.builder().baseUrl("baseUrl")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build();
return client;
}
}
Now I am getting this exception on startup:
{ java.lang.IllegalStateException: No suitable default ClientHttpConnector found
at org.springframework.web.reactive.function.client.DefaultWebClientBuilder.initConnector(DefaultWebClientBuilder.java:297)
at org.springframework.web.reactive.function.client.DefaultWebClientBuilder.build(DefaultWebClientBuilder.java:266)
at com.kronos.orgmap.sbs.impl.service.WebClientHandler.MyWebClient(WebClientHandler.java:41)
at com.kronos.orgmap.sbs.impl.service.WebClientHandler$$EnhancerBySpringCGLIB$$59a9a582.CGLIB$desiWebClient$0(<generated>)
at com.kronos.orgmap.sbs.impl.service.WebClientHandler$$EnhancerBySpringCGLIB$$59a9a582$$FastClassBySpringCGLIB$$76fa510d.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at com.kronos.orgmap.sbs.impl.service.WebClientHandler$$EnhancerBySpringCGLIB$$59a9a582.MyWebClient(<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:154)
at org.springframework.beans.factory.support.KronosConstructorResolver.instantiate(KronosConstructorResolver.java:654)
at org.springframework.beans.factory.support.KronosConstructorResolver.instantiateUsingFactoryMethod(KronosConstructorResolver.java:487)
at org.springframework.beans.factory.support.KronosAbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(KronosAbstractAutowireCapableBeanFactory.java:1345)
at org.springframework.beans.factory.support.KronosAbstractAutowireCapableBeanFactory.createBeanInstance(KronosAbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.KronosAbstractAutowireCapableBeanFactory.doCreateBean(KronosAbstractAutowireCapableBeanFactory.java:611)
at org.springframework.beans.factory.support.KronosAbstractAutowireCapableBeanFactory.createBean(KronosAbstractAutowireCapableBeanFactory.java:559)
at org.springframework.beans.factory.support.KronosAbstractBeanFactory.lambda$doGetBean$0(KronosAbstractBeanFactory.java:336)
at org.springframework.beans.factory.support.KronosDefaultSingletonBeanRegistry.getSingleton(KronosDefaultSingletonBeanRegistry.java:235)
at org.springframework.beans.factory.support.KronosAbstractBeanFactory.doGetBean(KronosAbstractBeanFactory.java:334)
at org.springframework.beans.factory.support.KronosAbstractBeanFactory.getBean(KronosAbstractBeanFactory.java:209)
at org.springframework.beans.factory.support.KronosDefaultListableBeanFactory.preInstantiateSingletons(KronosDefaultListableBeanFactory.java:952)
at com.kronos.container.impl.startup.KronosBeanFactory.preInstantiateSingletons(KronosBeanFactory.java:226)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4699)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1125)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1859)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
} }
Solution
Adding these dependencies in my gradle resolved the issue for me for 2nd approach, Now the DefaultWebClientBuilder is able to initiate connector to be used by webclient builder.
implementation platform('io.projectreactor:reactor-bom:2020.0.17')
implementation 'io.projectreactor.netty:reactor-netty-core'
implementation 'io.projectreactor.netty:reactor-netty-http'
Although still didn't figured out why the first approach not working even after adding the mentioned gradle dependencies. Still not able to find WebClient.Builder class as bean in constructor.
Answered By - Abhishek Wadhwa
Answer Checked By - Robin (JavaFixing Admin)