From 41ac51d6c7ec3c93df181065387c2f4ae0f116ac Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Wed, 29 May 2024 22:10:01 -0400 Subject: [PATCH 01/12] Add new KiwiResponses#onXxx methods that accept Supplier This commit is a straw-man to get some feedback: there are no tests or javadocs. --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index f9596163..755b7884 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -2,6 +2,7 @@ import static java.util.Objects.nonNull; import static org.kiwiproject.base.KiwiPreconditions.checkArgumentNotNull; +import static org.kiwiproject.base.KiwiPreconditions.checkOnlyOneArgumentIsNull; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; @@ -12,6 +13,7 @@ import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; /** * Static utilities related to evaluating and acting upon Jakarta REST responses. For example, this class contains @@ -304,6 +306,20 @@ public static boolean hasFamily(Response response, Family family) { return response.getStatusInfo().getFamily() == family; } + public static void onSuccessOrFailure(Supplier responseSupplier, + Consumer successConsumer, + Consumer failedConsumer, + Consumer exceptionConsumer) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + onSuccessOrFailure(result.response(), successConsumer, failedConsumer); + } else { + exceptionConsumer.accept(result.error()); + } + } + /** * Given a {@link Response}, perform an action depending on whether it was successful ({@code successConsumer}) * or failed ({@code failedConsumer}). @@ -332,6 +348,19 @@ public static void onSuccessOrFailure(Response response, } } + public static void onSuccessOrFailureThrow(Supplier responseSupplier, + Consumer successConsumer, + Function throwingFun) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + onSuccessOrFailureThrow(responseSupplier.get(), successConsumer, throwingFun); + } else { + throw result.error(); + } + } + /** * Given a {@link Response}, perform an action if it was successful ({@code successConsumer} or throw an * exception supplied by {@code throwingFun}. @@ -361,6 +390,16 @@ public static void onSuccessOrFailureThrow(Response response, } } + public static void onSuccess(Supplier response, + Consumer successConsumer) { + + var result = getResponse(response); + + if (result.hasResponse()) { + onSuccess(result.response(), successConsumer); + } + } + /** * Given a {@link Response}, perform an action only if it was successful ({@code successConsumer}. No action * is performed for an unsuccessful response. @@ -374,6 +413,18 @@ public static void onSuccess(Response response, Consumer successConsum onSuccessOrFailure(response, successConsumer, NO_OP_RESPONSE_CONSUMER); } + public static Optional onSuccessWithResult(Supplier responseSupplier, + Function successFun) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + return onSuccessWithResult(result.response(), successFun); + } + + return Optional.empty(); + } + /** * Given a {@link Response}, perform an action that returns a result only if it was successful ({@code successFun}). * No action is performer for an unsuccessful response. @@ -389,6 +440,19 @@ public static Optional onSuccessWithResult(Response response, Function responseSupplier, + Consumer failedConsumer, + Consumer exceptionConsumer) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + onFailure(result.response(), failedConsumer); + } else { + exceptionConsumer.accept(result.error()); + } + } + /** * Given a {@link Response}, perform an action only if it was not successful ({@code failedConsumer}). * No action is performed for a successful response. @@ -402,6 +466,18 @@ public static void onFailure(Response response, Consumer failedConsume onSuccessOrFailure(response, NO_OP_RESPONSE_CONSUMER, failedConsumer); } + public static void onFailureThrow(Supplier responseSupplier, + Function throwingFun) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + onFailureThrow(result.response(), throwingFun); + } else { + throw result.error(); + } + } + /** * Given a {@link Response}, throw a (subclass of) {@link RuntimeException} for failed responses using * {@code throwingFun}. No action is performed for a successful response. @@ -426,6 +502,22 @@ public static void onFailureThrow(Response response, } } + public static Optional onSuccessWithResultOrFailure(Supplier responseSupplier, + Function successFun, + Consumer failedConsumer, + Consumer exceptionConsumer) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + return onSuccessWithResultOrFailure(result.response(), successFun, failedConsumer); + } else { + exceptionConsumer.accept(result.error()); + } + + return Optional.empty(); + } + /** * Given a {@link Response}, perform an action that returns a result if the response was * successful ({@code successFun}) or perform an action if the response was unsuccessful ({@code failedConsumer}. @@ -459,6 +551,20 @@ public static Optional onSuccessWithResultOrFailure(Response response, return Optional.ofNullable(result); } + public static T onSuccessOrFailureWithResult(Supplier responseSupplier, + Function successFun, + Function failedFun, + Function exceptionFun) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + return onSuccessOrFailureWithResult(result.response(), successFun, failedFun); + } + + return exceptionFun.apply(result.error()); + } + /** * Given a {@link Response}, perform an action that returns a result if the response was * successful ({@code successFun}) or if not successful ({@code failedFun}). @@ -485,6 +591,43 @@ public static T onSuccessOrFailureWithResult(Response response, } } + public static T onSuccessWithResultOrFailureThrow(Supplier responseSupplier, + Function successFun, + Function throwingFun) { + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + return onSuccessWithResultOrFailureThrow(result.response(), successFun, throwingFun); + } + + throw result.error(); + } + + private record WebCallResult(RuntimeException error, Response response) { + + // This is really an "either" type...which sadly, Java does not have. + + WebCallResult { + checkOnlyOneArgumentIsNull(error, response, + "Either the Response or the RuntimeException can be null, but not both"); + } + + boolean hasResponse() { + return nonNull(response); + } + } + + private static WebCallResult getResponse(Supplier responseSupplier) { + try { + var response = responseSupplier.get(); + return new WebCallResult(null, response); + } catch (RuntimeException e) { + LOG.trace("Response Supplier threw an exception", e); + return new WebCallResult(e, null); + } + } + /** * Given a {@link Response}, perform an action that returns a result if it was successful ({@code successFun} * or throw a (subclass of ) {@link RuntimeException} if it failed ({@code throwingFun}). From 7bbf9e6a079300287687d96d9015e61178133c9c Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Thu, 30 May 2024 19:17:22 +0000 Subject: [PATCH 02/12] Add shell of javadocs (auto-generated but no contents) --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 755b7884..c31b26df 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -306,6 +306,14 @@ public static boolean hasFamily(Response response, Family family) { return response.getStatusInfo().getFamily() == family; } + /** + * TODO + * + * @param responseSupplier + * @param successConsumer + * @param failedConsumer + * @param exceptionConsumer + */ public static void onSuccessOrFailure(Supplier responseSupplier, Consumer successConsumer, Consumer failedConsumer, @@ -348,6 +356,13 @@ public static void onSuccessOrFailure(Response response, } } + /** + * TODO + * + * @param responseSupplier + * @param successConsumer + * @param throwingFun + */ public static void onSuccessOrFailureThrow(Supplier responseSupplier, Consumer successConsumer, Function throwingFun) { @@ -390,6 +405,12 @@ public static void onSuccessOrFailureThrow(Response response, } } + /** + * TODO + * + * @param response + * @param successConsumer + */ public static void onSuccess(Supplier response, Consumer successConsumer) { @@ -413,6 +434,14 @@ public static void onSuccess(Response response, Consumer successConsum onSuccessOrFailure(response, successConsumer, NO_OP_RESPONSE_CONSUMER); } + /** + * TODO + * + * @param + * @param responseSupplier + * @param successFun + * @return + */ public static Optional onSuccessWithResult(Supplier responseSupplier, Function successFun) { @@ -440,6 +469,13 @@ public static Optional onSuccessWithResult(Response response, Function responseSupplier, Consumer failedConsumer, Consumer exceptionConsumer) { @@ -466,6 +502,12 @@ public static void onFailure(Response response, Consumer failedConsume onSuccessOrFailure(response, NO_OP_RESPONSE_CONSUMER, failedConsumer); } + /** + * TODO + * + * @param responseSupplier + * @param throwingFun + */ public static void onFailureThrow(Supplier responseSupplier, Function throwingFun) { @@ -502,6 +544,16 @@ public static void onFailureThrow(Response response, } } + /** + * TODO + * + * @param + * @param responseSupplier + * @param successFun + * @param failedConsumer + * @param exceptionConsumer + * @return + */ public static Optional onSuccessWithResultOrFailure(Supplier responseSupplier, Function successFun, Consumer failedConsumer, @@ -551,6 +603,16 @@ public static Optional onSuccessWithResultOrFailure(Response response, return Optional.ofNullable(result); } + /** + * TODO + * + * @param + * @param responseSupplier + * @param successFun + * @param failedFun + * @param exceptionFun + * @return + */ public static T onSuccessOrFailureWithResult(Supplier responseSupplier, Function successFun, Function failedFun, @@ -591,6 +653,15 @@ public static T onSuccessOrFailureWithResult(Response response, } } + /** + * TODO + * + * @param + * @param responseSupplier + * @param successFun + * @param throwingFun + * @return + */ public static T onSuccessWithResultOrFailureThrow(Supplier responseSupplier, Function successFun, Function throwingFun) { From 50265b43a7fce8d7bf1e8b7ac9c3b7cc478c0aa6 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Thu, 30 May 2024 20:33:42 +0000 Subject: [PATCH 03/12] Add tests and TODOs on each new javadoc --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 4 +- .../kiwiproject/jaxrs/KiwiResponsesTest.java | 363 +++++++++++++++++- 2 files changed, 365 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index c31b26df..4ff89e07 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -4,6 +4,7 @@ import static org.kiwiproject.base.KiwiPreconditions.checkArgumentNotNull; import static org.kiwiproject.base.KiwiPreconditions.checkOnlyOneArgumentIsNull; +import com.google.common.annotations.VisibleForTesting; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status.Family; @@ -675,7 +676,8 @@ public static T onSuccessWithResultOrFailureThrow(Supplier respons throw result.error(); } - private record WebCallResult(RuntimeException error, Response response) { + @VisibleForTesting + record WebCallResult(RuntimeException error, Response response) { // This is really an "either" type...which sadly, Java does not have. diff --git a/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java b/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java index bb5ecf91..7e4ebd72 100644 --- a/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java +++ b/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java @@ -10,6 +10,7 @@ import static jakarta.ws.rs.core.MediaType.WILDCARD_TYPE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.catchThrowable; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -27,11 +28,13 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.kiwiproject.jaxrs.KiwiResponses.WebCallResult; import java.util.Arrays; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.stream.IntStream; @ExtendWith(SoftAssertionsExtension.class) @@ -39,11 +42,13 @@ class KiwiResponsesTest { private AtomicInteger successCount; private AtomicInteger failureCount; + private AtomicInteger exceptionCount; @BeforeEach void setUp() { successCount = new AtomicInteger(); failureCount = new AtomicInteger(); + exceptionCount = new AtomicInteger(); } @Nested @@ -413,6 +418,43 @@ void shouldCheckOther() { } } + @Nested + class OnSuccessOrFailure_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.CREATED); + Supplier supplier = () -> response; + + KiwiResponses.onSuccessOrFailure(supplier, + successResponse -> successCount.incrementAndGet(), + failResponse -> failureCount.incrementAndGet(), + supplierException -> exceptionCount.incrementAndGet()); + + assertThat(successCount).hasValue(1); + assertThat(failureCount).hasValue(0); + assertThat(exceptionCount).hasValue(0); + + verify(response).close(); + } + + @Test + void shouldCallExceptionConsumer_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + KiwiResponses.onSuccessOrFailure(supplier, + successResponse -> successCount.incrementAndGet(), + failResponse -> failureCount.incrementAndGet(), + supplierException -> exceptionCount.incrementAndGet()); + + assertThat(successCount).hasValue(0); + assertThat(failureCount).hasValue(0); + assertThat(exceptionCount).hasValue(1); + } + } + @Nested class OnSuccessOrFailure { @@ -461,6 +503,49 @@ void shouldCallFailedConsumer_ForUnsuccessfulResponse() { } } + @Nested + class OnSuccessOrFailureThrow_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.OK); + Supplier supplier = () -> response; + + KiwiResponses.onSuccessOrFailureThrow(supplier, + successResponse -> successCount.incrementAndGet(), + failResponse -> { + failureCount.incrementAndGet(); + return new CustomKiwiResponsesRuntimeException(failResponse); + }); + + assertThat(successCount).hasValue(1); + assertThat(failureCount).hasValue(0); + + verify(response).close(); + } + + @Test + void shouldRethrowSupplierException_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + var thrown = catchThrowable(() -> + KiwiResponses.onSuccessOrFailureThrow(supplier, + successResponse -> successCount.incrementAndGet(), + failResponse -> { + failureCount.incrementAndGet(); + return new CustomKiwiResponsesRuntimeException(failResponse); + })); + + assertThat(thrown).isExactlyInstanceOf(ProcessingException.class) + .hasMessage("request processing failed"); + + assertThat(successCount).hasValue(0); + assertThat(failureCount).hasValue(0); + } + } + @Nested class OnSuccessOrFailureThrow { @@ -502,6 +587,33 @@ void shouldThrow_ForUnsuccessfulResponse() { } } + @Nested + class OnSuccess_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.CREATED); + Supplier supplier = () -> response; + + KiwiResponses.onSuccess(supplier, successResponse -> successCount.incrementAndGet()); + + assertThat(successCount).hasValue(1); + + verify(response).close(); + } + + @Test + void shouldIgnoreExceptionsThrownBySupplier() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + KiwiResponses.onSuccess(supplier, successResponse -> successCount.incrementAndGet()); + + assertThat(successCount).hasValue(0); + } + } + @Nested class OnSuccess { @@ -528,6 +640,37 @@ void shouldNotCallSuccessConsumer_ForUnsuccessfulResponse() { } } + @Nested + class OnSuccessWithResult_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.ACCEPTED); + Supplier supplier = () -> response; + + Optional count = KiwiResponses.onSuccessWithResult(supplier, + successResponse -> successCount.incrementAndGet()); + + assertThat(count).hasValue(1); + assertThat(successCount).hasValue(1); + + verify(response).close(); + } + + @Test + void shouldIgnoreExceptionsThrownBySupplier() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + Optional count = KiwiResponses.onSuccessWithResult(supplier, + successResponse -> successCount.incrementAndGet()); + + assertThat(count).isEmpty(); + assertThat(successCount).hasValue(0); + } + } + @Nested class OnSuccessWithResult { @@ -558,6 +701,39 @@ void shouldReturnEmptyOptional_ForUnsuccessfulResponse() { } } + @Nested + class OnFailure_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.BAD_REQUEST); + Supplier supplier = () -> response; + + KiwiResponses.onFailure(supplier, + failResponse -> failureCount.incrementAndGet(), + exceptionConsumer -> exceptionCount.incrementAndGet()); + + assertThat(failureCount).hasValue(1); + assertThat(exceptionCount).hasValue(0); + + verify(response).close(); + } + + @Test + void shouldCallExceptionConsumer_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + KiwiResponses.onFailure(supplier, + failResponse -> failureCount.incrementAndGet(), + exceptionConsumer -> exceptionCount.incrementAndGet()); + + assertThat(failureCount).hasValue(0); + assertThat(exceptionCount).hasValue(1); + } + } + @Nested class OnFailure { @@ -584,6 +760,43 @@ void shouldCallFailConsumer_ForUnsuccessfulResponse() { } } + @Nested + class OnFailureThrow_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.CREATED); + Supplier supplier = () -> response; + + KiwiResponses.onFailureThrow(supplier, failResponse -> { + failureCount.incrementAndGet(); + return new CustomKiwiResponsesRuntimeException(response); + }); + + assertThat(failureCount).hasValue(0); + + verify(response).close(); + } + + @Test + void shouldRethrowSupplierException_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + var thrown = catchThrowable(() -> + KiwiResponses.onFailureThrow(supplier, failResponse -> { + failureCount.incrementAndGet(); + return new RuntimeException("should not be called"); + })); + + assertThat(thrown).isExactlyInstanceOf(ProcessingException.class) + .hasMessage("request processing failed"); + + assertThat(failureCount).hasValue(0); + } + } + @Nested class OnFailureThrow { @@ -602,7 +815,7 @@ void shouldNotThrow_ForSuccessfulResponse() { } @Test - void shouldThrow_ForSuccessfulResponse() { + void shouldThrow_ForUnsuccessfulResponse() { var response = newMockResponseWithStatus(Response.Status.EXPECTATION_FAILED); var thrown = catchThrowable(() -> @@ -619,6 +832,47 @@ void shouldThrow_ForSuccessfulResponse() { } } + @Nested + class OnSuccessWithResultOrFailure_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.NO_CONTENT); + Supplier supplier = () -> response; + + Optional count = KiwiResponses.onSuccessWithResultOrFailure(supplier, + successResponse -> successCount.incrementAndGet(), + failResponse -> failureCount.incrementAndGet(), + exceptionConsumer -> exceptionCount.incrementAndGet()); + + assertThat(count).hasValue(1); + + assertThat(successCount).hasValue(1); + assertThat(failureCount).hasValue(0); + assertThat(exceptionCount).hasValue(0); + + verify(response).close(); + } + + @Test + void shouldCallExceptionConsumer_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + Optional count = KiwiResponses.onSuccessWithResultOrFailure(supplier, + successResponse -> successCount.incrementAndGet(), + failResponse -> failureCount.incrementAndGet(), + exceptionConsumer -> exceptionCount.incrementAndGet()); + + assertThat(count).isEmpty(); + + assertThat(successCount).hasValue(0); + assertThat(failureCount).hasValue(0); + assertThat(exceptionCount).hasValue(1); + } + } + @Nested class OnSuccessWithResultOrFailure { @@ -655,6 +909,39 @@ void shouldReturnEmptyOptional_ForUnsuccessfulResult() { } } + @Nested + class OnSuccessOrFailureWithResult_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.OK); + Supplier supplier = () -> response; + + var result = KiwiResponses.onSuccessOrFailureWithResult(supplier, + successResponse -> 42, + failResponse -> -1, + supplierException -> 84); + + assertThat(result).isEqualTo(42); + + verify(response).close(); + } + + @Test + void shouldCallExceptionFunction_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + var result = KiwiResponses.onSuccessOrFailureWithResult(supplier, + successResponse -> 42, + failResponse -> -1, + supplierException -> 84); + + assertThat(result).isEqualTo(84); + } + } + @Nested class OnSuccessOrFailureWithResult { @@ -685,6 +972,39 @@ void shouldCallFailFunction_ForUnsuccessfulResponse() { } } + @Nested + class OnSuccessWithResultOrFailureThrow_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.PARTIAL_CONTENT); + Supplier supplier = () -> response; + + var result = KiwiResponses.onSuccessWithResultOrFailureThrow(supplier, + successResponse -> 42, + CustomKiwiResponsesRuntimeException::new); + + assertThat(result).isEqualTo(42); + + verify(response).close(); + } + + @Test + void shouldRethrowSupplierException_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + var thrown = catchThrowable(() -> + KiwiResponses.onSuccessWithResultOrFailureThrow(supplier, + successResponse -> 42, + CustomKiwiResponsesRuntimeException::new)); + + assertThat(thrown).isExactlyInstanceOf(ProcessingException.class) + .hasMessage("request processing failed"); + } + } + @Nested class OnSuccessWithResultOrFailureThrow { @@ -717,6 +1037,47 @@ void shouldThrow_ForUnsuccessfulResponse() { } } + @Nested + class WebCallResultRecord { + + @Test + void shouldConstructWithResponse() { + var response = Response.accepted().build(); + + var result = new WebCallResult(null, response); + + assertThat(result.hasResponse()).isTrue(); + assertThat(result.response()).isSameAs(response); + assertThat(result.error()).isNull(); + } + + @Test + void shouldConstructWithError() { + var error = new ProcessingException("something failed"); + + var result = new WebCallResult(error, null); + + assertThat(result.hasResponse()).isFalse(); + assertThat(result.response()).isNull(); + assertThat(result.error()).isSameAs(error); + } + + @Test + void shouldThrowIllegalArgument_WhenResponseAndEror_AreBothNull() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new WebCallResult(null, null)); + } + + @Test + void shouldThrowIllegalArgument_WhenResponseAndEror_AreBothNonNull() { + var error = new ProcessingException("something failed"); + var response = Response.serverError().build(); + + assertThatIllegalArgumentException() + .isThrownBy(() -> new WebCallResult(error, response)); + } + } + @Nested class Accept { From 030cd75fae388ee9d94c433427252cce55d4bafb Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Thu, 30 May 2024 20:46:23 +0000 Subject: [PATCH 04/12] Add the javadoc param, return, and throws tags --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 78 ++++++++++--------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 4ff89e07..077b3953 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -310,10 +310,10 @@ public static boolean hasFamily(Response response, Family family) { /** * TODO * - * @param responseSupplier - * @param successConsumer - * @param failedConsumer - * @param exceptionConsumer + * @param responseSupplier a Supplier that provides the response + * @param successConsumer the action to run if the response is successful + * @param failedConsumer the action to run if the response is not successful + * @param exceptionConsumer the action to run if the Supplier throws an exception */ public static void onSuccessOrFailure(Supplier responseSupplier, Consumer successConsumer, @@ -360,9 +360,10 @@ public static void onSuccessOrFailure(Response response, /** * TODO * - * @param responseSupplier - * @param successConsumer - * @param throwingFun + * @param responseSupplier a Supplier that provides the response + * @param successConsumer the action to run if the response is successful + * @param throwingFun a function that creates an appropriate (subclass of) RuntimeException + * @throws RuntimeException the result of {@code throwingFun}, or the exception thrown by the Supplier */ public static void onSuccessOrFailureThrow(Supplier responseSupplier, Consumer successConsumer, @@ -409,13 +410,13 @@ public static void onSuccessOrFailureThrow(Response response, /** * TODO * - * @param response - * @param successConsumer + * @param responseSupplier a Supplier that provides the response + * @param successConsumer the action to run if the response is successful */ - public static void onSuccess(Supplier response, + public static void onSuccess(Supplier responseSupplier, Consumer successConsumer) { - var result = getResponse(response); + var result = getResponse(responseSupplier); if (result.hasResponse()) { onSuccess(result.response(), successConsumer); @@ -438,10 +439,10 @@ public static void onSuccess(Response response, Consumer successConsum /** * TODO * - * @param - * @param responseSupplier - * @param successFun - * @return + * @param responseSupplier a Supplier that provides the response + * @param successFun the function to apply if the response is successful + * @param the result type + * @return an Optional containing a result for successful responses, or an empty Optional */ public static Optional onSuccessWithResult(Supplier responseSupplier, Function successFun) { @@ -473,9 +474,9 @@ public static Optional onSuccessWithResult(Response response, Function responseSupplier, Consumer failedConsumer, @@ -506,8 +507,9 @@ public static void onFailure(Response response, Consumer failedConsume /** * TODO * - * @param responseSupplier - * @param throwingFun + * @param responseSupplier a Supplier that provides the response + * @param throwingFun function that creates an appropriate (subclass of) RuntimeException + * @throws RuntimeException the result of {@code throwingFun}, or the exception thrown by the Supplier */ public static void onFailureThrow(Supplier responseSupplier, Function throwingFun) { @@ -548,12 +550,13 @@ public static void onFailureThrow(Response response, /** * TODO * - * @param - * @param responseSupplier - * @param successFun - * @param failedConsumer - * @param exceptionConsumer - * @return + * @param responseSupplier a Supplier that provides the response + * @param successFun the function to apply if the response is successful + * @param failedConsumer the action to run if the response is not successful + * @param exceptionConsumer the action to run if the Supplier throws an exception + * @param the result type + * @return the result from {@code successFun} for successful responses, or an empty Optional + * for unsuccessful responses or if the Supplier throws an exception */ public static Optional onSuccessWithResultOrFailure(Supplier responseSupplier, Function successFun, @@ -607,12 +610,12 @@ public static Optional onSuccessWithResultOrFailure(Response response, /** * TODO * - * @param - * @param responseSupplier - * @param successFun - * @param failedFun - * @param exceptionFun - * @return + * @param responseSupplier a Supplier that provides the response + * @param successFun the function to apply if the response is successful + * @param failedFun the function to apply if the response is not successful + * @param exceptionFun the function to apply if the Supplier throws an exception + * @param the result type + * @return the result from applying {@code successFun}, {@code failedFun}, or {@code exceptionFun} */ public static T onSuccessOrFailureWithResult(Supplier responseSupplier, Function successFun, @@ -657,11 +660,12 @@ public static T onSuccessOrFailureWithResult(Response response, /** * TODO * - * @param - * @param responseSupplier - * @param successFun - * @param throwingFun - * @return + * @param responseSupplier a Supplier that provides the response + * @param successFun the function to apply if the response is successful + * @param throwingFun a function that creates an appropriate (subclass of) RuntimeException + * @param the result type + * @return the result from applying {@code successFun} + * @throws RuntimeException the result of {@code throwingFun} or the exception thrown by the Supplier */ public static T onSuccessWithResultOrFailureThrow(Supplier responseSupplier, Function successFun, From 8df41b1e4435951ba0d2611885e34422915504ff Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Thu, 30 May 2024 21:02:59 +0000 Subject: [PATCH 05/12] Add rest of javadocs for the new onXxx methods, fix a few minor doc errors --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 57 +++++++++++++++---- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 077b3953..334fc522 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -308,7 +308,11 @@ public static boolean hasFamily(Response response, Family family) { } /** - * TODO + * Given a {@link Response} Supplier, perform an action depending on whether it was + * successful ({@code successConsumer}), failed ({@code failedConsumer}), or if the + * Supplier threw an exception ({@code exceptionConsumer}). + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successConsumer the action to run if the response is successful @@ -358,7 +362,11 @@ public static void onSuccessOrFailure(Response response, } /** - * TODO + * Given a {@link Response}, perform an action if it was successful ({@code successConsumer}. If + * the response was unsuccessful, throw the exception supplied by {@code throwingFun}. If the + * Supplier throws an exception, then that exception is rethrown. + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successConsumer the action to run if the response is successful @@ -408,7 +416,10 @@ public static void onSuccessOrFailureThrow(Response response, } /** - * TODO + * Given a {@link Response}, perform an action only if it was successful ({@code successConsumer}. No action + * is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successConsumer the action to run if the response is successful @@ -437,7 +448,10 @@ public static void onSuccess(Response response, Consumer successConsum } /** - * TODO + * Given a {@link Response}, perform an action that returns a result only if it was successful ({@code successFun}). + * No action is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successFun the function to apply if the response is successful @@ -458,7 +472,7 @@ public static Optional onSuccessWithResult(Supplier responseSup /** * Given a {@link Response}, perform an action that returns a result only if it was successful ({@code successFun}). - * No action is performer for an unsuccessful response. + * No action is performed for an unsuccessful response. *

