Aws java: анализ события S3Put, поступающего из SQS, в лямбда

Для меня было сюрпризом увидеть, что обработка источников событий — это что-то хитроумное...

Я имею в виду, что в течение нескольких дней я изо всех сил пытался получить («десериализовать») событие S3Put в свой обработчик (используя Spring-cloud-function-aws-adapter Consumer).

Сейчас я использую S3(send put event) -> SQS(send SQSMessage) -> lambda(receive SQSMessage).

Моя текущая функция Lambda кода (обработчик):

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

}

В настоящее время я получаю:

{
   "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":{
            
         }
      }
   ]
}

Как вы можете видеть, я пытаюсь десериализовать тело в S3Event, используя Gson, но понял, что мне получается S3Event без записей...

  1. Нет ли какой-либо библиотеки, занимающейся решением этих проблем синтаксического анализа?
  2. Как я мог разобрать его «вручную»?

Тело JSON, которое вы показали, содержит массив Records. Вы хотите сказать, что десериализованный s3Event в вашем коде имеет нулевой атрибут Records или пустое/нулевое возвращаемое значение при вызове метода доступа getRecords()? Также смотрите этот вопрос.

jarmod 01.03.2024 21:20
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
201
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я считаю, что проблема в том, что вы пытаетесь использовать gson для анализа сообщения SQS в S3Event, хотя на самом деле это S3EventNotification. Похоже, вам даже не придется анализировать его с помощью gson, вы можете сделать это:

S3EventNotification s3EventNotification = S3EventNotification.parse(sqsMessage.getBody());
for (S3EventNotification.S3EventNotificationRecord record : s3EventNotification.getRecords())
{
    S3EventNotification.S3Entity s3Entity = record.getS3();
    if (null != s3Entity)
    {
        log.info("s3Entity bucket name: {}", s3Entity.getBucket().getName());
        log.info("s3Entity object name: {}", s3Entity.getObject().getKey());
    }
}

Другие вопросы по теме