1

Is it possible to send messages with SimpMessageSendingOperations from a RabbitMQ listener bean?

I have the following listener class:

 public class MyJobListener {
     @Autowired
     public SimpMessageSendingOperations messagingTemplate;

     public void handleJob(JobMessage jobMessage) {
         doWork(jobMessage);

         messagingTemplate.convertAndSend("/topic/greetings", "TEST");
     }
 }

My Rabbit config file is:

<!-- RabbitMQ configuration -->
<rabbit:connection-factory id="connectionFactory" host="${rabbitmq.connection.host}" port="${rabbitmq.connection.port}"  />
<rabbit:admin connection-factory="connectionFactory" /> 
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" />

<!-- Queues -->    
<rabbit:queue id="myQueue" name="myQueue" />

<!-- Listeners -->
<bean id="myListener01" class="com.xxx.MyJobListener" />
<bean id="myListener02" class="com.xxx.MyJobListener" />
<bean id="myListener03" class="com.xxx.MyJobListener" />
<bean id="myListener04" class="com.xxx.MyJobListener" />    

<rabbit:listener-container connection-factory="connectionFactory" >
    <rabbit:listener ref="myListener01" method="handleJob" queue-names="myQueue" />
    <rabbit:listener ref="myListener02" method="handleJob" queue-names="myQueue" />
    <rabbit:listener ref="myListener03" method="handleJob" queue-names="myQueue" />
    <rabbit:listener ref="myListener04" method="handleJob" queue-names="myQueue" />
</rabbit:listener-container>  

<!-- Bindings -->
<rabbit:direct-exchange name="directexchange" >
    <rabbit:bindings>        
        <rabbit:binding queue="myQueue"/>
    </rabbit:bindings>
</rabbit:direct-exchange> 

When message is expected to be sent (messagingTemplate.convertAndSend("/topic/greetings", "TEST")) nothing happens, but if I do the same thing but in a @Controller everything works fine (message is sent through websocket to the browser)

I need to do this to send a notification to the user when the job is finished.

Andrés
  • 119
  • 1
  • 7
  • I'm not sure that your `MyJobListener` is really `@Autowired` with the `messagingTemplate`. It's just `null` during `handleJob()` process. Please, consult logs to be sure what's going on when `handleJob()` receives message from the RabbitMQ. Otherwise that would be great if you share on GitHub some simple application to play from our side. – Artem Bilan Sep 13 '17 at 16:20
  • Yes, it is being autowired. In fact if I debug I can see it is and instance of `org.springframework.messaging.simp.SimpMessagingTemplate` class – Andrés Sep 13 '17 at 16:33
  • Good. So, now only the sample can save us! – Artem Bilan Sep 13 '17 at 16:34

3 Answers3

0

After many tests I changed my rabbit configuration file, leaving only one listener:

<!-- Listeners -->
<bean id="myListener01" class="com.xxx.MyJobListener" />

<rabbit:listener-container connection-factory="connectionFactory" error-handler="queueErrorHandler" >
    <rabbit:listener ref="myListener01" method="handleJob" queue-names="myQueue" />
</rabbit:listener-container>

and now it works almost randomly. It's strange, but each 2 calls it works. I mean, two times yes, two times not, two times yes, two times not... and so... It's very strange. I think there is something with the rabbit config...

Andrés
  • 119
  • 1
  • 7
  • If I leave 2 listeners then it works each 4 calls.... What is going on?! – Andrés Sep 13 '17 at 22:18
  • OK. So, the story was not about not sending the message to the WebSocket, but that your `handleJob` just doesn't receive a message from the AMQP queue. Please, be sure that you don't have more listeners for that queue. – Artem Bilan Sep 14 '17 at 13:52
  • No ,my handleJob is receiving the messages. Always. The problem is the websocket message is not always being sent, only each x `handleJob()` executions, but `handleJob()` is always executing. – Andrés Sep 14 '17 at 14:59
  • I think there should be some logs on the matter, when you send to the WebSocket via `messagingTemplate.convertAndSend()`. At least you can turn on DEBUG for the `org.springframework.messaging.simp` category and see what's going on. On the other hand you might be able to debug the solution from your IDE and put on a break point on the `messagingTemplate.convertAndSend()` and jump into the call stack to follow the execution. – Artem Bilan Sep 14 '17 at 15:02
  • Yeah, I did that, and no exception is thrown. – Andrés Sep 14 '17 at 15:05
  • ??? I mean it would be great to go on debugging the Spring code as well from there. That's why I'm asking about sample app to play from our side – Artem Bilan Sep 14 '17 at 15:06
  • Yes, I know. But by now it's a little bit complicated... I will try to create a small app for this purpose. Thanks! – Andrés Sep 14 '17 at 15:09
  • That's true. We need only that listener and WebSocket configuration to see what's going on – Artem Bilan Sep 14 '17 at 15:10
  • 1
    I built a small app with a minimal configuration and libraries and everything works fine. It must be something with other configurations (it's a big project). Now I will have to see what can be generating conflicts (it will be a hard work ;) Thanks for your help friend – Andrés Sep 14 '17 at 17:05
0

Definitely is Spring Security configuration. If I disable Spring Security everything works fine. I will find out what it is, and then I'll post the answer here.

Andrés
  • 119
  • 1
  • 7
0

I was able to solve it.

The problem was not Spring Security, the problem was I was declarating twice the websocket message broker:

<websocket:message-broker application-destination-prefix="/app" >
    <websocket:stomp-endpoint path="/websocket" >
        <websocket:sockjs />
    </websocket:stomp-endpoint>

     <websocket:simple-broker prefix="/topic,/user" />      
</websocket:message-broker> 

These lines resides in my websocket.xml, and this file was imported more than one time because of an "ugly" import sentences distributions along my .xml spring files.

After ordering these imports and ensuring the bean is only created once everything works fine.

May this helps!

Andrés
  • 119
  • 1
  • 7