Trabalhar com Notificações de Eventos do S3 - AWS SDK for Java 2.x

Trabalhar com Notificações de Eventos do S3

Para ajudar você a monitorar a atividade nos buckets, o Amazon S3 pode enviar notificações quando determinados eventos acontecem. O Guia do usuário do Amazon S3 fornece informações sobre as notificações que um bucket pode enviar.

É possível configurar um bucket para enviar eventos a quatro destinos possíveis usando o SDK para Java:

  • Tópicos do Amazon Simple Notification Service

  • Filas do Amazon Simple Queue Service

  • Funções do AWS Lambda

  • Amazon EventBridge

Ao configurar um bucket para enviar eventos ao EventBridge, você pode configurar uma regra do EventBridge para fazer fanout do mesmo evento a vários destinos. Ao configurar o bucket para enviar diretamente a um dos três primeiros destinos, somente um tipo de destino pode ser especificado para cada evento.

Na próxima seção, você verá como configurar um bucket usando o SDK para Java a fim de enviar Notificações de Eventos do S3 de duas maneiras: diretamente para uma fila do Amazon SQS e para o EventBridge.

A última seção mostra como usar a API de Notificações de Eventos do S3 para trabalhar com notificações de uma forma orientada a objetos.

Configurar um bucket para enviar diretamente a um destino

O exemplo a seguir configura um bucket para enviar notificações quando eventos de criação de objetos ou eventos de marcação de objetos ocorrem em um bucket.

static void processS3Events(String bucketName, String queueArn) { // Configure the bucket to send Object Created and Object Tagging notifications to an existing SQS queue. s3Client.putBucketNotificationConfiguration(b -> b .notificationConfiguration(ncb -> ncb .queueConfigurations(qcb -> qcb .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING) .queueArn(queueArn))) .bucket(bucketName) ); }

O código mostrado acima configura uma fila para receber dois tipos de eventos. Convenientemente, o método queueConfigurations permite que você defina vários destinos de fila, se necessário. Além disso, no método notificationConfiguration, você pode definir destinos adicionais, como um ou mais tópicos do Amazon SNS ou uma ou mais funções do Lambda. O trecho a seguir mostra um exemplo com duas filas e três tipos de destinos.

s3Client.putBucketNotificationConfiguration(b -> b .notificationConfiguration(ncb -> ncb .queueConfigurations(qcb -> qcb .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING) .queueArn(queueArn), qcb2 -> qcb2.<...>) .topicConfigurations(tcb -> tcb.<...>) .lambdaFunctionConfigurations(lfcb -> lfcb.<...>)) .bucket(bucketName) );

O repositório GitHub de exemplos de código contém o exemplo completo para enviar notificações de eventos do S3 diretamente para uma fila.

Configurar um bucket para enviar ao EventBridge

O exemplo a seguir configura um bucket para enviar notificações ao EventBridge.

