It's been a surprise for me to see that handle event sources is something handcrafty...
I mean, I've been strugling for some days to try to receive ("deserialize") an S3Put event into my handler (using spring-cloud-function-aws-adapter Consumer).
Currently, I'm using an S3(send put event) -> SQS(send SQSMessage) -> lambda(receive SQSMessage).
My current code Lambda function (handler) is:
@Component
@RequiredArgsConstructor
@Slf4j
public class PushedDocumentLambdaConsumer implements Function<SQSEvent, String> {
@Override
public String apply(SQSEvent sqsEvent) {
log.info("Found " + sqsEvent.getRecords().size() + " sqs event(s)");
for (SQSEvent.SQSMessage sqsMessage : sqsEvent.getRecords()) {
log.info("sqs message body: {}", sqsMessage.getBody());
final String body = sqsMessage.getBody().replace("Records", "records");
log.info("Replaced sqs message body: {}", body);
Gson gson = new Gson();
S3Event s3Event = gson.fromJson(sqsMessage.getBody(), S3Event.class);
log.info("s3Event.toString(): {}", s3Event.toString());
if (s3Event != null && s3Event.getRecords() != null) {
log.info("Number of records: {}", s3Event.getRecords().size());
for (S3EventNotificationRecord s3EventNotificationRecord : s3Event.getRecords()) {
log.info("event name: {}", s3EventNotificationRecord.getEventName());
log.info("event source: {}", s3EventNotificationRecord.getEventSource());
S3Entity s3Entity = s3EventNotificationRecord.getS3();
if (null != s3Entity) {
log.info("s3Entity bucket name: {}", s3Entity.getBucket().getName());
log.info("s3Entity object name: {}", s3Entity.getObject().getKey());
}
}
}
}
return "Ok";
}
}
What I'm currently receiving is:
{
"Records":[
{
"body":"{\"Records\": [{\"eventVersion\": \"2.1\", \"eventSource\": \"aws:s3\", \"awsRegion\": \"us-east-1\", \"eventTime\": \"2024-03-01T12:54:12.608Z\", \"eventName\": \"ObjectCreated:Put\", \"userIdentity\": {\"principalId\": \"AIDAJDPLRKLG7UEXAMPLE\"}, \"requestParameters\": {\"sourceIPAddress\": \"127.0.0.1\"}, \"responseElements\": {\"x-amz-request-id\": \"b0c98e62\", \"x-amz-id-2\": \"eftixk72aD6Ap51TnqcoF8eFidJG9Z/2\"}, \"s3\": {\"s3SchemaVersion\": \"1.0\", \"configurationId\": \"abdde1c9\", \"bucket\": {\"name\": \"espaidoc\", \"ownerIdentity\": {\"principalId\": \"A3NL1KOZZKExample\"}, \"arn\": \"arn:aws:s3:::espaidoc\"}, \"object\": {\"key\": \"580d1374-2ec1-4bb3-8c14-2c43d07c7833\", \"sequencer\": \"0055AED6DCD90281E5\", \"size\": 2333, \"eTag\": \"1d11469e9d81f07729548d7708bbab82\"}}}]}",
"receiptHandle":"ZGJhNTJjNDItODU1Yy00ZjY2LWI4MmUtY2RmNDRhNzg5YTRkIGFybjphd3M6c3FzOnVzLWVhc3QtMTowMDAwMDAwMDAwMDA6U3FzUXVldWVDcmVhdGUgMmI1YjY3OTctMjY0Yy00NTVlLTgyNzMtZDIwMDlkYWVhZDliIDE3MDkyOTc2NTMuNDg2MTU4",
"md5OfBody":"2bb9d9a1a018099143bd02c0aea8b0cd",
"eventSourceARN":"arn:aws:sqs:us-east-1:000000000000:SqsQueueCreate",
"eventSource":"aws:sqs",
"awsRegion":"us-east-1",
"messageId":"2b5b6797-264c-455e-8273-d2009daead9b",
"attributes":{
"SenderId":"000000000000",
"SentTimestamp":"1709297652665",
"ApproximateReceiveCount":"1",
"ApproximateFirstReceiveTimestamp":"1709297653486"
},
"messageAttributes":{
}
}
]
}
As you can see, I'm trying to deserialize body to an S3Event using Gson, but I've realized that it gets me an S3Event without Records...
- Is not there any library engaging for this parsing issues?
- How could I parse it "manually"?
I believe the problem is you're trying to use gson to parse the SQS message into an
S3Event, when it is actually anS3EventNotification. It looks like you might not even have to parse it with gson, you could do this: