Work with S3 Event Notifications - AWS SDK for Java 2.x

Work with S3 Event Notifications

To help you monitor activity in your buckets, Amazon S3 can send notifications when certain events happen. The Amazon S3 User Guide provides information on the notifications that a bucket can send out.

You can set up a bucket to send events to four possible destinations using the SDK for Java:

  • Amazon Simple Notification Service topics

  • Amazon Simple Queue Service queues

  • AWS Lambda functions

  • Amazon EventBridge

When you setup up a bucket to send events to EventBridge, you have the ability to configure an EventBridge rule to fanout the same event to multiple destinations. When you configure your bucket to send directly to one of the first three destinations, only one destination type can be specified for each event.

In the next section, you'll see how to configure a bucket using the SDK for Java to send S3 Event Notifications in two ways: directly to an Amazon SQS queue and to EventBridge.

The last section shows you how to use the S3 Event Notifications API to work with notifications in an object-oriented way.

Configure a bucket to send directly to a destination

The following example configures a bucket to send notifications when object create events or object tagging events occur against a 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) ); }

The code shown above sets up one queue to receive two types of events. Conveniently, the queueConfigurations method allows you to set multiple queue destinations if needed. Also, in the notificationConfiguration method you can set additional destinations, such as one or more Amazon SNS topics or one or more Lambda functions. The following snippet shows an example with two queues and three types of destinations.

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) );

The Code Examples GitHub repository contains the complete example to send S3 event notifications directly to a queue.

Configure a bucket to send to EventBridge

The following example configures a bucket to send notifications to 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());

When you configure a bucket to send events to EventBridge, you simply indicate the EventBridge destination, not the types of events nor the ultimate destination that EventBridge will dispatch to. You configure the ultimate targets and event types by using the Java SDK's EventBridge client.

The following code shows how to configure EventBridge to fan out object created events to a topic and a queue.

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; }

To work with EventBridge in your Java code, add a dependency on the eventbridge artifact to your Maven pom.xml file.

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

The Code Examples GitHub repository contains the complete example to send S3 event notifications to EventBridge and then to a topic and queue.

Use the S3 Event Notifications API to process events

After a destination receives S3 notification events, you can process them in an object-oriented way by using the S3 Event Notifications API. You can use the S3 Event Notifications API to work with event notifications that are dispatched directly to a target (as shown in the first example), but not with notifications routed through EventBridge. S3 event notifications sent by buckets to EventBridge contain a different structure that the S3 Event Notifications API does not currently handle.

Add dependency

The S3 Event Notifications API was released with version 2.25.11 of the SDK for Java 2.x.

To use the S3 Event Notifications API, add the required dependency element to your Maven pom.xml as shown in the following snippet.

<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 Latest version.

Use the S3EventNotification class

Create an S3EventNotification instance from a JSON string

To convert a JSON string into an S3EventNotification object, use the static methods of the S3EventNotification class as shown in the following example.

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(); } }

In this example, the fromJson method converts the JSON string into an S3EventNotification object. Missing fields in the JSON string will result in null values in the corresponding Java object fields and any extra fields in the JSON will be ignored.

Other APIs for an event notification record can be found in API reference for S3EventNotificationRecord.

Convert an S3EventNotification instance to a JSON string

Use the toJson (or toJsonPretty) method to convert an S3EventNotification object into a JSON string as shown in the following example.

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); } }

Fields for GlacierEventData, ReplicationEventData, IntelligentTieringEventData, and LifecycleEventData are excluded from the JSON if they are null. Other null fields will be serialized as null.

The following shows example output of the toJsonPretty method for an S3 object tagging event.

{ "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" : "DOC-EXAMPLE-BUCKET", "ownerIdentity" : { "principalId" : "XXXXXXXXXXX" }, "arn" : "arn:aws:s3:::XXXXXXXXXX" }, "object" : { "key" : "akey", "size" : null, "eTag" : "XXXXXXXXXX", "versionId" : null, "sequencer" : null } } } ] }

A complete example is available in GitHub that shows how to use the API to work with notifications received by an Amazon SQS queue.