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
spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5432/inventoryservice spring.datasource.username=postgres spring.datasource.password=admin spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect server.port=8082 eureka.client.service-url.default-zone=http://localhost:8761/eureka spring.application.name=inventory-service
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
spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5432/postgres spring.datasource.username=postgres spring.datasource.password=admin spring.jpa.hibernate.ddl-auto=update spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect server.port=8081 eureka.client.service-url.default-zone=http://localhost:8761/eureka spring.application.name=order-service
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
spring.application.name=discovery-service eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false server.port=8761 eureka.client.service-url.default-zone=http://localhost:8761/eureka
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!
Comment From: bclozel
Can you open this issue against https://github.com/spring-cloud/spring-cloud-netflix/issues - this feature is not implemented in Spring Framework.
Thanks!
Comment From: Ivanbattochio
Isn't the Webclient implementation from spring framework repository? Hence the org.springframework:spring-webflux import and the class file.
I believe the error is originating from the spring framework's webclient implementation because performing the get request using the RestTemplate implementation works as expected and i am able to communicate with the eureka client using it's instance name.
I could be missing something here, but as to my knowledge I still believe this is spring framework's issue instead of spring cloud's.
Comment From: bclozel
Yes you are right WebClient is implemented in Spring Framework.
Reading your issue description, it looks like the client cannot resolve the remote endpoint address because the service name was not replaced by the actual host name of the service instance. Isn't this feature implemented in Spring Cloud? We can reopen this issue if you manage to simplify the repro project and reproduce without Spring Cloud being there at all. Please advise.