BAEL-5182 code for webclient status code handling article (#11373)

* BAEL-5182 code for webclient status code handling article

* BAEL-5182 code for webclient status code handling article

* BAEL-5182 added different exceptions to make seperate examples clearer

Co-authored-by: Liam Garvie <liamgarvie@192.168.1.106>
This commit is contained in:
LiamGve 2021-12-05 14:34:24 +00:00 committed by GitHub
parent 40669cc7c6
commit f879ab8cef
4 changed files with 166 additions and 0 deletions

View File

@ -0,0 +1,54 @@
package com.baeldung.webclient.status;
import com.baeldung.webclient.status.exception.BadRequestException;
import com.baeldung.webclient.status.exception.ServerErrorException;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class WebClientStatusCodeHandler {
public static Mono<String> getResponseBodyUsingExchangeFilterFunction(String uri) {
ExchangeFilterFunction errorResponseFilter = ExchangeFilterFunction
.ofResponseProcessor(WebClientStatusCodeHandler::exchangeFilterResponseProcessor);
return WebClient
.builder()
.filter(errorResponseFilter)
.build()
.post()
.uri(uri)
.retrieve()
.bodyToMono(String.class);
}
public static Mono<String> getResponseBodyUsingOnStatus(String uri) {
return WebClient
.builder()
.build()
.post()
.uri(uri)
.retrieve()
.onStatus(
HttpStatus.INTERNAL_SERVER_ERROR::equals,
response -> response.bodyToMono(String.class).map(ServerErrorException::new))
.onStatus(
HttpStatus.BAD_REQUEST::equals,
response -> response.bodyToMono(String.class).map(BadRequestException::new))
.bodyToMono(String.class);
}
private static Mono<ClientResponse> exchangeFilterResponseProcessor(ClientResponse response) {
HttpStatus status = response.statusCode();
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
return response.bodyToMono(String.class)
.flatMap(body -> Mono.error(new ServerErrorException(body)));
}
if (HttpStatus.BAD_REQUEST.equals(status)) {
return response.bodyToMono(String.class)
.flatMap(body -> Mono.error(new BadRequestException(body)));
}
return Mono.just(response);
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.webclient.status.exception;
public class BadRequestException extends Exception {
public BadRequestException(String message) {
super(message);
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.webclient.status.exception;
public class ServerErrorException extends Exception {
public ServerErrorException(String message) {
super(message);
}
}

View File

@ -0,0 +1,98 @@
package com.baeldung.webclient;
import com.baeldung.webclient.status.WebClientStatusCodeHandler;
import com.github.tomakehurst.wiremock.WireMockServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Mono;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.configureFor;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@RunWith(SpringRunner.class)
public class WebClientStatusCodeHandlerIntegrationTest {
private String baseUrl;
private WireMockServer wireMockServer;
@Before
public void setUp() {
wireMockServer = new WireMockServer(wireMockConfig().dynamicPort());
wireMockServer.start();
configureFor("localhost", wireMockServer.port());
baseUrl = format("http://localhost:%s", wireMockServer.port());
}
@After
public void tearDown() {
wireMockServer.stop();
}
@Test
public void whenResponseIs2XX_thenBothStatusHandlerAndExchangeFilterReturnEqualResponses() {
stubPostResponse("/success", 200, "success");
Mono<String> responseStatusHandler = WebClientStatusCodeHandler
.getResponseBodyUsingOnStatus(baseUrl + "/success");
Mono<String> responseExchangeFilter = WebClientStatusCodeHandler
.getResponseBodyUsingExchangeFilterFunction(baseUrl + "/success");
assertThat(responseStatusHandler.block())
.isEqualTo(responseExchangeFilter.block())
.isEqualTo("success");
}
@Test
public void whenResponseIs500_thenBothStatusHandlerAndExchangeFilterReturnEqualResponses() {
stubPostResponse("/server-error", 500, "Internal Server Error");
Mono<String> responseStatusHandler = WebClientStatusCodeHandler
.getResponseBodyUsingOnStatus(baseUrl + "/server-error");
Mono<String> responseExchangeFilter = WebClientStatusCodeHandler
.getResponseBodyUsingExchangeFilterFunction(baseUrl + "/server-error");
assertThatThrownBy(responseStatusHandler::block)
.isInstanceOf(Exception.class)
.hasMessageContaining("Internal Server Error");
assertThatThrownBy(responseExchangeFilter::block)
.isInstanceOf(Exception.class)
.hasMessageContaining("Internal Server Error");
}
@Test
public void whenResponseIs400_thenBothStatusHandlerAndExchangeFilterReturnEqualResponses() {
stubPostResponse("/client-error", 400, "Bad Request");
Mono<String> responseStatusHandler = WebClientStatusCodeHandler
.getResponseBodyUsingOnStatus(baseUrl + "/client-error");
Mono<String> responseExchangeFilter = WebClientStatusCodeHandler
.getResponseBodyUsingExchangeFilterFunction(baseUrl + "/client-error");
assertThatThrownBy(responseStatusHandler::block)
.isInstanceOf(Exception.class)
.hasMessageContaining("Bad Request");
assertThatThrownBy(responseExchangeFilter::block)
.isInstanceOf(Exception.class)
.hasMessageContaining("Bad Request");
}
private static void stubPostResponse(String url, int statusCode, String response) {
stubFor(post(urlEqualTo(url)).willReturn(aResponse()
.withStatus(statusCode)
.withBody(response)));
}
}