2016-03-29 1 views
0

Ich habe eine DynamoDB-Tabelle namens "Posteingang". Darin werden Nachrichten gespeichert, die an und von Benutzern gesendet werden. Es wird mehr als eine Art von Nachricht geben, und basierend auf dem Typ können Daten mit der Nachricht einhergehen. Ich habe ein Objekt UserMessage, das der Inbox-Tabelle zuordnet. Während es für alle Nachrichten gemeinsame Felder (z. B. sendTo, sentFrom) gibt, variieren die Daten in ihrer Struktur.DynamoDBMappingException bei der Verwendung von Java Generics

Anstatt eine Map für diese Daten zu verwenden, kommt der Gedanke, dass die Verwendung von Java Generics ein besserer Ansatz sein könnte. Ich habe ein Objekt mit @DynamoDBDocument annotiert, und DynamoDBMapper wird das zu JSON serialisieren. Wenn die Elementvariable wie folgt deklariert wird:

tatsächlich wird das Ergebnis erwartet. Daten werden in JSON serialisiert und im Datenattribut im Posteingang im Format der Annotationen von ContactData gespeichert. Um jedoch die gewünschte Flexibilität durch die Verwendung generischer Typen zu erzielen, löst ein Aufruf von DynamoDBMapper.save() DynamoDBMappingException aus: T kann nicht in eine Klasse konvertiert werden. Hier

ist die UserMessage Klasse:

@DynamoDBTable(tableName="inbox") 
public class UserMessage<T> { 

    private String toId; 
    private T data; 

@DynamoDBAttribute(attributeName="data") 
public T getData() { 
    return data; 
} 
public void setData(T data) { 
    this.data = data; 
} 
@DynamoDBHashKey(attributeName="toId") 
public String getToId() { 
    return toId; 
} 
public void setToId(String to) { 
    this.toId = to; 
    } 
} 

Und der Code für Kontaktdaten:

@DynamoDBDocument 
public class ContactData { 

    private String firstname; 
    private String lastname; 
    private String email; 

@DynamoDBAttribute(attributeName = "firstname") 
public String getFirstname() { 
    return firstname; 
} 
public void setFirstname(String firstname) { 
    this.firstname = firstname; 
} 
@DynamoDBAttribute(attributeName = "lastname") 
public String getLastname() { 
    return lastname; 
} 
public void setLastname(String lastname) { 
    this.lastname = lastname; 
} 
@DynamoDBAttribute(attributeName = "email") 
public String getEmail() { 
    return email; 
} 
public void setEmail(String email) { 
    this.email = email; 
} 
} 

Der Controller Code dies einzurichten ist:

UserMessage<ContactData> message = new UserMessage<ContactData>(); 
ContactData cd = new ContactData(); 
cd.setEmail("[email protected]"); 
cd.setFirstname("Jane"); 
cd.setLastname("Smith"); 

message.setToId("[email protected]"); 
message.setData(cd) 
DynamoDB.getMapper().save(message); 

Ich bin ziemlich unerfahrene und generische Typen sind für mich brandneu, also hoffe ich, dass ich sie richtig benutze. Ich denke ich bin. Ich denke nur, dass DynamoDBMapper in diesem Fall nicht der richtigen Klasse zugeordnet werden kann. Danke Jeff

Antwort

0

Jedes Mal, wenn Sie eine nicht standardmäßige Attributklasse verwenden, müssen Sie einen Marshaller bereitstellen. Hier habe ich einen globalen Objekt-Marshaller verwendet, den Sie wahrscheinlich verwenden können, um nur JSON-ify alles, was Sie möchten.

Ich persönlich bevorzuge die Verwendung von statischen Typen, jeder mit einem definierten Marshaller kann ich über, aber ymmv.

public class GenericDBEntity<T> 
{ 
    .. 
    private T extra; 

    @DynamoDBAttribute 
    @DynamoDBMarshalling(marshallerClass=ObjectMarshaller.class) 
    public T getExtra() 
    { 
     return extra; 
    } 
    public void setExtra(T extra) 
    { 
     this.extra = extra; 
    } 

    public static class ObjectMarshaller implements DynamoDBMarshaller<Object> 
    { 
     @Override 
     public String marshall(Object getterReturnResult) 
     { 
      return getterReturnResult.toString(); 
     } 

     @Override 
     public Object unmarshall(Class<Object> clazz, String obj) 
     { 
      return obj; 
     } 
    } 
}