elcharrua
elcharrua

Reputation: 1682

AWS JDK 2 create queue and subscribe to topic

I'm working on AWS with SNS / SQS, and i'm trying to create a SNS subscription on a SQS topic. I'm using AWS Java SDK 2. I can create the topics and the queues correctly, the problem i'm facing is im getting an error when creating the subscription between the topic and the queue. Below is the snippet of my code:

public SubscribeResponse subscribeQueue(String topicArn, String queueUrl){
    SubscribeRequest subscribeRequest = SubscribeRequest.builder()
            .topicArn(topicArn)
            .protocol("sqs")
            .endpoint(queueUrl)
            .returnSubscriptionArn(true).build();
    return getAmazonSNSClient().subscribe(subscribeRequest);
}

Below is the error i'm getting:

{ "message": "Internal Server Error: software.amazon.awssdk.services.sns.model.InvalidParameterException: Invalid parameter: SQS endpoint ARN (Service: Sns, Status Code: 400, Request ID: dabaeeb3-e77a-5873-861e-b8d0a7bf5c7f)" }

Can someone point me what i'm doing wrong?

Upvotes: 3

Views: 2866

Answers (1)

aksyuma
aksyuma

Reputation: 3180

With AWS Java SDK v1, you can subscribe SQS queue to an SNS topic using the method Topics.subscribeQueue where the endpoint object takes in queueUrl as shown below :

Topics.subscribeQueue(sns, sqs, myTopicARN, queueURL);

With AWS Java SDK v2, you can subscribe an SQS queue to an SNS topic using the method SunscribeRequest.builder where the endpoint object takes in queueArn.

Below is a sample java code snippet that I have tested to successfully subscribe an SQS queue to an SNS topic:

  public static void subscribeSQStoSNS(String queueUrl, String topicArn, SqsClient sqsClient, SnsClient snsClient) {


   /* with AWS Java SDK v1, you could subscribe an SQS queue to an SNS topic by
     * calling "Topics.subscribeQueue"()[1] where the endpoint object takes in queueUrl.
     * 
     * with AWS Java SDK v2, to subscribe an SQS queue to an SNS topic
     * one needs to use "SunscribeRequest.builder"() [2] where the endpoint object takes in queueArn.
     * 
     * [1] https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sns/util/Topics.html
     * [2] https://sdk.amazonaws.com/java/api/2.0.0-preview-11/software/amazon/awssdk/services/sns/model/SubscribeRequest.Builder.html
     *
     */

  // Step 1: We call "get-queue-attributes" API to retrieve the SQS queue Arn

  GetQueueAttributesRequest QueueAttributesRequest = GetQueueAttributesRequest.builder()
            .queueUrl(queueUrl)
            .attributeNamesWithStrings("All")
            .build();

   GetQueueAttributesResponse QueueAttributesResult = sqsClient.getQueueAttributes(QueueAttributesRequest);
    Map<String, String> sqsAttributeMap = QueueAttributesResult.attributesAsStrings();

  System.out.println("\n\n"+ QueueAttributesRequest);
    String queueArn = sqsAttributeMap.get("QueueArn");
    //System.out.println("\n\n"+ queueArn);


  // Step 2: We call "SubscribeRequest.builder" to subscribe the SQS queue to the SNS topic

   SubscribeRequest Qrequest = SubscribeRequest.builder()
            .protocol("sqs")
            .endpoint(queueArn)
            .returnSubscriptionArn(true)
            .topicArn(topicArn)
            .build();

   SubscribeResponse Qresponse = snsClient.subscribe(Qrequest);
    System.out.println("\n\nCreated Subscription ARN: " + Qresponse.subscriptionArn()+ " " + " and StatusCode : " + Qresponse.sdkHttpResponse().statusCode());}

Note:

1. The "Topics.subscribeQueue"() method automatically creates a policy for the subscription to allow the topic to send messages to the queue.

2. The "SunscribeRequest.builder"() method does not automatically add a policy for the subscription (i.e SQS queue) so as to allow the SNS topic to send messages to the queue. Therefore make sure you've given SNS topic permission to publish to the SQS queue by adding the following sample policy to the SQS queue as shown below and also as described here:

    {
      "Statement": [{
        "Effect":"Allow",
        "Principal":"*",
        "Action":"sqs:SendMessage",
        "Resource":"arn:aws:sqs:us-east-2:123456789012:MyQueue",
        "Condition":{
          "ArnEquals":{
            "aws:SourceArn":"arn:aws:sns:us-east-2:123456789012:MyTopic"
          }
        }
      }]
    }

You can find the complete code in github here : https://gist.github.com/syumaK/79c946ed4e618c1f871f50ecb1819a0f

Hope this helps.

Upvotes: 9

Related Questions