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