3

I am trying to create a Spring WebClient to call REST API. For that, I wrote the following piece of code.

@Bean
public WebClient defaultWebClient() {

    var tcpClient = TcpClient.create()
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3_000)
            .doOnConnected(connection ->
                    connection.addHandlerLast(new ReadTimeoutHandler(3))
                            .addHandlerLast(new WriteTimeoutHandler(3)));

    return WebClient.builder()
            .baseUrl("https://test.com")
            .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
            .defaultHeader(HttpHeaders.ACCEPT, "application/vnd.api+json")
            .build();
}

then the actual URI with the following code.

String user = webClient.get()
                       .uri(URI.create("/api/v1/user/1"))
                       .header("Authorization", TOKEN)
                       .header(HttpHeaders.ACCEPT, "application/json")
                       .retrieve()
                       .bodyToMono(String.class)
                       .block();

but when the above code executed then it throws the following exception.

{"timestamp":"1608209276546","level":"ERROR","thread":"http-nio-8080-exec-1","mdc":{"tenantId":null},"logger":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]","message":"Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientRequestException: Connection refused: no further information: /127.0.0.1:12012; nested exception is io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /127.0.0.1:12012] with root cause","context":"default","exception":"java.net.ConnectException: Connection refused: no further information\r\n\tat java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)\r\n\tat

as raw too:

{"timestamp":"1608209276546","level":"ERROR","thread":"http-nio-8080-exec-1","mdc":{"tenantId":null},"logger":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]","message":"Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientRequestException: Connection refused: no further information: /127.0.0.1:12012; nested exception is io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /127.0.0.1:12012] with root cause","context":"default","exception":"java.net.ConnectException: Connection refused: no further information\r\n\tat java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)\r\n\tat

I am not sure where I need to change here so that it starts pointing to base URI instead of localhost (127.0.0.1:12012). Another thing is if I pass the fully qualified name (https://test.com/api/v1/user/1) on API call then it works fine.

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
keepmoving
  • 1,813
  • 8
  • 34
  • 74

3 Answers3

2

From Javadoc, method uri(URI uri)

Specify the URI using an absolute, fully constructed URI

so this version of method does not use base url from configuration.

Instead, you should have specified URI using UriBuilder, which is injected into method uri(Function<UriBuilder,URI> uriFunction).

String user = webClient.get()
                       .uri(uriBuilder -> uriBuilder.path("/api/v1/user/1").build())
                       ...
Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
sawim
  • 1,032
  • 8
  • 18
0

There are two methods in WebClient.UriSpec that could help.

interface UriSpec<S extends RequestHeadersSpec<?>> {

    S uri(String uri, Object... uriVariables);

    S uri(String uri, Map<String, ?> uriVariables);

    ...
}

In the simplest case just pass String instead of URI as the argument.

String user = webClient
                .get()
                .uri("/api/v1/user/1")        // <- just String
                .retrieve()
                .bodyToMono(String.class)
                .block();
diziaq
  • 6,881
  • 16
  • 54
  • 96
0

You're using TcpClient, in my version I used HttpClient and had to specify the baseUrl parameter on that as well. i.e.

HttpClient httpClient = HttpClient
                        .create()
                        .baseUrl(getRootUrl())
                        .responseTimeout(Duration.ofMillis(<timeout in millis>));

return WebClient
                        .builder()
                        .baseUrl(getRootUrl())
                        .clientConnector(new ReactorClientHttpConnector(httpClient))
                        .defaultHeaders(headers -> {
                            if (!headers.containsKey(HttpHeaders.CONTENT_TYPE)) {
                                headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM.toString());
                            }

                            headers.add("Authorization", "Bearer " + accessKey);
                        })
                        .build();

Hope that helps.

M Sn
  • 31
  • 5