Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SqsListener with SNS and SQS

I'm using spring-cloud-aws's SqsListener to receive AWS SNS HTTP Notifications in JSON Format from AWS's Simple Queue Service (SQS).

This is the code for the listener:

@SqsListener(value = "my-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void handle(final MyObject obj) throws Exception {
// ...
}

The documentation linked above is only about sending and reading plain serialized objects to the Queue and I thought that receiving SNS messages is expected to work out of the box. But I end up receiving conversion errors:

10:45:51.480 [simpleMessageListenerContainer-2] ERROR o.s.c.a.m.l.SimpleMessageListenerContainer - Exception encountered while processing message. org.springframework.messaging.MessagingException: An exception occurred while invoking the handler method; nested exception is org.springframework.messaging.converter.MessageConversionException: No converter found to convert to class com.myproject.model.MyObject, message=GenericMessage

I also tried creating a wrapper object that looks like the expected SNS Json Format linked above, but I keep getting the same exception. The only type that works is a String in the signature. Shouldn't the SNS be converted automatically?

like image 716
msp Avatar asked Apr 11 '16 08:04

msp


People also ask

Can SNS poll SQS?

Amazon SNS works closely with Amazon Simple Queue Service (Amazon SQS). These services provide different benefits for developers. Amazon SNS allows applications to send time-critical messages to multiple subscribers through a “push” mechanism, eliminating the need to periodically check or “poll” for updates.

What is @SqsListener?

@Target(value=METHOD) @Retention(value=RUNTIME) @Documented @MessageMapping public @interface SqsListener. Annotation for mapping a Message onto listener methods by matching to the message destination. The destination can be a logical queue name (CloudFormation), a physical queue name or a queue URL.

What is QueueMessagingTemplate?

The QueueMessagingTemplate contains many convenience methods to send a message. There are send methods that specify the destination using a QueueMessageChannel object and those that specify the destination using a string which is going to be resolved against the SQS API.

How messages are consumed from SQS?

If you want to consume from SQS you have the following methods: Polling using the SDK to consume messages. Using the Amazon SQS Java Messaging Library. Subscribing to an SNS Topic.


1 Answers

This works without the @NotificationMessage as well. This way you don't need to send the "Type" and "Message" part, that is required to work with this annotation.

First create a class with the needed attributes.

public class SqsMessage {

   private String myTask;

   public SqsMessage() {
   }

   public SqsMessage(@JsonProperty("MyTask") String myTask ) {
       this.myTask = myTask ;
   }

   //Getter + Setter 
}

Next set up the Listener

@SqsListener(value = {"MyQueue"}, deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void receiveMessage(SqsMessage payload, @Headers Map<String, Object> header) {
   logger.info("Got message with task: " + payload.getTask() 
    + " with custom attribute " + header.get("CustomAttribute").toString());
}

Now you can send a JSON like

{"MyTask":"My task"}

The @JsonProperty("MyTask") annoation in the POJO's constructor can be optional, depending on your spring version and if your attribute has the same name as in the Json string. It's not necessary for example, if your attribute is called task and your Json string is {"task":"My task"}.

like image 75
Chris Avatar answered Oct 19 '22 06:10

Chris