Versions Compared

Key

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

...

Jira
serverONAP Jira
columnIdsissuekey,summary,issuetype,created,updated,duedate,assignee,reporter,priority,status,resolution
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-989

Medium article

Issues & Decisions

#IssueNotes Decision
1


Overview

As specified in the Jira ticket the replacement of RestTemplate became neccessary due the fact that it is not under development anymore and also because it does not support basic function required in the modern dev world such as async calls.

...

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);
}

...