0

I have a toy DynamoDB table with a hash key, and in it I want to store some simple items in DynamoDB document format.

Here's the class to represent the document:

@DynamoDBDocument
public class Simple {
  private String key;
  private String value;

  public Simple() {
  }

  public Simple(
      String key,
      String value
  ) {
    this.key = key;
    this.value = value;
  }

  @DynamoDBAttribute
  public String getKey() {
    return key;
  }

  public void setKey(String key) {
    this.key = key;
  }

  @DynamoDBAttribute
  public String getValue() {
    return value;
  }

  public void setValue(String value) {
    this.value = value;
  }
}

and here's a class to represent the entry in the table:

@DynamoDBDocument
public class SimpleRow {
    private String hash;
  private Simple entry;

  public SimpleRow() {
  }

  public SimpleRow(
      String hash,
      Simple entry
  ) {
    this.hash = hash;
    this.entry = entry;
  }

  @DynamoDBHashKey
  public String getHash() {
    return hash;
  }

  public void setHash(String hash) {
    this.hash = hash;
  }

  @DynamoDBAttribute
  public Simple getEntry() {
    return entry;
  }

  public void setEntry(Simple entry) {
    this.entry = entry;
  }
}

With this setup, I can save entries to and laod entries from the table without a problem, using a DynamoDBMapper:

DynamoDBMapper mapper = new DynamoDBMapper(
        AmazonDynamoDBClientBuilder.standard().build(),
        DynamoDBMapperConfig
            .builder()
            .withTableNameOverride(new DynamoDBMapperConfig.TableNameOverride("simple"))
            .build()
    );
    mapper.save(new SimpleRow("the-hash", new Simple("foo", "bar")));
    System.out.println(mapper.load(SimpleRow.class, "the-hash"));

which results in an entry looking like this:

{
  "entry": {
    "M": {
      "key": {
        "S": "foo"
      },
      "value": {
        "S": "bar"
      }
    }
  },
  "hash": {
    "S": "the-key"
  }
}

However, I dislike the pollution of the Simple class with setters and zero-argument constructor - it should be an immutable data class. Therefore, I'd like to use a DynamoDBTypeConverter to construct the Simple objects.

The problem is I can't seem to write a converter that works, as I can't find a suitable source type:

  • Map, which would seem the most natural, fails with DynamoDBMappingException: not supported; requires @DynamoDBTyped or @DynamoDBTypeConverted
  • String, which would seem to be a reasonable default, doesn't error but the string supplied to the convert() method is always empty
  • Object, which would seem to be a catch-all, isn't supported by Dynamo and fails with DynamoDBMappingException: could not resolve type of class SimpleConverter

Is it possible to write a DynamoDBTypeConverter for this type? If so, what type should I use? I've trawled the internet for exampels of this but nothing seems forthcoming.

Paul Davies
  • 135
  • 1
  • 9

1 Answers1

0

You need to change Simple to Simple[] in SimleRow.java

import java.util.Arrays;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;

@DynamoDBDocument
public class SimpleRow {
  private String hash;
  private Simple[] entry;

  public SimpleRow() {
  }

  public SimpleRow(
      String hash,
      Simple[] entry
  ) {
    this.hash = hash;
    this.entry = entry;
  }

  @DynamoDBHashKey
  public String getHash() {
    return hash;
  }

  public void setHash(String hash) {
    this.hash = hash;
  }

  @DynamoDBAttribute
  public Simple[] getEntry() {
    return entry;
  }

  public void setEntry(Simple[] entry) {
    this.entry = entry;
  }

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("SimpleRow [hash=");
    builder.append(hash);
    builder.append(", entry=");
    builder.append(Arrays.toString(entry));
    builder.append("]");
    return builder.toString();
}
}

And call it in main class as new SimpleRow("the-hash", new Simple[] {new Simple("foo", "bar")})

 mapper.save(new SimpleRow("the-hash", new Simple[] {new Simple("foo", "bar")}));
Dharman
  • 30,962
  • 25
  • 85
  • 135
prem30488
  • 2,828
  • 2
  • 25
  • 57
  • This doesn't solve the problem - the problem is in Simple, not SimpleRow. I realise this question is more complicated than it needs to be, though - I'll post a new one which is clearer and delete this one. Thanks for trying to help. – Paul Davies Oct 19 '20 at 07:36
  • New question here: https://stackoverflow.com/questions/64424766/dynamodbtypeconverter-for-dynamodb-document-field-without-annotations – Paul Davies Oct 19 '20 at 09:39