RestController throws 503 Service Unavailable, if the remote-server fails
authorKai Moritz <kai@juplo.de>
Tue, 14 Jan 2020 23:58:26 +0000 (00:58 +0100)
committerKai Moritz <kai@juplo.de>
Thu, 16 Jan 2020 10:18:03 +0000 (11:18 +0100)
* Added unit-test RestControllerTest.testResponseOtherErrors()
* Fixed the behavior of the RestController accordingly

src/main/java/de/juplo/demo/RestController.java
src/test/java/de/juplo/demo/RestControllerTest.java

index 288fd9e..f7f63a6 100644 (file)
@@ -4,6 +4,8 @@ package de.juplo.demo;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+import org.springframework.web.reactive.function.client.WebClientResponseException.NotFound;
 import reactor.core.publisher.Mono;
 
 
@@ -26,6 +28,22 @@ public class RestController
   @GetMapping(path = { "", "/" }, produces = MediaType.TEXT_PLAIN_VALUE)
   public Mono<String> fetch(@RequestParam String path)
   {
-    return service.getRemoteText(path);
+    return
+        service
+            .getRemoteText(path)
+            .onErrorResume(t ->
+            {
+              if(t.getClass().equals(NotFound.class))
+                return Mono.error(t);
+
+              return
+                  Mono.error(
+                      WebClientResponseException.create(
+                          503,
+                          "Service Unavailable - Cause: " + t.getMessage(),
+                          null,
+                          null,
+                          null));
+            });
   }
 }
index dae8929..4b4526a 100644 (file)
@@ -1,13 +1,18 @@
 package de.juplo.demo;
 
 
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
 import org.mockito.Mockito;
 import static org.mockito.Mockito.when;
+import org.springframework.http.HttpStatus;
 import org.springframework.web.reactive.function.client.WebClientResponseException;
 import org.springframework.web.reactive.function.client.WebClientResponseException.NotFound;
+import org.springframework.web.reactive.function.client.WebClientResponseException.ServiceUnavailable;
 import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
 
@@ -59,6 +64,50 @@ public class RestControllerTest
         .verify();
   }
 
+  /**
+   * Only the behavior on the common errors, as defined in {@link
+   * WebClientResponseException#create(int, String, org.springframework.http.HttpHeaders, byte[], java.nio.charset.Charset, org.springframework.http.HttpRequest)
+   * WebClientResponseException.create()} is tested.
+   */
+  @DisplayName("Other error while fetching data from remote-server")
+  @ParameterizedTest(name = "{arguments} ==> HTTP-status={0}")
+  @EnumSource(value = HttpStatus.class, names = {
+    "BAD_REQUEST",
+    "UNAUTHORIZED",
+    "FORBIDDEN",
+    "METHOD_NOT_ALLOWED",
+    "NOT_ACCEPTABLE",
+    "CONFLICT",
+    "GONE",
+    "UNSUPPORTED_MEDIA_TYPE",
+    "TOO_MANY_REQUESTS",
+    "UNPROCESSABLE_ENTITY",
+    "INTERNAL_SERVER_ERROR",
+    "NOT_IMPLEMENTED",
+    "BAD_GATEWAY",
+    "SERVICE_UNAVAILABLE",
+    "GATEWAY_TIMEOUT"
+  })
+  void testResponseOtherErrors(HttpStatus status)
+  {
+    Mono<String> mono = Mono.error(exception(status.value()));
+    when(service.getRemoteText("foo")).thenReturn(mono);
+
+    Mono<String> result = controller.fetch("foo");
+
+    StepVerifier
+        .create(result)
+        .expectErrorSatisfies((t) ->
+        {
+          assertThat(t).isInstanceOf(ServiceUnavailable.class);
+          assertThat(t.getMessage())
+              .startsWith(
+                  "503 Service Unavailable - Cause: " +
+                  Integer.toString(status.value()));
+        })
+        .verify();
+  }
+
 
   WebClientResponseException exception(int status)
   {