Closed Ivanbattochio closed 7 months ago
You need to provide a WebClient.Builder bean and annotate it with @LoadBalanced
or provide load balancer filter function to the web client. See https://spring.io/guides/gs/spring-cloud-loadbalancer
Code from my project:
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.web.reactive.function.client.WebClient;
@Bean
@Primary
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
I think this is a bug, adding @Primary
is just a workaround.
doing so will cause all spring auto configuration to not work as excepted (WebClientAutoConfiguration
)
This was how i solved the issue inside my project without @Primary
, turns out that i was importing spring framework's webflux outside spring boot ecosystem.
I don't know if that indicates that there is or not a bug that needs to be fixed, I only wanted to provide more context about how my issue was solved.
Hi,
If your eureka client will use WebClient
it will fail due to error of:
No qualifying bean of type 'org.springframework.web.reactive.function.client.WebClient$Builder' available: expected single matching bean but found 2: webClientBuilder,loadBalancerWebClient
eureka:
client:
webclient:
enabled: true
Hi, I'd like to know if anyone can help me.
I have a setup of microservices registering to a netflix discovery server, and I'm having problems using webClient to communicate with the servers using their instance names. When trying to request using RestTemplate it works as expected.
The entire project source code is inside this repo!
InventoryResponse[] inventoryResponses = webClient.get() .uri("http://inventory-service/api/inventory", uriBuilder -> uriBuilder.queryParam("skuCode", skuCodes).build()) .retrieve() .bodyToMono(InventoryResponse[].class) .block();
This is how I'm building and sending the request from the order-service to the inventory-service and this is the error stacktrace:
java.nio.channels.UnresolvedAddressException: null at java.base/sun.nio.ch.Net.checkAddress(Net.java:137) ~[na:na] at java.base/sun.nio.ch.Net.checkAddress(Net.java:145) ~[na:na] at java.base/sun.nio.ch.SocketChannelImpl.checkRemote(SocketChannelImpl.java:842) ~[na:na] at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:865) ~[na:na] at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:210) ~[java.net.http:na] at java.base/java.security.AccessController.doPrivileged(AccessController.java:571) ~[na:na] at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:212) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.Http1Exchange.sendHeadersAsync(Http1Exchange.java:312) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.Exchange.lambda$responseAsyncImpl0$8(Exchange.java:567) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.Exchange.checkFor407(Exchange.java:447) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.Exchange.lambda$responseAsyncImpl0$9(Exchange.java:571) ~[java.net.http:na] at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.uniHandleStage(CompletableFuture.java:950) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.handle(CompletableFuture.java:2372) ~[na:na] at java.net.http/jdk.internal.net.http.Exchange.responseAsyncImpl0(Exchange.java:571) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.Exchange.responseAsyncImpl(Exchange.java:423) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.Exchange.responseAsync(Exchange.java:415) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.MultiExchange.responseAsyncImpl(MultiExchange.java:413) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.MultiExchange.lambda$responseAsyncImpl$7(MultiExchange.java:454) ~[java.net.http:na] at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.uniHandleStage(CompletableFuture.java:950) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.handle(CompletableFuture.java:2372) ~[na:na] at java.net.http/jdk.internal.net.http.MultiExchange.responseAsyncImpl(MultiExchange.java:444) ~[java.net.http:na] at java.net.http/jdk.internal.net.http.MultiExchange.lambda$responseAsync0$2(MultiExchange.java:346) ~[java.net.http:na] at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na] at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1773) ~[na:na] at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
This is the inventory-service application.properties
This is the inventory-service build.gradle file
`plugins { id 'java' id 'org.springframework.boot' version '3.2.3' id 'io.spring.dependency-management' version '1.1.4' }
group = 'com.example.microservices' version = '0.0.1-SNAPSHOT'
java { sourceCompatibility = '21' }
ext { set('springCloudVersion', "2023.0.0") }
configurations { compileOnly { extendsFrom annotationProcessor } }
repositories { mavenCentral() }
dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
tasks.named('test') { useJUnitPlatform() } `
This is the order-service application.properties
This is the order service build.gradle
`plugins { id 'java' id 'org.springframework.boot' version '3.2.3' id 'io.spring.dependency-management' version '1.1.4' }
group = 'com.example.springmicroservices' version = '0.0.1-SNAPSHOT'
java { sourceCompatibility = '21' }
ext { set('springCloudVersion', "2023.0.0") }
configurations { compileOnly { extendsFrom annotationProcessor } }
repositories { mavenCentral() }
dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springframework:spring-webflux' implementation 'jakarta.validation:jakarta.validation-api' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.postgresql:postgresql' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
tasks.named('test') { useJUnitPlatform() } ` This is the discovery-service application.properties
This is the discovery-service build.gradle
`plugins { id 'java' id 'org.springframework.boot' version '3.2.3' id 'io.spring.dependency-management' version '1.1.4' }
group = 'com.example.microservices' version = '0.0.1-SNAPSHOT'
java { sourceCompatibility = '21' }
repositories { mavenCentral() }
ext { set('springCloudVersion', "2023.0.0") }
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
tasks.named('test') { useJUnitPlatform() } `
I'm using Java 21 and spring boot 3.2.3.
When debbuging the request i found where the error gets thrown:
I've tried to provide all the information i think anyone would need to replicate the problem, if i let something slip by please let me know so that i can provide more context!
Thanks!