aws / aws/aws-sdk-java-v2

Enhanced DynamoDB NPE on putItem with null map value

Open
#2,282 3 comments 2 reactions 0 assignees View on GitHub
bug dynamodb-enhanced p3
Dominant language
Java
Stars
2.6k
Forks
1k
Avg merge
2d 9h
Merged PRs (30d)
51

Description

A null pointer exception is hit in the dynamoDB enhanced client when performing a put of a map attribute with a null value.
This happens only when using a beanschema, not a staticschema.

## Describe the bug
```
public class SDKTest {

public static final StaticTableSchema CHAPTER_SCHEMA = StaticTableSchema.builder(Chapter.class)
.newItemSupplier(Chapter::new)
.addAttribute(Integer.class, a -> a.name("page").getter(Chapter::getPage).setter(Chapter::setPage))
.addAttribute(String.class, a -> a.name("text").getter(Chapter::getText).setter(Chapter::setText))
.build();

public static final StaticTableSchema BOOK_SCHEMA = StaticTableSchema.builder(Book.class)
.newItemSupplier(Book::new)
.addAttribute(String.class, a -> a.name("id").tags(primaryPartitionKey()).getter(Book::getId).setter(Book::setId))
.addAttribute(EnhancedType.mapOf(EnhancedType.of(String.class), EnhancedType.documentOf(Chapter.class, CHAPTER_SCHEMA)),
a -> a.name("map").getter(Book::getChapters).setter(Book::setChapters))
.build();

@DynamoDbBean
public static class Book {
private String id;
private Map chapters;

public Book() {}
public Book(String id) { setId(id); }

@DynamoDbPartitionKey public String getId() { return id; }
public void setId(String id) { this.id = id; }

public Map getChapters() { return chapters; }
public void setChapters(Map chapters) { this.chapters = chapters; }
}

@DynamoDbBean
public static class Chapter {
private Integer page;
private String text;

public Integer getPage() { return page; }
public void setPage(Integer page) { this.page = page; }

public String getText() { return text; }
public void setText(String text) { this.text = text; }
}

public void testStatic(DynamoDbClient client, DynamoDbEnhancedClient enhancedClient) throws Exception {
DynamoDbTable table = enhancedClient.table("books", BOOK_SCHEMA);
table.createTable();

client.putItem(b -> b.tableName("books")
.item(new HashMap() {{
put("id", AttributeValue.builder().s("123").build());
put("chapters", AttributeValue.builder()
.m(Collections.singletonMap("First", AttributeValue.builder().nul(true).build()))
.build());
}}));

Book item = table.getItem(new Book("123"));
table.putItem(item);
}

public void testBean(DynamoDbClient client, DynamoDbEnhancedClient enhancedClient) throws Exception {
DynamoDbTable table = enhancedClient.table("books", TableSchema.fromBean(Book.class));
table.createTable();

client.putItem(b -> b.tableName("books")
.item(new HashMap() {{
put("id", AttributeValue.builder().s("123").build());
put("chapters", AttributeValue.builder()
.m(Collections.singletonMap("First", AttributeValue.builder().nul(true).build()))
.build());
}}));

Book item = table.getItem(new Book("123"));
table.putItem(item); // <------------------------------LINE THAT THROWS EXCEPTION
}
}
```

## Behavior
`testStatic` works, while `testBean` throws NPE with the following trace:
```
java.lang.NullPointerException
at software.amazon.awssdk.enhanced.dynamodb.internal.mapper.ResolvedImmutableAttribute.lambda$create$0(ResolvedImmutableAttribute.java:48)
at software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema.lambda$itemToMap$5(StaticImmutableTableSchema.java:491)
at software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema.itemToMap(StaticImmutableTableSchema.java:489)
at software.amazon.awssdk.enhanced.dynamodb.mapper.WrappedTableSchema.itemToMap(WrappedTableSchema.java:59)
at software.amazon.awssdk.enhanced.dynamodb.mapper.WrappedTableSchema.itemToMap(WrappedTableSchema.java:59)
at software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.DocumentAttributeConverter.transformFrom(DocumentAttributeConverter.java:47)
at software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.MapAttributeConverter$Delegate.lambda$toAttributeValue$0(MapAttributeConverter.java:165)
at software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.MapAttributeConverter$Delegate.toAttributeValue(MapAttributeConverter.java:165)
at software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.MapAttributeConverter.transformFrom(MapAttributeConverter.java:138)
at software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.MapAttributeConverter.transformFrom(MapAttributeConverter.java:76)
at software.amazon.awssdk.enhanced.dynamodb.internal.mapper.StaticAttributeType.objectToAttributeValue(StaticAttributeType.java:40)
at software.amazon.awssdk.enhanced.dynamodb.internal.mapper.ResolvedImmutableAttribute.lambda$create$0(ResolvedImmutableAttribute.java:49)
at software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema.lambda$itemToMap$5(StaticImmutableTableSchema.java:491)
at software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema.itemToMap(StaticImmutableTableSchema.java:489)
at software.amazon.awssdk.enhanced.dynamodb.mapper.WrappedTableSchema.itemToMap(WrappedTableSchema.java:59)
at software.amazon.awssdk.enhanced.dynamodb.mapper.WrappedTableSchema.itemToMap(WrappedTableSchema.java:59)
at software.amazon.awssdk.enhanced.dynamodb.internal.operations.PutItemOperation.generateRequest(PutItemOperation.java:71)
at software.amazon.awssdk.enhanced.dynamodb.internal.operations.PutItemOperation.generateRequest(PutItemOperation.java:40)
at software.amazon.awssdk.enhanced.dynamodb.internal.operations.CommonOperation.execute(CommonOperation.java:113)
at software.amazon.awssdk.enhanced.dynamodb.internal.operations.TableOperation.executeOnPrimaryIndex(TableOperation.java:59)
at software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbTable.putItem(DefaultDynamoDbTable.java:179)
at software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbTable.putItem(DefaultDynamoDbTable.java:187)
at software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbTable.putItem(DefaultDynamoDbTable.java:192)
at com.magicbinder.core.SDKTest.testBean
```

## Your Environment

* AWS Java SDK version used: 2.15.81
* JDK version used: java 8
* Operating System and version: macOs

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.