spring-attic / spring-cloud-aws

All development has moved to https://github.com/awspring/spring-cloud-aws Integration for Amazon Web Services APIs with Spring
https://awspring.io/
Apache License 2.0
589 stars 376 forks source link

Add support for AWS SNS FIFO topics #714

Closed frjtrifork closed 3 years ago

frjtrifork commented 3 years ago

On 22 October AWS released FIFO enabled SNS Topics. These have some requirements regarding extra fields that has to be sent in the PublishRequest. I believe 1.11.892 version of aws-sdk is required to have the new properties available in the PublishRequest.

If the SNS Topic has ContentBasedDeduplication property set to false, a unique DeduplicationId must be set in each request.

If the ContentBasedDeduplication is set to true, a deduplication hash is calculated and sent automatically by the aws-sdk - so no need for the request to contain a deduplication id.

All publish requests to a FIFO topic must contain a MessageGroupId value.

Describe the solution you'd like It would be great if support for FIFO Topics could be added to spring-cloud in the NotificationMessagingTemplate

Links: https://docs.aws.amazon.com/sns/latest/dg/fifo-example-use-case.html https://docs.aws.amazon.com/sns/latest/dg/fifo-topic-code-examples.html https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sns/model/PublishRequest.html

alexharvey commented 3 years ago

Hi, any updates on when spring-cloud-aws will support FIFO for SNS topics? I've noticed that even the AWS SDK dependency for 2.2.5.RELEASE doesn't have support for MessageGroupId if I wanted to just code directly to the SDK within my Spring Boot service. Thanks!

frjtrifork commented 3 years ago

I made this simple workaround (Note it requires your SNS FIFO topics to have a name ending with .fifo - like the SQS fifo queues must) - it also requires you to use aws-java-sdk 1.11.892 or later in your dependency list - since https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-aws-dependencies/2.2.5.RELEASE is pointing to the older 1.11.792 that does not contain the new fields in PublishRequest.

Note: Our topics have ContentBasedDeduplication set to true, so deduplicationIds are created automatically. If your FIFO topics have ContentBasedDeduplication=false, you need to provide a deduplicationId per message - and will have to modify this example.

import com.amazonaws.AmazonWebServiceRequest;
import com.amazonaws.handlers.RequestHandler2;
import com.amazonaws.services.sns.model.PublishRequest;

public class SnsFifoMessageGroupIdHandler extends RequestHandler2 {

    @Override
    public AmazonWebServiceRequest beforeExecution(AmazonWebServiceRequest request) {
        AmazonWebServiceRequest amazonWebServiceRequest = super.beforeExecution(request);
        if (amazonWebServiceRequest instanceof PublishRequest) {
            PublishRequest publishRequest = (PublishRequest) amazonWebServiceRequest;
            if (publishRequest.getTopicArn().contains(".fifo")) {
                publishRequest.setMessageGroupId(publishRequest.getTopicArn());
            }
        }
        return amazonWebServiceRequest;
    }

}

Make it into a Spring bean somewhere in your configuration

    @Bean
    public SnsFifoMessageGroupIdHandler messageGroupIdRequestHandler() {
        return new SnsFifoMessageGroupIdHandler();
    }

And use it for constructing the AmazonSnsAsync bean instance

    @Bean
    public AmazonSNSAsync amazonSNS(SnsFifoMessageGroupIdHandler snsFifoMessageGroupIdHandler) {
        AmazonSNSAsyncClientBuilder amazonSNSAsyncClientBuilder = AmazonSNSAsyncClientBuilder
                .standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials()))
                .withRegion(awsRegion)
                .withRequestHandlers(snsFifoMessageGroupIdHandler)
        return amazonSNSAsyncClientBuilder.build();
    }

Then Spring will use it for AmazonSNSAsync dependencies automatically and use it in org.springframework.cloud.aws.messaging.config.annotation.SnsWebConfiguration#snsWebMvcConfigurer

Or you can create a NotificationTemplate yourself e.g.

    @Bean
    public NotificationMessagingTemplate notificationMessagingTemplate(AmazonSNS amazonSNS) {
        return new NotificationMessagingTemplate(amazonSNS);
    }
maciejwalkowiak commented 3 years ago

Replaced by https://github.com/awspring/spring-cloud-aws/issues/41