I'm using Spring Cloud AWS messaging to send/receive messages using SQS.
My code looks like this:
@SpringBootApplication
@Import(MessagingConfig.class)
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@Configuration
public class MessagingConfig {
@Bean
public QueueMessagingTemplate queueMessagingTemplate(AmazonSQS amazonSqs, ResourceIdResolver resourceIdResolver) {
return new QueueMessagingTemplate(amazonSqs, resourceIdResolver);
}
}
The sender code is like this (wired via a controller):
@Component
public class Sender {
@Autowired
private QueueMessagingTemplate queueMessagingTemplate;
public void send(MyMessage message) {
queueMessagingTemplate.convertAndSend("testQueue", message);
}
}
I have an application.yaml
file that defines the AWS parameters that seem to be correctly loaded. So, when I run this application, I get the following warning/error:
Message header with name 'id' and type 'java.util.UUID' cannot be sent as message attribute because it is not supported by SQS.
Is there something that I'm doing wrong here, or is there an issue with the way Spring creates messages for SQS?
This appears to be only a warning and does not affect the sending and/or receiving of the message. When I tested this against a real SQS queue, I could both send and receive messages.
However, when using elasticMQ on my local box as a replacement for the real SQS, it was failing to process the message. It looks like an issue with that tool rather than Spring.
How to answer the question this
The problem occurs because the constructor called MessageHeaders class
MessageHeaders class
MessageHeaders(Map<String, Object> headers) { } on line 39
And to not send the id header you need to call the constructor
MessageHeaders class
MessageHeaders(Map<String, Object> headers, UUID id, Long timestamp){} on line 43
because this constructor has the condition does not create the id header automatically
to stop sending the header id you need to override the MessageHeader and NotificationMessagingTemplate classes
class MessageHeaders
public class MessageHeadersCustom extends MessageHeaders {
public MessageHeadersCustom() {
super(new HashMap<String, Object>(), ID_VALUE_NONE, null);
}
}
class NotificationMessagingTemplate
public class NotificationMessagingTemplateCustom extends NotificationMessagingTemplate {
public NotificationMessagingTemplateCustom(AmazonSNS amazonSns) {
super(amazonSns);
}
@Override
public void sendNotification(Object message, String subject) {
MessageHeaders headersCustom = new MessageHeadersCustom();
headersCustom.put(TopicMessageChannel.NOTIFICATION_SUBJECT_HEADER, subject);
this.convertAndSend(getRequiredDefaultDestination(), message, headersCustom);
}
}
And finally, your class that will make the call need to use your implementation
package com.stackoverflow.sample.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.aws.messaging.core.NotificationMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/whatever")
public class SampleController {
@Autowired
private NotificationMessagingTemplateCustom template;
@RequestMapping(method = RequestMethod.GET)
public String handleGet() {
this.template.sendNotification("message", "subject");
return "yay";
}
}
}