Code Monkey home page Code Monkey logo

spring-cloud-starter-dynamodb-v2's Introduction

spring-cloud-aws-starter-dynamodb

novo starter do spring cloud, provendo autoconfiguração do client do dynamodb de forma simples, abstração de métodos através de uma interface template para utilização nos services e facilidade de configuração na utilização do DAX no client do Dynamodb através de propriedades de configuração na aplicação.

sumário

  1. Standard autoconfiguração
    1. Autoconfiguração no client do DynamoDB
    2. Abstração dos métodos para operações no Dynamo
    3. Como utilizar
      1. Como declarar dependencia
      2. Modelagem da entidade
      3. Realizando operações no dynamodb
  2. Configuração de ambiente local👷
  3. Configurações com o acelerador DAX👷

solução starter-dynamodb

autoconfiguração no client do DynamoDB

Com o starter-dynamodb não há necessidade de declarar beans do DynamoDbClient e injetar em DynamoDbEnhancedClient para fazer a utilização dos métodos de tabela.

Forma manual de configurar o client com a sdk do dynamo v2:

   @Bean
    public DynamoDbClient  dynamoDbClient() {
            return DynamoDbClient.builder()
            .credentialsProvider(STATIC_CREDENTIALS)
            .endpointOverride(URI_LOCALSTACK)
            .region(Region.SA_EAST_1)
            .build();
            }
    
    @Bean
    public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient client) {
            return DynamoDbEnhancedClient.builder().dynamoDbClient(client).build();
            }

com o starter isso é feito de forma automática na classe de configuração DynamoDbAutoConfiguration

	@Conditional(MissingDaxUrlCondition.class)
	@Configuration(proxyBeanMethods = false)
	static class StandardDynamoDbClient {

		@ConditionalOnMissingBean
		@Bean
		public DynamoDbClient dynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer,
				ObjectProvider<AwsClientCustomizer<DynamoDbClientBuilder>> configurer, DynamoDbProperties properties) {
			return awsClientBuilderConfigurer
					.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable()).build();
		}

	}

	@ConditionalOnMissingBean
	@Bean
	public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
		return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build();
	}

	@ConditionalOnMissingBean(DynamoDbOperations.class)
	@Bean
	public DynamoDbTemplate dynamoDBTemplate(DynamoDbEnhancedClient dynamoDbEnhancedClient,
			Optional<DynamoDbTableSchemaResolver> tableSchemaResolver,
			Optional<DynamoDbTableNameResolver> tableNameResolver) {
		DynamoDbTableSchemaResolver tableSchemaRes = tableSchemaResolver
				.orElseGet(DefaultDynamoDbTableSchemaResolver::new);
		DynamoDbTableNameResolver tableNameRes = tableNameResolver.orElseGet(DefaultDynamoDbTableNameResolver::new);
		return new DynamoDbTemplate(dynamoDbEnhancedClient, tableSchemaRes, tableNameRes);
	}

Conta também com a propriedade spring.cloud.aws.dynamodb.endpoint para sobrescrever o endpoint do client, de forma fácil a utlização com LocalStack por exemplo.

Lista de propriedades do starter-dynamodb:

nome descrição valor default
spring.cloud.aws.dynamodb.enabled habilita a auto configuração true
spring.cloud.aws.dynamodb.endpoint configura o endpoint usado em DynamodB Client
spring.cloud.aws.dynamodb.region configura a region usado em DynamodB Client

Abstração dos métodos para operações no Dynamo

Através da interface DynamoDbOperationsé possível utilizar os métodos para utilizar os recursos do Dynamo para requisitar dados e atualizar dados, isso é possível por causa da auto configuração do client

Tabela dos métodos disponível através da interface:

Nome do método parametros descrição
save T entity salva uma entidade na tabbela do DynamoDB.
update T entity atualiza uma entidade na tabela do DynamoDB.
delete Key key, Class<?> clazz
OU
T entity
Deleta um record para a entidade recebida.
load Key key, Class clazz carrega a entidade com a perspectiva chave passada.
scanAll Class clazz realiza o scan de toda a tabela, incluindo seus items.
query QueryEnhancedRequest queryEnhancedRequest, Class clazz query o data da entidade personalizavél
scan ScanEnhancedRequest scanEnhancedRequest, Class clazz scan personalizavel para items ou expression

Os métodos injetam em DynamoDbTable através do método em todas as chamadas de forma unitária.

        private <T> DynamoDbTable<T> prepareTable(T entity) {
        String tableName = dynamoDbTableNameResolver.resolve(entity.getClass());
        return dynamoDbEnhancedClient.table(tableName,
        dynamoDbTableSchemaResolver.resolve(entity.getClass(), tableName));
        }
    
        private <T> DynamoDbTable<T> prepareTable(Class<T> clazz) {
        String tableName = dynamoDbTableNameResolver.resolve(clazz);
        return dynamoDbEnhancedClient
        .table(tableName, dynamoDbTableSchemaResolver.resolve(clazz, tableName));
        }