* Ensures the response is closed after performing the action. * @@ -472,7 +486,11 @@ public static Optional onSuccessWithResult(Response response, Functionnot successful ({@code failedConsumer}), + * or if the Supplier threw an exception ({@code exceptionConsumer}). + * No action is performed for a successful response. + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param failedConsumer the action to run if the response is not successful @@ -505,7 +523,11 @@ public static void onFailure(Response response, Consumer failedConsume } /** - * TODO + * Given a {@link Response}, throw a (subclass of) {@link RuntimeException} for failed responses using + * {@code throwingFun}. If the Supplier throws an exception, that exception is rethrown. + * No action is performed for a successful response. + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param throwingFun function that creates an appropriate (subclass of) RuntimeException @@ -548,7 +570,11 @@ public static void onFailureThrow(Response response, } /** - * TODO + * Given a {@link Response}, perform an action that returns a result if the response was + * successful ({@code successFun}). Perform an action if the response was unsuccessful ({@code failedConsumer}, + * or if the Supplier threw an exception ({@code exceptionConsumer}). + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successFun the function to apply if the response is successful @@ -608,7 +634,12 @@ public static Optional onSuccessWithResultOrFailure(Response response, } /** - * TODO + * Given a {@link Response}, perform an action that returns a result if the response was + * successful ({@code successFun}. If the response was not successful return the result + * of a function ({@code failedFun}). If the Supplier threw an exception, return the result + * of a different function ({@code exceptionFun}). + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successFun the function to apply if the response is successful @@ -658,7 +689,11 @@ public static T onSuccessOrFailureWithResult(Response response, } /** - * TODO + * Given a {@link Response}, perform an action that returns a result if it was successful ({@code successFun} + * or throw a (subclass of) {@link RuntimeException} if it failed ({@code throwingFun}). If the + * Supplier threw an exception, then that exception is rethrown. + *

+ * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successFun the function to apply if the response is successful @@ -707,7 +742,7 @@ private static WebCallResult getResponse(Supplier responseSupplier) { /** * Given a {@link Response}, perform an action that returns a result if it was successful ({@code successFun} - * or throw a (subclass of ) {@link RuntimeException} if it failed ({@code throwingFun}). + * or throw a (subclass of) {@link RuntimeException} if it failed ({@code throwingFun}). *

* Ensures the response is closed after performing the action. * From 898b5f3d210f27b5b4ce459f92101d03c8f8e8d1 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Thu, 30 May 2024 21:05:01 +0000 Subject: [PATCH 06/12] Move WebCallResult and factory below all onXxx methods This keeps the "pairs" of onXxx methods together, with the Supplier one first in each pair. --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 334fc522..522c9e54 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -715,31 +715,6 @@ public static T onSuccessWithResultOrFailureThrow(Supplier respons throw result.error(); } - @VisibleForTesting - record WebCallResult(RuntimeException error, Response response) { - - // This is really an "either" type...which sadly, Java does not have. - - WebCallResult { - checkOnlyOneArgumentIsNull(error, response, - "Either the Response or the RuntimeException can be null, but not both"); - } - - boolean hasResponse() { - return nonNull(response); - } - } - - private static WebCallResult getResponse(Supplier responseSupplier) { - try { - var response = responseSupplier.get(); - return new WebCallResult(null, response); - } catch (RuntimeException e) { - LOG.trace("Response Supplier threw an exception", e); - return new WebCallResult(e, null); - } - } - /** * Given a {@link Response}, perform an action that returns a result if it was successful ({@code successFun} * or throw a (subclass of) {@link RuntimeException} if it failed ({@code throwingFun}). @@ -771,6 +746,31 @@ public static T onSuccessWithResultOrFailureThrow(Response response, } } + @VisibleForTesting + record WebCallResult(RuntimeException error, Response response) { + + // This is really an "either" type...which sadly, Java does not have. + + WebCallResult { + checkOnlyOneArgumentIsNull(error, response, + "Either the Response or the RuntimeException can be null, but not both"); + } + + boolean hasResponse() { + return nonNull(response); + } + } + + private static WebCallResult getResponse(Supplier responseSupplier) { + try { + var response = responseSupplier.get(); + return new WebCallResult(null, response); + } catch (RuntimeException e) { + LOG.trace("Response Supplier threw an exception", e); + return new WebCallResult(e, null); + } + } + /** * Given a {@link Response}, perform some action using the supplied consumer. *

From 5f51e65450d1dcf4063a8ea742d8a297decd81e6 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:21:26 -0400 Subject: [PATCH 07/12] Add argument checking and WARN-level logging when TRACE not enabled --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 64 ++++++++++++- .../kiwiproject/jaxrs/KiwiResponsesTest.java | 93 ++++++++++++++++++- 2 files changed, 149 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 522c9e54..aed91323 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -10,6 +10,7 @@ import jakarta.ws.rs.core.Response.Status.Family; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; import java.util.Optional; import java.util.function.Consumer; @@ -324,6 +325,9 @@ public static void onSuccessOrFailure(Supplier responseSupplier, Consumer failedConsumer, Consumer exceptionConsumer) { + checkArgumentNotNull(responseSupplier); + checkArgumentNotNull(exceptionConsumer); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -377,6 +381,8 @@ public static void onSuccessOrFailureThrow(Supplier responseSupplier, Consumer successConsumer, Function throwingFun) { + checkArgumentNotNull(responseSupplier); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -427,6 +433,8 @@ public static void onSuccessOrFailureThrow(Response response, public static void onSuccess(Supplier responseSupplier, Consumer successConsumer) { + checkArgumentNotNull(responseSupplier); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -461,6 +469,8 @@ public static void onSuccess(Response response, Consumer successConsum public static Optional onSuccessWithResult(Supplier responseSupplier, Function successFun) { + checkArgumentNotNull(responseSupplier); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -500,6 +510,9 @@ public static void onFailure(Supplier responseSupplier, Consumer failedConsumer, Consumer exceptionConsumer) { + checkArgumentNotNull(responseSupplier); + checkArgumentNotNull(exceptionConsumer); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -536,6 +549,8 @@ public static void onFailure(Response response, Consumer failedConsume public static void onFailureThrow(Supplier responseSupplier, Function throwingFun) { + checkArgumentNotNull(responseSupplier); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -589,6 +604,9 @@ public static Optional onSuccessWithResultOrFailure(Supplier re Consumer failedConsumer, Consumer exceptionConsumer) { + checkArgumentNotNull(responseSupplier); + checkArgumentNotNull(exceptionConsumer); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -653,6 +671,9 @@ public static T onSuccessOrFailureWithResult(Supplier responseSupp Function failedFun, Function exceptionFun) { + checkArgumentNotNull(responseSupplier); + checkArgumentNotNull(exceptionFun); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -706,6 +727,8 @@ public static T onSuccessWithResultOrFailureThrow(Supplier respons Function successFun, Function throwingFun) { + checkArgumentNotNull(responseSupplier); + var result = getResponse(responseSupplier); if (result.hasResponse()) { @@ -756,18 +779,49 @@ record WebCallResult(RuntimeException error, Response response) { "Either the Response or the RuntimeException can be null, but not both"); } + static WebCallResult ofResponse(Response response) { + return new WebCallResult(null, response); + } + + static WebCallResult ofError(RuntimeException error) { + return new WebCallResult(error, null); + } + boolean hasResponse() { return nonNull(response); } } - private static WebCallResult getResponse(Supplier responseSupplier) { + @VisibleForTesting + static WebCallResult getResponse(Supplier responseSupplier) { + Response response = null; + RuntimeException error = null; try { - var response = responseSupplier.get(); - return new WebCallResult(null, response); + response = responseSupplier.get(); } catch (RuntimeException e) { - LOG.trace("Response Supplier threw an exception", e); - return new WebCallResult(e, null); + error = e; + } + + if (nonNull(response)) { + return WebCallResult.ofResponse(response); + } + + if (nonNull(error)) { + logResponseSupplierException(LOG, error); + return WebCallResult.ofError(error); + } + + LOG.warn("Response Supplier returned a null Response, which is not permitted"); + throw new IllegalStateException("Response returned by Supplier must not be null"); + } + + @VisibleForTesting + static void logResponseSupplierException(Logger logger, RuntimeException error) { + if (logger.isTraceEnabled()) { + logger.trace("Response Supplier threw an exception", error); + } else { + logger.warn("Response Supplier unexpectedly threw: {}: {} (enable TRACE level to see stack trace)", + error.getClass().getName(), error.getMessage()); } } diff --git a/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java b/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java index 7e4ebd72..cb2fdf61 100644 --- a/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java +++ b/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java @@ -11,11 +11,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assertions.assertAll; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import jakarta.ws.rs.ProcessingException; @@ -29,6 +32,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kiwiproject.jaxrs.KiwiResponses.WebCallResult; +import org.kiwiproject.junit.jupiter.ClearBoxTest; +import org.slf4j.Logger; import java.util.Arrays; import java.util.Optional; @@ -1044,7 +1049,7 @@ class WebCallResultRecord { void shouldConstructWithResponse() { var response = Response.accepted().build(); - var result = new WebCallResult(null, response); + var result = WebCallResult.ofResponse(response); assertThat(result.hasResponse()).isTrue(); assertThat(result.response()).isSameAs(response); @@ -1055,7 +1060,7 @@ void shouldConstructWithResponse() { void shouldConstructWithError() { var error = new ProcessingException("something failed"); - var result = new WebCallResult(error, null); + var result = WebCallResult.ofError(error); assertThat(result.hasResponse()).isFalse(); assertThat(result.response()).isNull(); @@ -1069,7 +1074,7 @@ void shouldThrowIllegalArgument_WhenResponseAndEror_AreBothNull() { } @Test - void shouldThrowIllegalArgument_WhenResponseAndEror_AreBothNonNull() { + void shouldThrowIllegalArgument_WhenResponseAndError_AreBothNonNull() { var error = new ProcessingException("something failed"); var response = Response.serverError().build(); @@ -1078,6 +1083,88 @@ void shouldThrowIllegalArgument_WhenResponseAndEror_AreBothNonNull() { } } + @Nested + class GetResponseFromSupplier { + + @ClearBoxTest + void shouldRequireNonNullResponse() { + Supplier responseSupplier = () -> null; + + assertThatIllegalStateException() + .isThrownBy(() -> KiwiResponses.getResponse(responseSupplier)) + .withMessage("Response returned by Supplier must not be null"); + } + + @ClearBoxTest + void shouldReturnResponseFromSupplier() { + var response = Response.accepted().build(); + Supplier responseSupplier = () -> response; + + var webCallResult = KiwiResponses.getResponse(responseSupplier); + + assertAll( + () -> assertThat(webCallResult.hasResponse()).isTrue(), + () -> assertThat(webCallResult.response()).isSameAs(response), + () -> assertThat(webCallResult.error()).isNull() + ); + } + + @ClearBoxTest + void shouldReturnRuntimeExceptionFromSupplier() { + var processingException = new ProcessingException("request processing failed"); + Supplier responseSupplier = () -> { + throw processingException; + }; + + var webCallResult = KiwiResponses.getResponse(responseSupplier); + + assertAll( + () -> assertThat(webCallResult.hasResponse()).isFalse(), + () -> assertThat(webCallResult.response()).isNull(), + () -> assertThat(webCallResult.error()).isSameAs(processingException) + ); + } + + @Nested + class LogResponseSupplierException { + + private Logger logger; + private RuntimeException error; + + @BeforeEach + void setUp() { + logger = mock(Logger.class); + error = new ProcessingException("error processing"); + } + + @ClearBoxTest + void shouldLogAtTraceWhenTraceLevelEnabled() { + when(logger.isTraceEnabled()).thenReturn(true); + + KiwiResponses.logResponseSupplierException(logger, error); + + verify(logger).isTraceEnabled(); + verify(logger).trace("Response Supplier threw an exception", error); + verifyNoMoreInteractions(logger); + } + + @ClearBoxTest + void shouldLogAtWarnWhenTraceLevelNotEnabled() { + when(logger.isTraceEnabled()).thenReturn(false); + + KiwiResponses.logResponseSupplierException(logger, error); + + verify(logger).isTraceEnabled(); + verify(logger).warn( + "Response Supplier unexpectedly threw: {}: {} (enable TRACE level to see stack trace)", + ProcessingException.class.getName(), + "error processing" + ); + verifyNoMoreInteractions(logger); + } + } + } + @Nested class Accept { From 287c863be3437dc012cc3cb8200ac3439db944dd Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sun, 2 Jun 2024 09:43:18 -0400 Subject: [PATCH 08/12] Add overloads for accept/apply that accept Supplier; code cleanup --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 213 +++++++++++------- .../kiwiproject/jaxrs/KiwiResponsesTest.java | 179 ++++++++++----- 2 files changed, 256 insertions(+), 136 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index aed91323..fd0356d3 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -315,9 +315,9 @@ public static boolean hasFamily(Response response, Family family) { *

* Ensures the response is closed after performing the action. * - * @param responseSupplier a Supplier that provides the response - * @param successConsumer the action to run if the response is successful - * @param failedConsumer the action to run if the response is not successful + * @param responseSupplier a Supplier that provides the response + * @param successConsumer the action to run if the response is successful + * @param failedConsumer the action to run if the response is not successful * @param exceptionConsumer the action to run if the Supplier throws an exception */ public static void onSuccessOrFailure(Supplier responseSupplier, @@ -366,15 +366,15 @@ public static void onSuccessOrFailure(Response response, } /** - * Given a {@link Response}, perform an action if it was successful ({@code successConsumer}. If - * the response was unsuccessful, throw the exception supplied by {@code throwingFun}. If the - * Supplier throws an exception, then that exception is rethrown. + * Given a {@link Response} Supplier, perform an action if it was successful ({@code successConsumer}. + * If the response was unsuccessful, throw the exception supplied by {@code throwingFun}. + * If the Supplier throws an exception, then that exception is rethrown. *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param successConsumer the action to run if the response is successful - * @param throwingFun a function that creates an appropriate (subclass of) RuntimeException + * @param successConsumer the action to run if the response is successful + * @param throwingFun a function that creates an appropriate (subclass of) RuntimeException * @throws RuntimeException the result of {@code throwingFun}, or the exception thrown by the Supplier */ public static void onSuccessOrFailureThrow(Supplier responseSupplier, @@ -422,13 +422,13 @@ public static void onSuccessOrFailureThrow(Response response, } /** - * Given a {@link Response}, perform an action only if it was successful ({@code successConsumer}. No action - * is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. + * Given a {@link Response} Supplier, perform an action only if it was successful ({@code successConsumer}. + * No action is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param successConsumer the action to run if the response is successful + * @param successConsumer the action to run if the response is successful */ public static void onSuccess(Supplier responseSupplier, Consumer successConsumer) { @@ -456,14 +456,16 @@ public static void onSuccess(Response response, Consumer successConsum } /** - * Given a {@link Response}, perform an action that returns a result only if it was successful ({@code successFun}). - * No action is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. + * Given a {@link Response} Supplier, perform an action that returns a result only if it was + * successful ({@code successFun}). + * No action is performed for an unsuccessful response, and exceptions + * thrown by the Supplier are ignored. *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param successFun the function to apply if the response is successful - * @param the result type + * @param successFun the function to apply if the response is successful + * @param the result type * @return an Optional containing a result for successful responses, or an empty Optional */ public static Optional onSuccessWithResult(Supplier responseSupplier, @@ -496,14 +498,15 @@ public static Optional onSuccessWithResult(Response response, Functionnot successful ({@code failedConsumer}), - * or if the Supplier threw an exception ({@code exceptionConsumer}). + * Given a {@link Response} Supplier, perform an action only if it was + * not successful ({@code failedConsumer}), or if the Supplier + * threw an exception ({@code exceptionConsumer}). * No action is performed for a successful response. *

* Ensures the response is closed after performing the action. * - * @param responseSupplier a Supplier that provides the response - * @param failedConsumer the action to run if the response is not successful + * @param responseSupplier a Supplier that provides the response + * @param failedConsumer the action to run if the response is not successful * @param exceptionConsumer the action to run if the Supplier throws an exception */ public static void onFailure(Supplier responseSupplier, @@ -536,14 +539,15 @@ public static void onFailure(Response response, Consumer failedConsume } /** - * Given a {@link Response}, throw a (subclass of) {@link RuntimeException} for failed responses using - * {@code throwingFun}. If the Supplier throws an exception, that exception is rethrown. + * Given a {@link Response} Supplier, throw a (subclass of) {@link RuntimeException} for failed + * responses using {@code throwingFun}. + * If the Supplier throws an exception, that exception is rethrown. * No action is performed for a successful response. *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param throwingFun function that creates an appropriate (subclass of) RuntimeException + * @param throwingFun function that creates an appropriate (subclass of) RuntimeException * @throws RuntimeException the result of {@code throwingFun}, or the exception thrown by the Supplier */ public static void onFailureThrow(Supplier responseSupplier, @@ -585,17 +589,17 @@ public static void onFailureThrow(Response response, } /** - * Given a {@link Response}, perform an action that returns a result if the response was + * Given a {@link Response} Supplier, perform an action that returns a result if the response was * successful ({@code successFun}). Perform an action if the response was unsuccessful ({@code failedConsumer}, * or if the Supplier threw an exception ({@code exceptionConsumer}). *

* Ensures the response is closed after performing the action. * - * @param responseSupplier a Supplier that provides the response - * @param successFun the function to apply if the response is successful - * @param failedConsumer the action to run if the response is not successful + * @param responseSupplier a Supplier that provides the response + * @param successFun the function to apply if the response is successful + * @param failedConsumer the action to run if the response is not successful * @param exceptionConsumer the action to run if the Supplier throws an exception - * @param the result type + * @param the result type * @return the result from {@code successFun} for successful responses, or an empty Optional * for unsuccessful responses or if the Supplier throws an exception */ @@ -652,7 +656,7 @@ public static Optional onSuccessWithResultOrFailure(Response response, } /** - * Given a {@link Response}, perform an action that returns a result if the response was + * Given a {@link Response} Supplier, perform an action that returns a result if the response was * successful ({@code successFun}. If the response was not successful return the result * of a function ({@code failedFun}). If the Supplier threw an exception, return the result * of a different function ({@code exceptionFun}). @@ -660,10 +664,10 @@ public static Optional onSuccessWithResultOrFailure(Response response, * Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param successFun the function to apply if the response is successful - * @param failedFun the function to apply if the response is not successful - * @param exceptionFun the function to apply if the Supplier throws an exception - * @param the result type + * @param successFun the function to apply if the response is successful + * @param failedFun the function to apply if the response is not successful + * @param exceptionFun the function to apply if the Supplier throws an exception + * @param the result type * @return the result from applying {@code successFun}, {@code failedFun}, or {@code exceptionFun} */ public static T onSuccessOrFailureWithResult(Supplier responseSupplier, @@ -710,16 +714,17 @@ public static T onSuccessOrFailureWithResult(Response response, } /** - * Given a {@link Response}, perform an action that returns a result if it was successful ({@code successFun} - * or throw a (subclass of) {@link RuntimeException} if it failed ({@code throwingFun}). If the - * Supplier threw an exception, then that exception is rethrown. + * Given a {@link Response} Supplier, perform an action that returns a result if it was + * successful ({@code successFun} or throw a (subclass of) {@link RuntimeException} if it + * failed ({@code throwingFun}). + * If the Supplier threw an exception, then that exception is rethrown. *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param successFun the function to apply if the response is successful - * @param throwingFun a function that creates an appropriate (subclass of) RuntimeException - * @param the result type + * @param successFun the function to apply if the response is successful + * @param throwingFun a function that creates an appropriate (subclass of) RuntimeException + * @param the result type * @return the result from applying {@code successFun} * @throws RuntimeException the result of {@code throwingFun} or the exception thrown by the Supplier */ @@ -769,6 +774,98 @@ public static T onSuccessWithResultOrFailureThrow(Response response, } } + /** + * Given a {@link Response} Supplier, perform some action using the supplied consumer. + *

+ * Ensures the response is closed after performing the action. + * + * @param responseSupplier a Supplier that provides the response + * @param responseConsumer the action to run + * @param exceptionConsumer the action to run if the Supplier throws an exception + */ + public static void accept(Supplier responseSupplier, + Consumer responseConsumer, + Consumer exceptionConsumer) { + + checkArgumentNotNull(responseSupplier); + checkArgumentNotNull(exceptionConsumer); + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + accept(result.response(), responseConsumer); + } else { + exceptionConsumer.accept(result.error()); + } + } + + /** + * Given a {@link Response}, perform some action using the supplied consumer. + *

+ * Ensures the response is closed after performing the action. + * + * @param response the response object + * @param responseConsumer the action to run + */ + public static void accept(Response response, Consumer responseConsumer) { + checkArgumentNotNull(response); + checkArgumentNotNull(responseConsumer); + + try { + responseConsumer.accept(response); + } finally { + closeQuietly(response); + } + } + + /** + * Given a {@link Response} Supplier, perform an action tha returns a result using the given function. + *

+ * Ensures the response is closed after performing the action. + * + * @param responseSupplier a Supplier that provides the response + * @param fun the function to apply to the response + * @param exceptionFun the function to apply if the Supplier throws an exception + * @param the result type + * @return the result of applying the given function + */ + public static T apply(Supplier responseSupplier, + Function fun, + Function exceptionFun) { + + checkArgumentNotNull(responseSupplier); + checkArgumentNotNull(exceptionFun); + + var result = getResponse(responseSupplier); + + if (result.hasResponse()) { + return apply(result.response(), fun); + } + + return exceptionFun.apply(result.error()); + } + + /** + * Given a {@link Response}, perform an action tha returns a result using the given function. + *

+ * Ensures the response is closed after performing the action. + * + * @param response the response object + * @param fun the function to apply to the response + * @param the result type + * @return the result of applying the given function + */ + public static T apply(Response response, Function fun) { + checkArgumentNotNull(response); + checkArgumentNotNull(fun); + + try { + return fun.apply(response); + } finally { + closeQuietly(response); + } + } + @VisibleForTesting record WebCallResult(RuntimeException error, Response response) { @@ -825,46 +922,6 @@ static void logResponseSupplierException(Logger logger, RuntimeException error) } } - /** - * Given a {@link Response}, perform some action using the supplied consumer. - *

- * Ensures the response is closed after performing the action. - * - * @param response the response object - * @param responseConsumer the action to run - */ - public static void accept(Response response, Consumer responseConsumer) { - checkArgumentNotNull(response); - checkArgumentNotNull(responseConsumer); - - try { - responseConsumer.accept(response); - } finally { - closeQuietly(response); - } - } - - /** - * Given a {@link Response}, perform an action tha returns a result using the given function. - *

- * Ensures the response is closed after performing the action. - * - * @param response the response object - * @param fun the function to apply to the response - * @param the result type - * @return the result of applying the given function - */ - public static T apply(Response response, Function fun) { - checkArgumentNotNull(response); - checkArgumentNotNull(fun); - - try { - return fun.apply(response); - } finally { - closeQuietly(response); - } - } - /** * Closes the given {@link Response}, which can be {@code null}, swallowing any exceptions and logging them * at INFO level. diff --git a/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java b/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java index cb2fdf61..e650c6a5 100644 --- a/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java +++ b/src/test/java/org/kiwiproject/jaxrs/KiwiResponsesTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.kiwiproject.jaxrs.KiwiResponses.WebCallResult; import org.kiwiproject.junit.jupiter.ClearBoxTest; import org.slf4j.Logger; @@ -1042,6 +1041,122 @@ void shouldThrow_ForUnsuccessfulResponse() { } } + @Nested + class Accept_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.UNSUPPORTED_MEDIA_TYPE); + Supplier supplier = () -> response; + + KiwiResponses.accept(supplier, + anyResponse -> successCount.incrementAndGet(), + supplierException -> exceptionCount.incrementAndGet()); + + assertThat(successCount).hasValue(1); + assertThat(exceptionCount).hasValue(0); + + verify(response).close(); + } + + @Test + void shouldCallExceptionConsumer_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + KiwiResponses.accept(supplier, + anyResponse -> successCount.incrementAndGet(), + supplierException -> exceptionCount.incrementAndGet()); + + assertThat(successCount).hasValue(0); + assertThat(exceptionCount).hasValue(1); + } + } + + @Nested + class Accept { + + @Test + void shouldAccept_SuccessfulResponses() { + var response = newMockResponseWithStatus(Response.Status.NO_CONTENT); + + assertAccepts(response); + } + + @Test + void shouldAccept_UnsuccessfulResponses() { + var response = newMockResponseWithStatus(Response.Status.BAD_REQUEST); + + assertAccepts(response); + } + + private void assertAccepts(Response response) { + KiwiResponses.accept(response, response1 -> successCount.incrementAndGet()); + + assertThat(successCount).hasValue(1); + + verify(response).close(); + } + } + + @Nested + class Apply_UsingResponseSupplier { + + @Test + void shouldUseResponseFromSupplier() { + var response = newMockResponseWithStatus(Response.Status.CREATED); + Supplier supplier = () -> response; + + var result = KiwiResponses.apply(supplier, + anyResponse -> 42, + supplierException -> 24); + + assertThat(result).isEqualTo(42); + + verify(response).close(); + } + + @Test + void shouldCallExceptionFunction_WhenResponseSupplierThrowsException() { + Supplier supplier = () -> { + throw new ProcessingException("request processing failed"); + }; + + var result = KiwiResponses.apply(supplier, + anyResponse -> 42, + supplierException -> 24); + + assertThat(result).isEqualTo(24); + } + } + + @Nested + class Apply { + + @Test + void shouldApply_SuccessfulResponses() { + var response = newMockResponseWithStatus(Response.Status.CREATED); + + assertApplies(response); + } + + @Test + void shouldApply_UnsuccessfulResponses() { + var response = newMockResponseWithStatus(Response.Status.UNAUTHORIZED); + + assertApplies(response); + } + + private void assertApplies(Response response) { + var result = KiwiResponses.apply(response, response1 -> 84); + + assertThat(result).isEqualTo(84); + + verify(response).close(); + } + } + @Nested class WebCallResultRecord { @@ -1049,7 +1164,7 @@ class WebCallResultRecord { void shouldConstructWithResponse() { var response = Response.accepted().build(); - var result = WebCallResult.ofResponse(response); + var result = KiwiResponses.WebCallResult.ofResponse(response); assertThat(result.hasResponse()).isTrue(); assertThat(result.response()).isSameAs(response); @@ -1060,7 +1175,7 @@ void shouldConstructWithResponse() { void shouldConstructWithError() { var error = new ProcessingException("something failed"); - var result = WebCallResult.ofError(error); + var result = KiwiResponses.WebCallResult.ofError(error); assertThat(result.hasResponse()).isFalse(); assertThat(result.response()).isNull(); @@ -1068,9 +1183,9 @@ void shouldConstructWithError() { } @Test - void shouldThrowIllegalArgument_WhenResponseAndEror_AreBothNull() { + void shouldThrowIllegalArgument_WhenResponseAndError_AreBothNull() { assertThatIllegalArgumentException() - .isThrownBy(() -> new WebCallResult(null, null)); + .isThrownBy(() -> new KiwiResponses.WebCallResult(null, null)); } @Test @@ -1079,7 +1194,7 @@ void shouldThrowIllegalArgument_WhenResponseAndError_AreBothNonNull() { var response = Response.serverError().build(); assertThatIllegalArgumentException() - .isThrownBy(() -> new WebCallResult(error, response)); + .isThrownBy(() -> new KiwiResponses.WebCallResult(error, response)); } } @@ -1165,58 +1280,6 @@ void shouldLogAtWarnWhenTraceLevelNotEnabled() { } } - @Nested - class Accept { - - @Test - void shouldAccept_SuccessfulResponses() { - var response = newMockResponseWithStatus(Response.Status.NO_CONTENT); - - assertAccepts(response); - } - - @Test - void shouldAccept_UnsuccessfulResponses() { - var response = newMockResponseWithStatus(Response.Status.BAD_REQUEST); - - assertAccepts(response); - } - - private void assertAccepts(Response response) { - KiwiResponses.accept(response, response1 -> successCount.incrementAndGet()); - - assertThat(successCount).hasValue(1); - - verify(response).close(); - } - } - - @Nested - class Apply { - - @Test - void shouldApply_SuccessfulResponses() { - var response = newMockResponseWithStatus(Response.Status.CREATED); - - assertApplies(response); - } - - @Test - void shouldApply_UnsuccessfulResponses() { - var response = newMockResponseWithStatus(Response.Status.UNAUTHORIZED); - - assertApplies(response); - } - - private void assertApplies(Response response) { - var result = KiwiResponses.apply(response, response1 -> 84); - - assertThat(result).isEqualTo(84); - - verify(response).close(); - } - } - private static class CustomKiwiResponsesRuntimeException extends RuntimeException { CustomKiwiResponsesRuntimeException(Response response) { super("Kiwi received failed response with status: " + response.getStatus()); From c0d3ae24bd088e94c7eda074d8d92da678c77aa5 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sun, 2 Jun 2024 10:58:37 -0400 Subject: [PATCH 09/12] Update javadocs on accept and apply --- src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index fd0356d3..857cc97f 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -775,12 +775,12 @@ public static T onSuccessWithResultOrFailureThrow(Response response, } /** - * Given a {@link Response} Supplier, perform some action using the supplied consumer. + * Given a {@link Response} Supplier, perform some action using one of the supplied consumers. *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response - * @param responseConsumer the action to run + * @param responseConsumer the action to run on any response * @param exceptionConsumer the action to run if the Supplier throws an exception */ public static void accept(Supplier responseSupplier, @@ -819,7 +819,7 @@ public static void accept(Response response, Consumer responseConsumer } /** - * Given a {@link Response} Supplier, perform an action tha returns a result using the given function. + * Given a {@link Response} Supplier, perform an action tha returns a result using one of the given functions. *

* Ensures the response is closed after performing the action. * From 977566182cbc22d52fe86852d8265326d340087e Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sun, 2 Jun 2024 11:10:41 -0400 Subject: [PATCH 10/12] Emphasize that failures/exceptions are ignored in javadocs for onSuccess --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 857cc97f..a62634f7 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -423,7 +423,8 @@ public static void onSuccessOrFailureThrow(Response response, /** * Given a {@link Response} Supplier, perform an action only if it was successful ({@code successConsumer}. - * No action is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. + *

+ * No action is performed for an unsuccessful response, and exceptions thrown by the Supplier are ignored. *

* Ensures the response is closed after performing the action. * @@ -443,8 +444,9 @@ public static void onSuccess(Supplier responseSupplier, } /** - * Given a {@link Response}, perform an action only if it was successful ({@code successConsumer}. No action - * is performed for an unsuccessful response. + * Given a {@link Response}, perform an action only if it was successful ({@code successConsumer}. + *

+ * No action is performed for an unsuccessful response. *

* Ensures the response is closed after performing the action. * @@ -458,8 +460,9 @@ public static void onSuccess(Response response, Consumer successConsum /** * Given a {@link Response} Supplier, perform an action that returns a result only if it was * successful ({@code successFun}). - * No action is performed for an unsuccessful response, and exceptions - * thrown by the Supplier are ignored. + *

+ * No action is performed for an unsuccessful response, and exceptions + * thrown by the Supplier are ignored. *

* Ensures the response is closed after performing the action. * @@ -484,7 +487,8 @@ public static Optional onSuccessWithResult(Supplier responseSup /** * Given a {@link Response}, perform an action that returns a result only if it was successful ({@code successFun}). - * No action is performed for an unsuccessful response. + *

+ * No action is performed for an unsuccessful response. *

* Ensures the response is closed after performing the action. * From 70aaf6ad6f03eec95e89b3630bb2a2f56f964be9 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sun, 2 Jun 2024 11:17:20 -0400 Subject: [PATCH 11/12] More javadoc improvements For the onFailure methods, separate "no action for successful response" into a new paragraph for clarity. --- src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index a62634f7..4fe58d12 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -505,6 +505,7 @@ public static Optional onSuccessWithResult(Response response, Functionnot successful ({@code failedConsumer}), or if the Supplier * threw an exception ({@code exceptionConsumer}). + *

* No action is performed for a successful response. *

* Ensures the response is closed after performing the action. @@ -531,6 +532,7 @@ public static void onFailure(Supplier responseSupplier, /** * Given a {@link Response}, perform an action only if it was not successful ({@code failedConsumer}). + *

* No action is performed for a successful response. *

* Ensures the response is closed after performing the action. @@ -546,6 +548,7 @@ public static void onFailure(Response response, Consumer failedConsume * Given a {@link Response} Supplier, throw a (subclass of) {@link RuntimeException} for failed * responses using {@code throwingFun}. * If the Supplier throws an exception, that exception is rethrown. + *

* No action is performed for a successful response. *

* Ensures the response is closed after performing the action. @@ -570,7 +573,9 @@ public static void onFailureThrow(Supplier responseSupplier, /** * Given a {@link Response}, throw a (subclass of) {@link RuntimeException} for failed responses using - * {@code throwingFun}. No action is performed for a successful response. + * {@code throwingFun}. + *

+ * No action is performed for a successful response. *

* Ensures the response is closed after performing the action. * From ff5f50e2b26b3510f12f03163c428d979ccf0870 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sun, 2 Jun 2024 17:26:55 -0400 Subject: [PATCH 12/12] Code review: Rename all "failedConsumer" to "failureConsumer" --- .../org/kiwiproject/jaxrs/KiwiResponses.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java index 4fe58d12..edb15f27 100644 --- a/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java +++ b/src/main/java/org/kiwiproject/jaxrs/KiwiResponses.java @@ -310,19 +310,19 @@ public static boolean hasFamily(Response response, Family family) { /** * Given a {@link Response} Supplier, perform an action depending on whether it was - * successful ({@code successConsumer}), failed ({@code failedConsumer}), or if the + * successful ({@code successConsumer}), failed ({@code failureConsumer}), or if the * Supplier threw an exception ({@code exceptionConsumer}). *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successConsumer the action to run if the response is successful - * @param failedConsumer the action to run if the response is not successful + * @param failureConsumer the action to run if the response is not successful * @param exceptionConsumer the action to run if the Supplier throws an exception */ public static void onSuccessOrFailure(Supplier responseSupplier, Consumer successConsumer, - Consumer failedConsumer, + Consumer failureConsumer, Consumer exceptionConsumer) { checkArgumentNotNull(responseSupplier); @@ -331,7 +331,7 @@ public static void onSuccessOrFailure(Supplier responseSupplier, var result = getResponse(responseSupplier); if (result.hasResponse()) { - onSuccessOrFailure(result.response(), successConsumer, failedConsumer); + onSuccessOrFailure(result.response(), successConsumer, failureConsumer); } else { exceptionConsumer.accept(result.error()); } @@ -339,26 +339,26 @@ public static void onSuccessOrFailure(Supplier responseSupplier, /** * Given a {@link Response}, perform an action depending on whether it was successful ({@code successConsumer}) - * or failed ({@code failedConsumer}). + * or failed ({@code failureConsumer}). *

* Ensures the response is closed after performing the action. * * @param response the response object * @param successConsumer the action to run if the response is successful - * @param failedConsumer the action to run if the response is not successful + * @param failureConsumer the action to run if the response is not successful */ public static void onSuccessOrFailure(Response response, Consumer successConsumer, - Consumer failedConsumer) { + Consumer failureConsumer) { checkArgumentNotNull(response); checkArgumentNotNull(successConsumer); - checkArgumentNotNull(failedConsumer); + checkArgumentNotNull(failureConsumer); try { if (successful(response)) { successConsumer.accept(response); } else { - failedConsumer.accept(response); + failureConsumer.accept(response); } } finally { closeQuietly(response); @@ -503,7 +503,7 @@ public static Optional onSuccessWithResult(Response response, Functionnot successful ({@code failedConsumer}), or if the Supplier + * not successful ({@code failureConsumer}), or if the Supplier * threw an exception ({@code exceptionConsumer}). *

* No action is performed for a successful response. @@ -511,11 +511,11 @@ public static Optional onSuccessWithResult(Response response, Function responseSupplier, - Consumer failedConsumer, + Consumer failureConsumer, Consumer exceptionConsumer) { checkArgumentNotNull(responseSupplier); @@ -524,24 +524,24 @@ public static void onFailure(Supplier responseSupplier, var result = getResponse(responseSupplier); if (result.hasResponse()) { - onFailure(result.response(), failedConsumer); + onFailure(result.response(), failureConsumer); } else { exceptionConsumer.accept(result.error()); } } /** - * Given a {@link Response}, perform an action only if it was not successful ({@code failedConsumer}). + * Given a {@link Response}, perform an action only if it was not successful ({@code failureConsumer}). *

* No action is performed for a successful response. *

* Ensures the response is closed after performing the action. * * @param response the response object - * @param failedConsumer the action to run if the response is not successful + * @param failureConsumer the action to run if the response is not successful */ - public static void onFailure(Response response, Consumer failedConsumer) { - onSuccessOrFailure(response, NO_OP_RESPONSE_CONSUMER, failedConsumer); + public static void onFailure(Response response, Consumer failureConsumer) { + onSuccessOrFailure(response, NO_OP_RESPONSE_CONSUMER, failureConsumer); } /** @@ -599,14 +599,14 @@ public static void onFailureThrow(Response response, /** * Given a {@link Response} Supplier, perform an action that returns a result if the response was - * successful ({@code successFun}). Perform an action if the response was unsuccessful ({@code failedConsumer}, + * successful ({@code successFun}). Perform an action if the response was unsuccessful ({@code failureConsumer}, * or if the Supplier threw an exception ({@code exceptionConsumer}). *

* Ensures the response is closed after performing the action. * * @param responseSupplier a Supplier that provides the response * @param successFun the function to apply if the response is successful - * @param failedConsumer the action to run if the response is not successful + * @param failureConsumer the action to run if the response is not successful * @param exceptionConsumer the action to run if the Supplier throws an exception * @param the result type * @return the result from {@code successFun} for successful responses, or an empty Optional @@ -614,7 +614,7 @@ public static void onFailureThrow(Response response, */ public static Optional onSuccessWithResultOrFailure(Supplier responseSupplier, Function successFun, - Consumer failedConsumer, + Consumer failureConsumer, Consumer exceptionConsumer) { checkArgumentNotNull(responseSupplier); @@ -623,7 +623,7 @@ public static Optional onSuccessWithResultOrFailure(Supplier re var result = getResponse(responseSupplier); if (result.hasResponse()) { - return onSuccessWithResultOrFailure(result.response(), successFun, failedConsumer); + return onSuccessWithResultOrFailure(result.response(), successFun, failureConsumer); } else { exceptionConsumer.accept(result.error()); } @@ -633,29 +633,29 @@ public static Optional onSuccessWithResultOrFailure(Supplier re /** * Given a {@link Response}, perform an action that returns a result if the response was - * successful ({@code successFun}) or perform an action if the response was unsuccessful ({@code failedConsumer}. + * successful ({@code successFun}) or perform an action if the response was unsuccessful ({@code failureConsumer}. *

* Ensures the response is closed after performing the action. * * @param response the response object * @param successFun the function to apply if the response is successful - * @param failedConsumer the action to run if the response is not successful + * @param failureConsumer the action to run if the response is not successful * @param the result type * @return the result from {@code successFun} for successful responses, or an empty Optional for unsuccessful ones */ public static Optional onSuccessWithResultOrFailure(Response response, Function successFun, - Consumer failedConsumer) { + Consumer failureConsumer) { checkArgumentNotNull(response); checkArgumentNotNull(successFun); - checkArgumentNotNull(failedConsumer); + checkArgumentNotNull(failureConsumer); T result = null; try { if (successful(response)) { result = successFun.apply(response); } else { - failedConsumer.accept(response); + failureConsumer.accept(response); } } finally { closeQuietly(response);