Reputation:
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.
Upvotes: 4
Views: 8012
Reputation: 1
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" }
}
Upvotes: 0
Reputation: 31
Override 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; }
}
Upvotes: 0
Reputation: 39196
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;
}
Upvotes: 0