Como utilizar

Como declarar dependência

Exemplo de utilização standart sem a utilização do dax, primeiro adicione a dependência spring-cloud-aws-starter-dynamodb no pom ou gradle.

		<dependency>
			<groupId>io.awspring.cloud</groupId>
			<artifactId>spring-cloud-aws-starter-dynamodb</artifactId>
                        <version>3.0.0-RC1</version>
		</dependency>
implementation 'io.awspring.cloud:spring-cloud-aws-starter-dynamodb:3.0.0-RC1'

Modelagem da entidade

Para realizar as operações no banco do Dynamodb precisamos descrever o Bean da nossa entidade conforme abaixo.

@DynamoDbBean
public class Customer {
    private String id;
    private String name;
    private String age;

    public Customer(String name, String age) {
        this.id = UUID.randomUUID().toString();
        this.name = name;
        this.age = age;
    }

    @DynamoDbPartitionKey
    public String getId() {
        return id;
    }
    
    //getters and setters

NOTE: a entidade precisa estar anotada com @DynamodbBean. Visto que a auto configuração do TableSchema estar apontando para o um Bean.

WARNING: A autoconfiguração do client é incompativel com a seguinte anotação Dynamo, @DynamoDbImmutable.

Realizando operações no dynamodb

Utilizando o starter web do spring vamos realizar chamadas aos endpoint para testar a integração com o serviço do dynamodb através da localstack

@RestController
class CustomerController {
   private static final Logger LOGGER = LoggerFactory.getLogger(CustomerController.class);
   private final DynamoDbTemplate dynamoDbTemplate;

   CustomerController(DynamoDbTemplate dynamoDbTemplate) {
      this.dynamoDbTemplate = dynamoDbTemplate;
   }

   @GetMapping("/customers")
   List<Customer> customers() {
      return dynamoDbTemplate.scanAll(Customer.class).items().stream().toList();
   }

   @PostMapping("/customers")
   void create(@RequestBody CustomerDto customerDto) {
      LOGGER.info("Creating customer: {}", customerDto);
      dynamoDbTemplate.save(new Customer(customerDto.name(), customerDto.age()));
   }
   @GetMapping("register/{id}")
   Customer getById(@PathVariable String id){
      LOGGER.info("get customer by id: {}", id);
      return dynamoDbTemplate.load(Key.builder().partitionValue(id).build(), Customer.class);
   }
   @PutMapping
   void test(Customer w) {
      LOGGER.info("update customer: {}", w);
      dynamoDbTemplate.update(w);
   }

   @GetMapping("/{value}")
   List<Customer> scanByAttributeByContent(@RequestBody CustomerName customerName, @PathVariable String value) {
      return dynamoDbTemplate.scan(ScanEnhancedRequest.builder()
                      .filterExpression(Expression.builder()
                              .expression(value + " = :value")
                              .expressionValues(Map.of(":value", AttributeValue.builder()
                                      .s(customerName.name())
                                      .build()))
                              .build())
                      .build(), Customer.class)
              .items().stream().toList();
   }

   @GetMapping
   List<Customer> scanByAttributeByContent(@RequestBody Customer customer, @PathVariable String value) {
      return dynamoDbTemplate.query(QueryEnhancedRequest.builder()
              .filterExpression(Expression.builder()
                      .expression(value + ": value")
                      .expressionValues(Map.of(":value", AttributeValue.builder().s(customer.getAge()).build())).build())
              .queryConditional(QueryConditional.keyEqualTo(Key.builder()
                      .partitionValue(customer.getId())
                      .build()))
              .build(), Customer.class).items().stream().toList();
   }
}

Para criar um dado através do Dynamo

curl --location 'localhost:8080/customers' \
--header 'Content-Type: application/json' \
--data '{
    "nameCustomer": "teste-name",
    "age": "23"
}'

Para retornar todos os items cadastrados no Dynamodb

curl --location 'localhost:8080/customers'

exemplo de resposta:

[
    {
        "id": "01d4bda3-c305-436a-a27d-2b476488eff8",
        "name": "teste-name",
        "age": "23"
    }
]

Com esse ID podemos fazer uma requisição passando o ID para nos retornar a entidade

curl --location 'localhost:8080/register/{ID}'

exemplo de resposta:

{
   "id": "4bea4b53-e711-43d1-a23f-7b811d954180",
   "nameCustomer": "teste-name",
   "age": "23"
}

para retornar através dos campos

curl --location --request GET 'localhost:8080/nameCustomer' \
--header 'Content-Type: application/json' \
--data '{
    "nameCustomer": "teste-name"
}'

Exemplo de resposta

[
    {
        "id": "4bea4b53-e711-43d1-a23f-7b811d954180",
        "nameCustomer": "teste-name",
        "age": "23"
    }
]

Configuração de ambiente local

WORKING ...:construction_worker:

Configurações com o acelerador DAX

WORKING ...:construction_worker:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.