Skip to content

Commit

Permalink
Throw converter not found instead of generic IndexOutOfBound exception (
Browse files Browse the repository at this point in the history
#5538)

* Throw converter not found instead of generic IndexOutOfBound exception fixing #3845

* Amazon DynamoDB Update: added size check to param validation, style changes in unit tests
  • Loading branch information
ar0d10n authored Sep 16, 2024
1 parent d72c3d5 commit f59c9f0
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changes/next-release/bugfix-AmazonDynamoDB-ce8ceaf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "bugfix",
"category": "Amazon DynamoDB",
"contributor": "",
"description": "Throw converter not found instead of generic IndexOutOfBound exception"
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,12 @@ private boolean shouldCache(Class<?> type) {

@SuppressWarnings("unchecked")
private <T> AttributeConverter<T> createMapConverter(EnhancedType<T> type) {
EnhancedType<?> keyType = type.rawClassParameters().get(0);
EnhancedType<T> valueType = (EnhancedType<T>) type.rawClassParameters().get(1);
List<EnhancedType<?>> rawClassParameters = type.rawClassParameters();
if (rawClassParameters.isEmpty() || rawClassParameters.size() < 2) {
throw new IllegalStateException("Converter not found for " + type);
}
EnhancedType<?> keyType = rawClassParameters.get(0);
EnhancedType<T> valueType = (EnhancedType<T>) rawClassParameters.get(1);

StringConverter<?> keyConverter = StringConverterProvider.defaultProvider().converterFor(keyType);
AttributeConverter<?> valueConverter = findConverter(valueType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,21 @@ public static <T> AttributeConverter<T> converterForClass(EnhancedType<T> type,
ChainConverterProvider chainConverterProvider) {

if (type.rawClass().isAssignableFrom(List.class)) {
List<EnhancedType<?>> params = type.rawClassParameters();
if (params.isEmpty()) {
throw new IllegalStateException("Type parameter is missing for " + type);
}
return (AttributeConverter<T>) ListAttributeConverter
.create(converterForClass(type.rawClassParameters().get(0), chainConverterProvider));
.create(converterForClass(params.get(0), chainConverterProvider));
}
if (type.rawClass().isAssignableFrom(Map.class)) {
List<EnhancedType<?>> params = type.rawClassParameters();
if (params.isEmpty() || params.size() < 2) {
throw new IllegalStateException("Type parameters are missing for " + type);
}
return (AttributeConverter<T>) MapAttributeConverter.mapConverter(
StringConverterProvider.defaultProvider().converterFor(type.rawClassParameters().get(0)),
converterForClass(type.rawClassParameters().get(1), chainConverterProvider));
StringConverterProvider.defaultProvider().converterFor(params.get(0)),
converterForClass(params.get(1), chainConverterProvider));
}
return Optional.ofNullable(chainConverterProvider.converterFor(type))
.orElseThrow(() -> new IllegalStateException(
Expand Down Expand Up @@ -503,4 +511,4 @@ private static void checkAndValidateClass(Class<?> type, boolean isPut) {
String.format(VALIDATE_TYPE_ERROR, "Map", isPut ? "put" : "get", "Map"));

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package software.amazon.awssdk.enhanced.dynamodb;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;

import org.junit.Rule;
import org.junit.Test;
Expand All @@ -26,6 +27,7 @@
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.InvalidBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.ObjectMapBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.SimpleBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.SimpleImmutable;

Expand Down Expand Up @@ -85,6 +87,13 @@ public void fromClass_constructsImmutableTableSchema() {
assertThat(tableSchema).isInstanceOf(ImmutableTableSchema.class);
}

@Test
public void fromClass_missingObjectConverter_throwsIllegalStateException() {
assertThatIllegalStateException().isThrownBy(
() -> TableSchema.fromClass(ObjectMapBean.class)
).withMessage("Converter not found for EnhancedType(java.lang.Object)");
}

@Test
public void fromClass_invalidClassThrowsException() {
exception.expect(IllegalArgumentException.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -304,6 +305,32 @@ void access_CustomType_without_AttributeConverterProvider() {
assertThat(docWithCustomProvider.get("customMapValue", EnhancedType.of(CustomClassForDocumentAPI.class))).isNotNull();
}

@Test
void listUsed_missingTypeParameter_throwsIllegalStateException() {
EnhancedDocument enhancedDocument = EnhancedDocument.builder()
.attributeConverterProviders(defaultProvider())
.put("list", Collections.singletonList(new Object()),
EnhancedType.of(List.class))
.build();

assertThatIllegalStateException().isThrownBy(
() -> enhancedDocument.toJson()
).withMessage("Type parameter is missing for EnhancedType(java.util.List)");
}

@Test
void mapUsed_missingTypeParameters_throwsIllegalStateException() {
EnhancedDocument enhancedDocument = EnhancedDocument.builder()
.attributeConverterProviders(defaultProvider())
.put("map", Collections.singletonMap("key1", new Object()),
EnhancedType.of(Map.class))
.build();

assertThatIllegalStateException().isThrownBy(
() -> enhancedDocument.toJson()
).withMessage("Type parameters are missing for EnhancedType(java.util.Map)");
}

@Test
void error_When_DefaultProviderIsPlacedCustomProvider() {
CustomClassForDocumentAPI customObject = CustomClassForDocumentAPI.builder().string("str_one")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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.mapper.testbeans;

import java.util.Map;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;

@DynamoDbBean
public class ObjectMapBean {

public ObjectMapBean() {
}

public ObjectMapBean(Map<String, Object> map) {
this.objectMap = map;
}

private Map<String, Object> objectMap;

public Map<String, Object> getObjectMap() {
return objectMap;
}

public void setObjectMap(Map<String, Object> map) {
this.objectMap = map;
}
}

0 comments on commit f59c9f0

Please sign in to comment.