I'm using DynamoDB and I would like to store the enum's String values instead of the enum itself.
For instance, I have this enum:
public enum Source { BREACH("breach"), LEAKAGE("leakage"); private final String desc; Source(String desc) { this.desc = desc; } public String desc() { return desc; } } ...and this "entity":
@DynamoDBTable(tableName = "Alerts") public final class Alert implements Serializable { private static final long serialVersionUID = 4012517315640518044L; @DynamoDBHashKey(attributeName = "AlertId") // Partition Key or Hash Attribute private String alertId; @DynamoDBTypeConvertedEnum @DynamoDBAttribute(attributeName = "Source") private Source type; // Constructor(s), Getter(s), Setter(s), ToString, etc... } With the @DynamoDBTypeConvertedEnum annotation, the value that gets saved is BREACH, but I want breach.
{ "AlertId": { "S": "a083168d-cb23-4ec8-ab80-a1c16955c4b8" }, "Source": { "S": "BREACH" }, ... "CreatedAt": { "S": "2017-05-03T14:07:36.395Z" } } Any clues? I did try "converters" (not fully, I couldn't make it work though) but I think I have to end up doing one for each enum type since they are all different.
3 Answers
You can code the Alert class like this i.e. define the attribute as String and design the getter and setter to send/receive enum object (i.e. Source).
Alert class:-
@DynamoDBTable(tableName = "Alerts") public final class Alert implements Serializable { private static final long serialVersionUID = 4012517315640518044L; private String alertId; private String type; @DynamoDBHashKey(attributeName = "AlertId") public String getAlertId() { return alertId; } @DynamoDBAttribute(attributeName = "Source") public Source getType() { if (type != null) return Source.valueOf(type); else return null; } public void setAlertId(String alertId) { this.alertId = alertId; } public void setType(Source type) { this.type = type.desc(); } } Create Alert:-
Stores the value as expected on database table. The get item from DynamoDB table also works fine.
public Boolean createAlert(String alertId, Source source) { DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient); Alert alert = new Alert(); alert.setAlertId(alertId); alert.setType(source); dynamoDBMapper.save(alert); return true; } 4Override toString() this should work.
public enum Source { BREACH("breach"), LEAKAGE("leakage"); private final String desc; Source(String desc) { this.desc = desc; } public String desc() { return desc; } @Override public String toString() { return desc; } } I solved it by defining a custom attribute converter. It works but I'm afraid you'd have to write converters for each enum.
There is already method for serializing desc().We can define a static method for deserializing toSource() Source.java
public enum Source { BREACH("breach"), LEAKAGE("leakage"); private final String desc; Source(String desc) { this.desc = desc; } public String desc() { return desc; } public static Source toSource(String value) { return Arrays.stream(Source.values()).filter(et -> et.desc().equals(value)).findFirst().orElse(null); } } We can then define a custom DynamoDBType converter:
SourceEnumDynamoDbConverter.java
public class SourceEnumDynamoDbConverter implements DynamoDBTypeConverter<String, Source> { @Override public String convert(Source source) { return source.desc(); } @Override public Source unconvert(String sourceStr) { return Source.toSource(sourceStr); } } And finally annotate our Entity's Source property with this custom converter Alert.java
@DynamoDBTable(tableName = "Alerts") public final class Alert implements Serializable { private static final long serialVersionUID = 4012517315640518044L; @DynamoDBHashKey(attributeName = "AlertId") // Partition Key or Hash Attribute private String alertId; private Source type; @DynamoDBTypeConverted(converter = TrialEnumDynamoDbConverter.class) @DynamoDBAttribute(attributeName = "Source") public Source getSource() { return type; } public void setSource(Source type) { this.type = type; } // Constructor(s), Getter(s), Setter(s), ToString, etc... } This way desc is stored and read from dynamodb resulting in
{ "AlertId": { "S": "a083168d-cb23-4ec8-ab80-a1c16955c4b8" }, "Source": { "S": "breach" }, ... "CreatedAt": { "S": "2017-05-03T14:07:36.395Z" } }