diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java index a545cb4b088e..7482b0c63f6d 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.core.internal.http.pipeline.stages; import java.io.IOException; +import java.io.UncheckedIOException; import java.time.Duration; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -56,7 +57,7 @@ public Response execute(SdkHttpFullRequest request, RequestExecutionCon Response response = executeRequest(retryableStageHelper, context); retryableStageHelper.recordAttemptSucceeded(); return response; - } catch (SdkExceptionWithRetryAfterHint | SdkException | IOException e) { + } catch (SdkExceptionWithRetryAfterHint | SdkException | IOException | UncheckedIOException e) { Throwable throwable = e; if (e instanceof SdkExceptionWithRetryAfterHint) { SdkExceptionWithRetryAfterHint wrapper = (SdkExceptionWithRetryAfterHint) e; diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtils.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtils.java index 0f6f20583187..663a03249cb2 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtils.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtils.java @@ -36,18 +36,26 @@ private ConverterUtils() { /** * Validates that a given Double input is a valid double supported by {@link DoubleAttributeConverter}. + * Null values are accepted (null will be stored as NULL in DynamoDB and round-trips correctly). * @param input */ public static void validateDouble(Double input) { + if (input == null) { + return; + } Validate.isTrue(!Double.isNaN(input), "NaN is not supported by the default converters."); Validate.isTrue(Double.isFinite(input), "Infinite numbers are not supported by the default converters."); } /** - * Validates that a given Float input is a valid double supported by {@link FloatAttributeConverter}. + * Validates that a given Float input is a valid float supported by {@link FloatAttributeConverter}. + * Null values are accepted (null will be stored as NULL in DynamoDB and round-trips correctly). * @param input */ public static void validateFloat(Float input) { + if (input == null) { + return; + } Validate.isTrue(!Float.isNaN(input), "NaN is not supported by the default converters."); Validate.isTrue(Float.isFinite(input), "Infinite numbers are not supported by the default converters."); } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtilsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtilsTest.java new file mode 100644 index 000000000000..901d1ff11fd2 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/converter/ConverterUtilsTest.java @@ -0,0 +1,63 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.enhanced.dynamodb.internal.converter; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ConverterUtilsTest { + + @Test + void validateDouble_nullDoesNotThrow() { + assertThatCode(() -> ConverterUtils.validateDouble(null)) + .doesNotThrow(); + } + + @Test + void validateDouble_finiteValueDoesNotThrow() { + assertThatCode(() -> ConverterUtils.validateDouble(3.14)) + .doesNotThrow(); + } + + @Test + void validateDouble_nanThrows() { + assertThatThrownBy(() -> ConverterUtils.validateDouble(Double.NaN)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("NaN"); + } + + @Test + void validateDouble_infiniteThrows() { + assertThatThrownBy(() -> ConverterUtils.validateDouble(Double.POSITIVE_INFINITY)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Infinite"); + } + + @Test + void validateFloat_nullDoesNotThrow() { + assertThatCode(() -> ConverterUtils.validateFloat(null)) + .doesNotThrow(); + } + + @Test + void validateFloat_nanThrows() { + assertThatThrownBy(() -> ConverterUtils.validateFloat(Float.NaN)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("NaN"); + } +}