У меня есть три следующих приложения:
Проект 1 содержит
- Бизнес-логика (функция Spring Cloud)
- Интерфейс IDemoEntity
Проект 2
- Обработчик, специфичный для AWS
- Одна реализация IDemoEntity , с аннотациями для DynamoDB
- Проект основан на Spring Boot
Проект 3
- Одна реализация IDemoEntity , с аннотацией CosmosDB
- Обработчик, специфичный для Azure
Классы проекта 1 выглядят так:
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;
}
}
Для проекта2, реализация IDemoEntity выглядит следующим образом:
@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;
}
}
Для проекта 3 реализация IDemoEntity будет выглядеть аналогично DynamoDemoEntity , но с аннотациями CosmosDB.
Структура может показаться немного сложной, но идея заключается в следующем:
- Один раз реализовать бизнес-логику и модель данных (в проекте 1) (используя функцию Spring Cloud)
- Реализовать только проект-оболочку для каждой платформы (я начинаю с AWS Lambda в проекте 2, но в проекте 3).для Azure будет выглядеть аналогично), а также вещи, специфичные для платформы (например, реализация сущности, для которой нужны аннотации, специфичные для БД)
- Скомпилируйте проект, специфичный для платформы (например, проект 2 для AWS Lambda) с проектом 1 какЗависимость
Я пробовал, и установка работает в основном.Однако есть одна большая проблема:
При вызове StoreFunction выше, Джексон выдает следующее исключение:
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
Это имеет смысл, потому что Джексон не знает, к реализации которого, если IDemoEntity
будет десериализовать полученный JSON.
Самый простой способ сейчас будет заключаться в том, чтобы поместить @JsonDeserialize(as = DynamoDemoEntity.class)
в IDemoEntity
.
Однако это сломало бы мойПолная структура: у Проекта 1 не должно быть никакой информации, с каким платформенным проектом он компилируется.
Любые идеи, как я мог бы предоставить собственный десериализатор (например, как Spring bean), но без внесения модификаций для платформыв проекте 1?