0

I'm attempting to use localstack for development with SQS.

  • Aws client v2.20.60
  • localstack v2.0.2.

I'm following this blog post, but no matter what I try, I always get the error:

exception while calling sqs with unknown operation: Operation detection failed. Missing Action in request for query-protocol service ServiceModel(sqs).

This is how I created the SqsClient:

    SqsClientBuilder builder = SqsClient.builder();
    builder.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test")));
    builder.endpointOverride(new URI("http://localhost:4566"));
    builder.region(Region.of("us-west-2"));
    return builder.build();

And then any of the Sqs operations, for example creating a queue:

    sqsClient.createQueue(CreateQueueRequest.builder()
        .queueName("test2")
        .build());

Logs:

software.amazon.awssdk.request           : Retrying Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=http, host=localhost, port=4566, encodedPath=/, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent, X-Amz-Target], queryParameters=[])
org.apache.http.wire                     : http-outgoing-3 >> "POST / HTTP/1.1[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "Host: localhost:4566[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "amz-sdk-invocation-id: 3f223a7a-773b-d41f-388a-b222efb26e25[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "amz-sdk-request: attempt=4; max=4[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "Authorization: AWS4-HMAC-SHA256 Credential=test/20230512/us-west-2/sqs/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-date;x-amz-target, Signature=4cd498092415018e24f7fb37c3b86ad77f10154f3cc5dc2627f3e7bf2aa7b7f8[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "Content-Type: application/x-amz-json-1.0[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "User-Agent: aws-sdk-java/2.20.60 Linux/6.3.1 OpenJDK_64-Bit_Server_VM/17.0.3+7-nixos Java/17.0.3 vendor/N_A io/sync http/Apache cfg/retry-mode/legacy[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "X-Amz-Date: 20230512T043918Z[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "X-Amz-Target: AmazonSQS.CreateQueue[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "Content-Length: 21[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "Connection: Keep-Alive[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 >> "{"QueueName":"test2"}"
org.apache.http.wire                     : http-outgoing-3 << "HTTP/1.1 500 [\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "Content-Type: text/xml[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "Content-Length: 407[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "Access-Control-Allow-Origin: *[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "Access-Control-Allow-Methods: HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "Access-Control-Allow-Headers: authorization,cache-control,content-length,content-md5,content-type,etag,location,x-amz-acl,x-amz-content-sha256,x-amz-date,x-amz-request-id,x-amz-security-token,x-amz-tagging,x-amz-target,x-amz-user-agent,x-amz-version-id,x-amzn-requestid,x-localstack-target,amz-sdk-invocation-id,amz-sdk-request[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "Access-Control-Expose-Headers: etag,x-amz-version-id[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "date: Fri, 12 May 2023 04:39:18 GMT[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "server: hypercorn-h11[\r][\n]"
org.apache.http.wire                     : http-outgoing-3 << "[\r][\n]"
software.amazon.awssdk.request           : Received failed response: 500, Request ID: not available, Extended Request ID: not available
org.apache.http.wire                     : http-outgoing-3 << "<?xml version='1.0' encoding='utf-8'?>[\n]"
org.apache.http.wire                     : http-outgoing-3 << "<ErrorResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/"><Error><Code>InternalError</Code><Message>exception while calling sqs with unknown operation: Operation detection failed. Missing Action in request for query-protocol service ServiceModel(sqs).</Message></Error><RequestId>5J3R58QQJ04NODX9NQYFLEZM110VTGAFIQ0W894F7HXWVNAZCK3U</RequestId></ErrorResponse>"
o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: software.amazon.awssdk.services.sqs.model.SqsException: Service returned HTTP status code 500 (Service: Sqs, Status Code: 500, Request ID: null)] with root cause

software.amazon.awssdk.services.sqs.model.SqsException: Service returned HTTP status code 500 (Service: Sqs, Status Code: 500, Request ID: null)
    at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
    at ...
org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)
Kevin
  • 1,080
  • 3
  • 15
  • 41

1 Answers1

0

I recommended that you get it running in a Java Console app before trying to get it to work with localstack. Make sure your AWS SDK for Java V2 logic works.

To create a SQS Client object, use:

 SqsClient sqsClient = SqsClient.builder()
            .region(Region.US_WEST_2)
            .credentialsProvider(ProfileCredentialsProvider.create())
            .build();

Try getting this SQS example working in a Java JDE like IntelliJ and make sure you can run it.

The Github location where you will find the POM is here.

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/sqs

Full example to try:

package com.example.sqs;

// snippet-start:[sqs.java2.sqs_example.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityRequest;
import software.amazon.awssdk.services.sqs.model.CreateQueueRequest;
import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
import software.amazon.awssdk.services.sqs.model.GetQueueUrlRequest;
import software.amazon.awssdk.services.sqs.model.GetQueueUrlResponse;
import software.amazon.awssdk.services.sqs.model.ListQueuesRequest;
import software.amazon.awssdk.services.sqs.model.ListQueuesResponse;
import software.amazon.awssdk.services.sqs.model.Message;
import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest;
import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry;
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
import software.amazon.awssdk.services.sqs.model.SqsException;

import java.util.List;
// snippet-end:[sqs.java2.sqs_example.import]


/**
 * Before running this Java V2 code example, set up your development environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class SQSExample {

    public static void main(String[] args) {
        String queueName = "queue" + System.currentTimeMillis();
        SqsClient sqsClient = SqsClient.builder()
            .region(Region.US_WEST_2)
            .credentialsProvider(ProfileCredentialsProvider.create())
            .build();

        // Perform various tasks on the Amazon SQS queue
        String queueUrl= createQueue(sqsClient, queueName );
        listQueues(sqsClient);
        listQueuesFilter(sqsClient, queueUrl);
        List<Message> messages = receiveMessages(sqsClient, queueUrl);
        sendBatchMessages(sqsClient, queueUrl);
        changeMessages(sqsClient, queueUrl, messages);
        deleteMessages(sqsClient, queueUrl, messages) ;
        sqsClient.close();
    }

    // snippet-start:[sqs.java2.sqs_example.main]
    public static String createQueue(SqsClient sqsClient,String queueName ) {

        try {
            System.out.println("\nCreate Queue");
            // snippet-start:[sqs.java2.sqs_example.create_queue]

            CreateQueueRequest createQueueRequest = CreateQueueRequest.builder()
                .queueName(queueName)
                .build();

            sqsClient.createQueue(createQueueRequest);
            // snippet-end:[sqs.java2.sqs_example.create_queue]

            System.out.println("\nGet queue url");

            // snippet-start:[sqs.java2.sqs_example.get_queue]
            GetQueueUrlResponse getQueueUrlResponse = sqsClient.getQueueUrl(GetQueueUrlRequest.builder().queueName(queueName).build());
            return getQueueUrlResponse.queueUrl();

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return "";
        // snippet-end:[sqs.java2.sqs_example.get_queue]
    }

    public static void listQueues(SqsClient sqsClient) {

        System.out.println("\nList Queues");
        // snippet-start:[sqs.java2.sqs_example.list_queues]
        String prefix = "que";

        try {
            ListQueuesRequest listQueuesRequest = ListQueuesRequest.builder().queueNamePrefix(prefix).build();
            ListQueuesResponse listQueuesResponse = sqsClient.listQueues(listQueuesRequest);
            for (String url : listQueuesResponse.queueUrls()) {
                System.out.println(url);
            }

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        // snippet-end:[sqs.java2.sqs_example.list_queues]
    }

    public static void listQueuesFilter(SqsClient sqsClient, String queueUrl ) {
        // List queues with filters
        String namePrefix = "queue";
        ListQueuesRequest filterListRequest = ListQueuesRequest.builder()
            .queueNamePrefix(namePrefix)
            .build();

        ListQueuesResponse listQueuesFilteredResponse = sqsClient.listQueues(filterListRequest);
        System.out.println("Queue URLs with prefix: " + namePrefix);
        for (String url : listQueuesFilteredResponse.queueUrls()) {
            System.out.println(url);
        }

        System.out.println("\nSend message");
        try {
            // snippet-start:[sqs.java2.sqs_example.send_message]
            sqsClient.sendMessage(SendMessageRequest.builder()
                .queueUrl(queueUrl)
                .messageBody("Hello world!")
                .delaySeconds(10)
                .build());
            // snippet-end:[sqs.java2.sqs_example.send_message]

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }

    public static void sendBatchMessages(SqsClient sqsClient, String queueUrl) {

        System.out.println("\nSend multiple messages");
        try {
            // snippet-start:[sqs.java2.sqs_example.send__multiple_messages]
            SendMessageBatchRequest sendMessageBatchRequest = SendMessageBatchRequest.builder()
                .queueUrl(queueUrl)
                .entries(SendMessageBatchRequestEntry.builder().id("id1").messageBody("Hello from msg 1").build(),
                        SendMessageBatchRequestEntry.builder().id("id2").messageBody("msg 2").delaySeconds(10).build())
                .build();
            sqsClient.sendMessageBatch(sendMessageBatchRequest);
            // snippet-end:[sqs.java2.sqs_example.send__multiple_messages]

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }

    public static List<Message> receiveMessages(SqsClient sqsClient, String queueUrl) {

        System.out.println("\nReceive messages");
        try {
            // snippet-start:[sqs.java2.sqs_example.retrieve_messages]
            ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl)
                .maxNumberOfMessages(5)
                .build();
            return sqsClient.receiveMessage(receiveMessageRequest).messages();

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return null;
        // snippet-end:[sqs.java2.sqs_example.retrieve_messages]
    }

    public static void changeMessages(SqsClient sqsClient, String queueUrl, List<Message> messages) {

        System.out.println("\nChange Message Visibility");
        try {

            for (Message message : messages) {
                ChangeMessageVisibilityRequest req = ChangeMessageVisibilityRequest.builder()
                    .queueUrl(queueUrl)
                    .receiptHandle(message.receiptHandle())
                    .visibilityTimeout(100)
                    .build();
                sqsClient.changeMessageVisibility(req);
            }

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }

    public static void deleteMessages(SqsClient sqsClient, String queueUrl, List<Message> messages) {
        System.out.println("\nDelete Messages");
        // snippet-start:[sqs.java2.sqs_example.delete_message]

        try {
            for (Message message : messages) {
                DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
                    .queueUrl(queueUrl)
                    .receiptHandle(message.receiptHandle())
                    .build();
                sqsClient.deleteMessage(deleteMessageRequest);
            }
            // snippet-end:[sqs.java2.sqs_example.delete_message]

        } catch (SqsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
   }
   // snippet-end:[sqs.java2.sqs_example.main]
}
 

I just ran this example and it worked perfectly.

enter image description here

smac2020
  • 9,637
  • 4
  • 24
  • 38