4

I am trying to access an amazon queue using java sdk. The queue is set in an environment with EC2 instance roles so I do not need to use credentials to access it. Here is my code

public AWSSimpleQueueServiceClient(String queueName, String endPoint) {
    try{
        this.queueName = queueName;
        logger.debug("Queue Name = " + this.queueName + "Endpoint = " + endPoint);
        this.sqs = new AmazonSQSClient(new InstanceProfileCredentialsProvider());
        if(endPoint != null) {
            this.sqs.setEndpoint(endPoint);
        }
    } catch (Exception e) {
        logger.error("Exception while creating AWS SQS Client = " + e.getMessage());
    }
}

QueueName and Endpoint are got from configuration files. I try to send/receive messages from the queue but it gives me the following exception

Exception in thread "main" com.amazonaws.services.sqs.model.QueueDoesNotExistException: The specified queue does not exist or you do not have access to it. (Service: AmazonSQS; Status Code: 400; Error Code: AWS.SimpleQueueService.NonExistentQueue; Request ID: c30b2c9a-0e62-560d-9306-628ebff676d8)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1160)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:748)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:467)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:302)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2422)
at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.java:541)
at com.ensighten.inform.sqsClient.AWSSimpleQueueServiceClient.getQueueUrl(AWSSimpleQueueServiceClient.java:66)

However, when I try to access the queue using the curl command, I get a response

aws sqs receive-message --queue-url <Endpoint>/031143137427/<QueueName> --    region us-east-1
 {
    "Messages": [
        {
            "Body": "Test", 
            "ReceiptHandle":     "AQEBA49LjMDLPyyl4QKwHx9/oVFDV7mZDiOOpdKS/IC2zR3GNblg2IoHuqWBgr5iw7URCkL03Dm23TCs0Z2hB2DIzU+9qxZTOa9Ti57eiHOyAL2XAlbk7TAqGCR4lcsdSW8+LJ5zWCTkBUg5iZOqy4P0KFTfI7KtJJb2aAmeWJpApu+yJRTNAkYtdN91EcYOVFHqc1p6HJmtvvW6vJwfHB5JEbagXdfWwH3/UnJ/O36JwuFoLDp/NBRu6TO+bmYxeZmCN4GdhHuT0a11weki6Ez47Ln63G11LeQ4SFdZTC7QOWflypf8FSbG8W4JGGPZ8J8iWTkW7PGGw6DRavSu97rx3w==", 
            "MD5OfBody": "1f871ceacd9f4028ed371e91400efe80", 
            "MessageId": "0f6290d2-4554-4d96-8f93-7564ef667feb"
        }
    ]
}

This is an exception that I get when I try it on another machine setup with EC2 roles.

Exception in thread "main" com.amazonaws.AmazonClientException: Unable to load credentials from Amazon EC2 metadata service
at com.amazonaws.auth.InstanceProfileCredentialsProvider.handleError(InstanceProfileCredentialsProvider.java:244)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.loadCredentials(InstanceProfileCredentialsProvider.java:225)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.getCredentials(InstanceProfileCredentialsProvider.java:124)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2413)
at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.java:541)
at com.ensighten.inform.sqsClient.AWSSimpleQueueServiceClient.getQueueUrl(AWSSimpleQueueServiceClient.java:74)
at com.ensighten.inform.sqsClient.AWSSimpleQueueServiceClient.getMessagesFromQueue(AWSSimpleQueueServiceClient.java:93)
at com.ensighten.inform.jobRunner.TestJobRunner.execute(TestJobRunner.java:96)
at com.ensighten.inform.jobRunner.TestJobRunner.main(TestJobRunner.java:90)
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at   java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:211)
at sun.net.www.http.HttpClient.New(HttpClient.java:308)
at sun.net.www.http.HttpClient.New(HttpClient.java:326)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:996)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:932)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:850)
at com.amazonaws.internal.EC2MetadataClient.readResource(EC2MetadataClient.java:90)
at com.amazonaws.internal.EC2MetadataClient.getDefaultCredentials(EC2MetadataClient.java:55)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.loadCredentials(InstanceProfileCredentialsProvider.java:186)
... 7 more

This is how I get the URL of the queue. Tried doing it two ways below. It errors out with the above exception

public String getQueueUrl() {
    GetQueueUrlRequest queueUrlRequest = new GetQueueUrlRequest(this.queueName);
    logger.debug("Queue Name... = " + this.queueName);
    //FIRST WAY -----------> EXCEPTION on the line below
    System.out.println("Queue URL .....= " + this.sqs.getQueueUrl(this.queueName));
    //SECOND WAY
    return this.sqs.getQueueUrl(queueUrlRequest).getQueueUrl();
}

I have been trying to figure this out for a while now. Any help is appreciated.

Programmer
  • 175
  • 1
  • 2
  • 17
  • Are you passing the endpoint to your method so that it's set? It's required. – mjuopperi Jul 06 '15 at 18:40
  • Yes, the constructor sets the endpoint for the sqs object. – Programmer Jul 06 '15 at 19:22
  • 12
    Does your instance role have permission to call GetQueueUrl? You're bypassing that call when using the CLI by manually constructing the QueueUrl parameter. – David Murray Jul 07 '15 at 03:07
  • 1
    @DavidMurray that is a good point. I was not aware if there were permissions needed to call getQueueUrl(). I might need to check it. Do they need to be the same as the Queue permissions? Or how does it work? – Programmer Jul 07 '15 at 17:19
  • The permissions were added to access getQueueUrl(). I have edited my question to show how I call the method and the place it errors out. – Programmer Jul 07 '15 at 18:31
  • 2
    @DavidMurray +1 Your suggestion solved my problem. Worthy of an answer. – Mattiavelli Jul 20 '16 at 15:26

1 Answers1

0

As David Murray pointed out in the comments above, if the SQS Queue exists, it probably is an issue with the permissions. Make sure that the EC2 instance role is allowed to use the sqs:GetQueueUrl action.

Here's an example policy including the necessary statement.:

{
   "Version": "2012-10-17",
   "Statement": [{
      "Effect": "Allow",
      "Action": "sqs:GetQueueUrl",
      "Resource": "QUEUE_ARN"
   }]
}

(make sure to replace QUEUE_ARN with SQS queue ARN)

Dennis Traub
  • 50,557
  • 7
  • 93
  • 108