Je les trois applications suivantes:
Projet 1 détient
- La logique métier (fonction Cloud Spring)
- Une interface IDemoEntity
projet 2
- gestionnaire AWS-spécifique
- Une mise en œuvre de IDemoEntity , avec des annotations spécifiques DynamoDB
- Le projet est basé sur Spring Boot
projet 3
- Une mise en œuvre de IDemoEntity , avec l' annotation CosmosDB
- Azure spécifique gestionnaire
Les classes de projet 1 ressemblent à ceci:
public interface IDemoEntity {
String getName();
void setName(String name);
}
@Component
public class StoreFunction implements Consumer<Message<IDemoEntity>> {
@Override
public void accept(Message<IDemoEntity> t) {
System.out.println("Stored entity " + t.getPayload().getName());
return;
}
}
Pour le projet 2, la mise en œuvre de IDemoEntity ressemble à ceci:
@DynamoDBTable(tableName = "DemoEntity")
public class DynamoDemoEntity implements IDemoEntity {
private String name;
@Override
@DynamoDBHashKey
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}
Pour le projet 3, la mise en œuvre de IDemoEntity ressemblerait à DynamoDemoEntity , mais avec annotations CosmosDB.
La structure peut sembler un peu compliqué, mais l'idée est la suivante:
- Mettre en œuvre la logique métier et le modèle de données une seule fois (dans le projet 1) (tirant parti de fonction Cloud Spring)
- Mettre en œuvre tout un projet d'emballage pour chaque plate-forme (je commence avec AWS Lambda dans le projet 2, mais le projet 3 pour Azure serait similaire), ainsi que des choses spécifiques de la plate-forme (comme la mise en œuvre de l'entité, qui a besoin d'annotations DB spécifiques)
- Compiler le projet spécifique à la plate-forme (par exemple 2 pour projeter AWS Lambda) avec le projet comme une dépendance
Je l'ai essayé, et la configuration fonctionne essentiellement. Cependant, il y a un gros problème:
Lorsque vous appelez le StoreFunction ci - dessus, Jackson lance l'exception suivante:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `de.margul.awstutorials.springcloudfunction.logic.IDemoEntity` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (String)"{"name": "Detlef"}"; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
at de.margul.awstutorials.springcloudfunction.aws.handler.RestSpringBootApiGatewayRequestHandler.deserializeBody(RestSpringBootApiGatewayRequestHandler.java:57)
... 3 more
Cela a du sens, parce que Jackson ne sait pas, auquel la mise en œuvre si IDemoEntity
elle désérialiser le JSON reçu.
La façon la plus facile maintenant serait de placer un @JsonDeserialize(as = DynamoDemoEntity.class)
sur IDemoEntity
.
Toutefois, cela briserait ma structure complète: Projet 1 aura aucune information, quel projet spécifique à la plate-forme, il est compilé avec.
Toutes les idées, la façon dont je pourrais fournir un sérialiseur personnalisé (par exemple le haricot printemps), mais sans modifications spécifiques de la plate-forme dans le projet 1?
, Vous devez d' abord créer votre commande DynamoDemoEntityDeserializer
comme ci - dessous:
class DynamoDemoEntityDeserializer extends JsonDeserializer<DynamoDemoEntity> {
@Override
public DynamoDemoEntity deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
// return DynamoDemoEntity instance;
}
}
Ensuite , vous pouvez créer des haricots com.fasterxml.jackson.databind.Module
comme ci - dessous:
@Bean
public Module dynamoDemoEntityDeserializer() {
SimpleModule module = new SimpleModule();
module.addDeserializer(IDemoEntity.class, new DynamoDemoEntityDeserializer());
return module;
}
Tous les haricots de type com.fasterxml.jackson.databind.Module sont automatiquement enregistrés avec le Jackson2ObjectMapperBuilder configuré automatiquement et sont appliqués à toutes les instances ObjectMapper qu'il crée. Cela fournit un mécanisme global pour contribuer modules personnalisés lorsque vous ajoutez de nouvelles fonctionnalités à votre application.