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
590 stars 373 forks source link

Add support for AWS SNS FIFO topics #762

Closed maciejwalkowiak closed 3 years ago

maciejwalkowiak commented 3 years ago

From spring-cloud-aws created by frjtrifork: spring-cloud/spring-cloud-aws#714

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

maciejwalkowiak commented 3 years ago

https://github.com/spring-cloud/spring-cloud-aws/issues/714#issuecomment-774345788

@frjtrifork:

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