public static String setBucketNotificationToEventBridge(String bucketName) { // Enable bucket to emit S3 Event notifications to EventBridge. s3Client.putBucketNotificationConfiguration(b -> b .bucket(bucketName) .notificationConfiguration(b1 -> b1 .eventBridgeConfiguration(SdkBuilder::build)) .build());

Ao configurar um bucket para enviar eventos ao EventBridge, basta indicar o destino do EventBridge, não os tipos de eventos nem o destino final para o qual o EventBridge enviará. Você configura os destinos e os tipos de eventos finais usando o cliente EventBridge do Java SDK.

O código a seguir mostra como configurar o EventBridge para distribuir eventos criados por objetos para um tópico e uma fila.

public static String configureEventBridge(String topicArn, String queueArn) { try { // Create an EventBridge rule to route Object Created notifications. PutRuleRequest putRuleRequest = PutRuleRequest.builder() .name(RULE_NAME) .eventPattern(""" { "source": ["aws.s3"], "detail-type": ["Object Created"], "detail": { "bucket": { "name": ["%s"] } } } """.formatted(bucketName)) .build(); // Add the rule to the default event bus. PutRuleResponse putRuleResponse = eventBridgeClient.putRule(putRuleRequest) .whenComplete((r, t) -> { if (t != null) { logger.error("Error creating event bus rule: " + t.getMessage(), t); throw new RuntimeException(t.getCause().getMessage(), t); } logger.info("Event bus rule creation request sent successfully. ARN is: {}", r.ruleArn()); }).join(); // Add the existing SNS topic and SQS queue as targets to the rule. eventBridgeClient.putTargets(b -> b .eventBusName("default") .rule(RULE_NAME) .targets(List.of ( Target.builder() .arn(queueArn) .id("Queue") .build(), Target.builder() .arn(topicArn) .id("Topic") .build()) ) ).join(); return putRuleResponse.ruleArn(); } catch (S3Exception e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } return null; }

Para trabalhar com o EventBridge em seu código Java, adicione uma dependência no artefato eventbridge ao arquivo pom.xml do Maven.

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>eventbridge</artifactId> </dependency>

O repositório GitHub de exemplos de código contém o exemplo completo para enviar notificações de eventos do S3 ao EventBridge e, então, a um tópico e uma fila.

Usar a API de Notificações de Eventos do S3 para processar eventos

Depois que um destino recebe eventos de notificação do S3, você pode processá-los de forma orientada a objetos usando a API de Notificações de Eventos do S3. É possível usar a API de Notificações de Eventos do S3 para trabalhar com notificações de eventos que são enviadas diretamente a um destino (conforme mostrado no primeiro exemplo), mas não com notificações roteadas pelo EventBridge. As notificações de eventos do S3 enviadas por buckets para o EventBridge contêm uma estrutura diferente que a API de Notificações de Eventos do S3 não processa atualmente.

Adicionar dependência

A API de Notificações de Eventos do S3 foi lançada com a versão 2.25.11 do SDK para Java 2.x.

Para usar a API de Notificações de Eventos do S3, adicione o elemento de dependência necessário ao pom.xml do Maven, conforme mostrado no trecho a seguir.

<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.X.X1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-event-notifications</artifactId> </dependency> </dependencies>

1 Versão mais recente.

Usar a classe S3EventNotification

Criar uma instância do S3EventNotification com base em uma string JSON

Para converter uma string JSON em um objeto S3EventNotification, use os métodos estáticos da classe S3EventNotification, conforme mostrado no exemplo a seguir.

import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord import software.amazon.awssdk.services.sqs.model.Message; public class S3EventNotificationExample { ... void receiveMessage(Message message) { // Message received from SQSClient. String sqsEventBody = message.body(); S3EventNotification s3EventNotification = S3EventNotification.fromJson(sqsEventBody); // Use getRecords() to access all the records in the notification. List<S3EventNotificationRecord> records = s3EventNotification.getRecords(); S3EventNotificationRecord record = records.stream().findFirst(); // Use getters on the record to access individual attributes. String awsRegion = record.getAwsRegion(); String eventName = record.getEventName(); String eventSource = record.getEventSource(); } }

Neste exemplo, o método fromJson converte a string JSON em um objeto S3EventNotification. Os campos ausentes na string JSON resultarão em valores null nos campos do objeto Java correspondentes e os campos extras no JSON serão ignorados.

Outras APIs para um registro de notificação de eventos podem ser encontradas na referência da API para S3EventNotificationRecord.

Converter uma instância S3EventNotification em uma string JSON

Use o método toJson (ou toJsonPretty) para converter um objeto S3EventNotification em uma string JSON, conforme mostrado no exemplo a seguir.

import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification public class S3EventNotificationExample { ... void toJsonString(S3EventNotification event) { String json = event.toJson(); String jsonPretty = event.toJsonPretty(); System.out.println("JSON: " + json); System.out.println("Pretty JSON: " + jsonPretty); } }

Os campos para GlacierEventData, ReplicationEventData, IntelligentTieringEventData e LifecycleEventData serão excluídos do JSON se forem null. Outros campos null serão serializados como null.

Veja a seguir um exemplo de saída do método toJsonPretty para um evento de marcação de objetos do S3.

{ "Records" : [ { "eventVersion" : "2.3", "eventSource" : "aws:s3", "awsRegion" : "us-east-1", "eventTime" : "2024-07-19T20:09:18.551Z", "eventName" : "ObjectTagging:Put", "userIdentity" : { "principalId" : "AWS:XXXXXXXXXXX" }, "requestParameters" : { "sourceIPAddress" : "XXX.XX.XX.XX" }, "responseElements" : { "x-amz-request-id" : "XXXXXXXXXXXX", "x-amz-id-2" : "XXXXXXXXXXXXX" }, "s3" : { "s3SchemaVersion" : "1.0", "configurationId" : "XXXXXXXXXXXXX", "bucket" : { "name" : "amzn-s3-demo-bucket", "ownerIdentity" : { "principalId" : "XXXXXXXXXXX" }, "arn" : "arn:aws:s3:::XXXXXXXXXX" }, "object" : { "key" : "akey", "size" : null, "eTag" : "XXXXXXXXXX", "versionId" : null, "sequencer" : null } } } ] }

Um exemplo completo está disponível no GitHub que mostra como usar a API para trabalhar com notificações recebidas por uma fila do Amazon SQS.

Processar eventos do S3 no Lambda com bibliotecas Java: AWS SDK for Java 2.x e aws-lambda-java-events

Em vez de usar o SDK para Java 2.x para processar notificações de eventos do Amazon S3 em uma função do Lambda, você pode usar a biblioteca aws-lambda-java-events na versão 3.x.x. A AWS mantém a biblioteca aws-lambda-java-events de forma independente e tem seus próprios requisitos de dependência. A biblioteca aws-lambda-java-events funciona somente com eventos do S3 nas funções do Lambda, enquanto o SDK para Java 2.x funciona com eventos do S3 nas funções do Lambda, Amazon SNS e Amazon SQS.

Ambas as abordagens modelam a carga útil de notificação de eventos JSON de forma orientada a objetos com APIs semelhantes. A tabela a seguir mostra as diferenças notáveis entre o uso das duas abordagens.

AWS SDK para Java biblioteca aws-lambda-java-events
Nomeação do pacote

software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification

com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification
RequestHandlerParâmetro

Escreva a implementação RequestHandler da função do Lambda para receber uma string JSON:

import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification; public class Handler implements RequestHandler<String, String> { @Override public String handleRequest(String jsonS3Event, Context context) { S3EventNotification s3Event = S3EventNotification .fromJson(jsonS3Event); // Work with the s3Event object. ... } }
Escreva a implementação RequestHandler da função do Lambda para receber um objeto S3Event:
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; public class Handler implements RequestHandler<S3Event, String> { @Override public String handleRequest(S3Event s3event, Context context) { // Work with the s3Event object. ... } }
Dependências do Maven
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.X.X</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-event-notifications</artifactId> </dependency> <!-- Add other SDK dependencies that you need. --> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.X.X</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- The following two dependencies are for the aws-lambda-java-events library. --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> <version>3.15.0</version> </dependency> <!-- Add other SDK dependencies that you need. --> </dependencies>