Spring AMQP: error with annotation-driven listener endpoints
java, rabbitmq, spring, spring-amqp
Solution
Your issue is very simple!
To send any Java object over RabbitMQ with default `SimpleMessageConverter` you have to to mark your class as `Serializable`:
public class HelloMessage implements Serializable {
....
}
Of course, a `listener` application should have the same class in its CLASSPATH to have an ability to `deserialize` `byte[]` from `payload` (AMQP Message body) to the appropriate `HelloMessage` object.
Problem
I'm trying to set up a simple Spring AMQP scenario, but am getting the following error: ``` Could not resolve method parameter at index 0 in method: public void handleMessage(HelloMessage), with 1 error(s): [Error in object 'msg': codes []; arguments []; default message [@Payload param is required]] ``` I don't understand the error message, I was under the impression I can use any POJO to send and receive a message, as per the documentation here. It's a very simple setup: main ``` public class Program { private static ConfigurableApplicationContext applicationContext; public static void main(String[] args) { try { startApp(); System.out.println("Running..."); System.in.read(); applicationContext.close(); System.out.println("Shutting down..."); } catch (Throwable e) { e.printStackTrace(); } } private static void startApp() { applicationContext = new ClassPathXmlApplicationContext("/application-context.xml"); applicationContext.refresh(); MessageSender messageSender = applicationContext.getBean(MessageSender.class); messageSender.sendMessage("hello", 1); } ``` application-context.xml ``` <context:component-scan base-package="org.abiri.amqpTest" /> <rabbit:connection-factory id="connectionFactory" host="localhost" port="5672" username="guest" password="guest"/> <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/> <rabbit:admin connection-factory="connectionFactory"/> <rabbit:queue name="hello"/> <bean id="rabbitListenerContainerFactory" class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory"> <property name="connectionFactory" ref="connectionFactory"/> <property name="concurrentConsumers" value="3"/> <property name="maxConcurrentConsumers" value="10"/> </bean> <rabbit:annotation-driven container-factory="rabbitListenerContainerFactory"/> <rabbit:listener-container connection-factory="connectionFactory" /> ``` MessageSender ``` @Service public class MessageSender { @Autowired private AmqpTemplate amqpTemplate; // Accessors... public void sendMessage(String message, Integer sillyNumber) { amqpTemplate.convertAndSend("hello", new HelloMessage(message, sillyNumber)); } } ``` MessageListener ``` @Component public class MessageListener { @RabbitListener(queues = "hello") public void handleMessage(HelloMessage msg) { out.println(format("Received message: %s with silly number: %d", msg.getMessage(), msg.getSillyNumber())); } } ``` HelloMessage ``` public class HelloMessage { private String message; private Integer sillyNumber; // Empty constructor, full constructor and accessors } ``` I am able to verify that the message was indeed sent and is in the queue: RabbitMQ default installation via homebrew.