title: Combining @SqsListener and @RequestMapping
body: <p>We're currently in the middle of migrating our current architecture into Spring-AWS-based microservices. One of my tasks is to research on how our microservices communicate with one another. <em>I'm aiming to set-up a hybrid system of RESTful HTTP endpoints and SQS producers and consumers.</em></p>
  
  <p>As an example, I have the below code:</p>
  
  <pre><code>@SqsListener("request_queue")
  @SendTo("response_queue")
  @PostMapping("/send")
  public Object send(@RequestBody Request request, @Header("SenderId") String senderId) {
      if (senderId != null &amp;&amp; !senderId.trim().isEmpty()) {
          logger.info("SQS Message Received!");
          logger.info("Sender ID: ".concat(senderId));
          request = new Gson().fromJson(payload, Request.class);
      }
  
      Response response = processRequest(request); // Process request
  
      return response;
  }
  </code></pre>
  
  <p>Theoretically, this method should be able to handle the following:</p>
  
  <ol>
  <li>Receive a <strong>Request</strong> object via HTTP</li>
  <li>Continually poll the <strong>request_queue</strong> for a message containing the <strong>Request</strong> object</li>
  </ol>
  
  <p>As an HTTP endpoint, the method returns no error. However, as an SQS listener, it runs into the following exception:</p>
  
  <pre><code>org.springframework.messaging.converter.MessageConversionException: 
      Cannot convert from [java.lang.String] to [com.oriente.salt.Request] for 
      GenericMessage [payload={"source":"QueueTester","message":"This is a wonderful 
      message send by queue from Habanero to Salt. Spicy.","msisdn":"+639772108550"}, 
      headers={LogicalResourceId=salt_queue, ApproximateReceiveCount=1, 
      SentTimestamp=1523444620218, ....
  </code></pre>
  
  <p>I've tried to annotate the <strong>Request</strong> param with @Payload, but to no avail. Currently I've also set-up the AWS config via Java, as seen below:</p>
  
  <p><strong>ConsuerAWSSQSConfig.java</strong></p>
  
  <pre><code>@Configuration
  public class ConsumerAWSSQSConfig {
  
  @Bean
  public SimpleMessageListenerContainer simpleMessageListenerContainer() {
      SimpleMessageListenerContainer msgListenerContainer = simpleMessageListenerContainerFactory()
              .createSimpleMessageListenerContainer();
      msgListenerContainer.setMessageHandler(queueMessageHandler());
      return msgListenerContainer;
  }
  
  @Bean
  public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory() {
      SimpleMessageListenerContainerFactory msgListenerContainerFactory = new SimpleMessageListenerContainerFactory();
      msgListenerContainerFactory.setAmazonSqs(amazonSQSClient());
      return msgListenerContainerFactory;
  }
  
  @Bean
  public QueueMessageHandler queueMessageHandler() {
      QueueMessageHandlerFactory queueMsgHandlerFactory = new QueueMessageHandlerFactory();
      queueMsgHandlerFactory.setAmazonSqs(amazonSQSClient());
      QueueMessageHandler queueMessageHandler = queueMsgHandlerFactory.createQueueMessageHandler();
      List&lt;HandlerMethodArgumentResolver&gt; list = new ArrayList&lt;&gt;();
      HandlerMethodArgumentResolver resolver = new PayloadArgumentResolver(new MappingJackson2MessageConverter());
      list.add(resolver);
      queueMessageHandler.setArgumentResolvers(list);
      return queueMessageHandler;
  }
  
  @Lazy
  @Bean(name = "amazonSQS", destroyMethod = "shutdown")
  public AmazonSQSAsync amazonSQSClient() {
      AmazonSQSAsync awsSQSAsync = AmazonSQSAsyncClientBuilder.standard().withRegion(Regions.AP_SOUTHEAST_1).build();
      return awsSQSAsync;
  }
  }
  </code></pre>
  
  <p>What do you guys think?</p>