Spring Boot Listener for AWS SQS With Spring Cloud

Spring Cloud AWS makes it easy to create a Java method that listens for messages on an Amazon SQS queue.  Between Spring Boot and Spring Cloud, I was surprised by just how little code I needed to make all this happen.

The key is that when you have the right dependencies in your Maven POM, all you have to do is annotate your listener method with  @SqsListener:

@SqsListener("your-queue-name")
public void listen(DataObject message) {
LOG.info("!!!! received message {} {}", message.getFoo(), message.getBar());
}


The dependency on spring-cloud-starter-aws takes care of initializing everything and scanning for annotated methods.

I put a gist on Github to illustrate the full Java class and full Maven POM.

Converting Messages to Java Objects

Your listener method can accept a String as an argument, or it can convert JSON in the message into Java objects.  Spring will use Jackson to convert the incoming JSON to Java, with appropriate annotations:

@JsonCreator
public DataObject(@JsonProperty("foo") String foo, @JsonProperty("bar") String bar) {
this.foo = foo;
this.bar = bar;
}

Command Line Arguments and Authentication

You specify AWS credentials and region through Spring Boot properties. I passed these as command line arguments through Eclipse, where I was debugging locally/not on AWS:

If I were running in AWS itself, the EC2 instance metadata could have determined the region automatically, and also provided credentials via the instance profile.

Testing via AWS Console

I used the AWS console to send test messages. The main catch is that if you are using JSON messages and using Spring to automatically deserialize JSON to your objects via @JsonProperty  annotations, you will need to specify the message attribute (header) contentType  with value  application/json. Otherwise, the conversion will fail with an unhelpful error message like "Cannot convert from [java.lang.String] to .... for GenericMessage ...." with no indication why there was a failure.

There is another alternative for reconfiguring the default Spring messaging classes to ignore the contentType  header.

 

 

 

 

Top