Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

WebClient at the other hand is based on the Spring Reactive framework which provides capability to non-blocking async calls thanks to it's event-driven architecture. Because of this WebClient uses less resources (threads, memory).


Affected classes

Apart from the *Spec files the RestTemplate is used only in 2 classes: NcmpConfiguration and DmiRestClient.

The first class configures the client while the second performs requests with RestClient.

These two classes have to be rewritten/refactored to use the WebClient.

Example configuration

Code Block
languagejava
titleConfiguration Example
linenumberstrue
collapsetrue
@Slf4j
@Configuration
@AllArgsConstructor
public class WebClientConfiguration {

    public static final int TIMEOUT = 2000;
    private final DmiConfiguration.SdncProperties sdncProperties;

    @Bean
    public WebClient webClient() {
        final var httpClient = HttpClient.create()
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT) // millis
                .doOnConnected(connection ->
                        connection
                                .addHandlerLast(new ReadTimeoutHandler(TIMEOUT, TimeUnit.MILLISECONDS)) // millis
                                .addHandlerLast(new WriteTimeoutHandler(TIMEOUT, TimeUnit.MILLISECONDS))); //millis

        return WebClient.builder()
                .baseUrl(sdncProperties.getBaseUrl())
                .defaultHeaders(header -> header.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
                .defaultHeaders(header -> header.setBasicAuth(sdncProperties.getAuthUsername(), sdncProperties.getAuthPassword()))
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .filter(logRequest())
                .filter(logResponse())
                .build();
    }

    private ExchangeFilterFunction logRequest() {
        return (clientRequest, next) -> {
            log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
            log.info("--- Http Headers: ---");
            clientRequest.headers().forEach(this::logHeader);
            log.info("--- Http Cookies: ---");
            clientRequest.cookies().forEach(this::logHeader);
            return next.exchange(clientRequest);
        };
    }

    private ExchangeFilterFunction logResponse() {
        return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
            log.info("Response: {}", clientResponse.statusCode());
            clientResponse.headers().asHttpHeaders()
                    .forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
            return Mono.just(clientResponse);
        });
    }

    private void logHeader(String name, List values) {
        values.forEach(value -> log.info("{}={}", name, value));
    }
}

...

Code Block
languagejava
firstline1
titleSync Call
linenumberstrue
collapsetrue
String response = webClient
 .get()
 .uri(resourceUrl)
 .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
 .retrieve()
 .onStatus(HttpStatus::is4xxClientError,
 error -> Mono.error(new RuntimeException("API not found")))
 .onStatus(HttpStatus::is5xxServerError,
 error -> Mono.error(new RuntimeException("Server is not responding")))
 .bodyToMono(String.class)
 .block();
return ResponseEntity.ok(response);

...

Async call example with

...

subscription

Code Block
languagejava
titledeclaration
linenumberstrue
collapsetrue
public Mono<String> httpOperationWithJsonData(final HttpMethod httpMethod, 
												final String resourceUrl, 
												final String jsonData,
												final HttpHeaders httpHeaders) {

return webClient
 .get()
 .uri(resourceUrl)
 .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
 .retrieve()
 .onStatus(HttpStatus::is4xxClientError,
 error -> Mono.error(new RuntimeException("API not found")))
 .onStatus(HttpStatus::is5xxServerError,
 error -> Mono.error(new RuntimeException("Server is not responding")))
 .bodyToMono(String.class);
}

...