3
votes

I am using Spring AMQP's MessageListenerContainer for recieving messages from RabbitMq Broker . Though I am able to receive message inside the listener , autowiring is not working inside listener .

Here is how I have configured my Listener

@Bean
public SimpleMessageListenerContainer listenerContainer() {
    SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
    listenerContainer.setConnectionFactory(this.inputQueueMgr
            .getRabbitConnectionFactory());
    JsonMessageConverter converter = new JsonMessageConverter();
    listenerContainer.setMessageConverter(converter);
    listenerContainer.setMessageListener(new InputQueueEventDispatcher());
    listenerContainer.setQueueNames("queue1");
    listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
    listenerContainer.setPrefetchCount(1);
    return listenerContainer;
}

Here is the class where I am listening to the messages from rabbitMq

@Component(value = "inputMessageListner")
public class InputQueueEventDispatcher implements Serializable, MessageListener {

private static final long serialVersionUID = -5391659256992655430L;

@Autowired
private volatile InputQueueManagerImpl inputQueueMgr;

@Autowired
private volatile NotificationQueueManagerImpl notificationManager;

@Value("${input.rabbitmq.events.queue}")
private String queueName;

@Autowired
private SubscriptionRepository subRepository;

@SuppressWarnings({ "unchecked" })
@Override
public void onMessage(Message message) {
    try {
        String messageContent = new String(message.getBody());
         .....
 }

The problem is inside onMessage(Message message) all the autowire components are coming as null .

PS-> Please note that I have declared all the autowire instances as @Component and doing appropriate ComponentScan to scan their packages appropriately . Infact these components do get autowired in normal flow but since onMessage(Message message) gets executed on a seperate thread , these values are showing null . Is there any way to enable autowiring here inside listener .

Thanks

2

2 Answers

2
votes

You've set a @Component annotation on your listener, but you don't get this bean from the context. Instead, you're creating the instance yourself, using new. So Spring has no way to know that this instance has been created and must be autowired.

Remove that @Component annotation, and change your code to

@Bean
public SimpleMessageListenerContainer listenerContainer() {
    SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
    listenerContainer.setConnectionFactory(this.inputQueueMgr
            .getRabbitConnectionFactory());
    JsonMessageConverter converter = new JsonMessageConverter();
    listenerContainer.setMessageConverter(converter);
    listenerContainer.setMessageListener(inputMessageListener());
    listenerContainer.setQueueNames("queue1");
    listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
    listenerContainer.setPrefetchCount(1);
    return listenerContainer;
}

@Bean 
public InputQueueEventDispatcher inputMessageListener() {
    return new InputQueueEventDispatcher();
}

Now, since the bean is returned from a @Bean-annotated method, Spring will make is a Spring bean and autowire it.

-1
votes

Most probably the other thread you mentioned on your question is not getting that instance from spring's application context. So no injection happens for it.

You should use

@RabbitListener(queues = "queue_name")

on your onMessage method. But you should also change onMessage method syntax and and

onMessage(Message<String> originalMessage)

that way spring will automatically call that method with message