Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Websocket : receiving nothing from SimpMessagingTemplate

I'm currently using Websockets in a Spring-MVC webapp to send notifications to spring-security-authenticated users at any time. The point is to notify users without any page refresh or user interaction (like Facebook does for example).

Therefore, I'm using Spring's SimpMessagingTemplate

It looks (as seen in the browser console) like the client subscribes correctly, and that the SimpMessagingTemplate actually sends a message (debugging the Spring code shows a happy flow happening, sent == true etc). However, nothing happens at client-side - which is the issue.

After hours of re-reading the reference, other Stackoverflow posts etc (which do the same thing as here.. But seem to work !), I can't find an appropriate solution. The only difference is that I have a duplicated websocket configuration, which might be the cause of my troubles, but that I cannot get rid of (more on that hereunder : see dispatcher-servlet.xml and applicationContext.xml).

Client-side, I subscribe like this :

<script>
    var socket = new SockJS('/stomp');
    var client = Stomp.over(socket);

    client.connect({}, function(s) {
            client.subscribe('/user/queue/notify', function (msg) {
            alert('SHOULD SEE THIS.. BUT DOES NOT WORK');
            console.log("SHOULD SEE THIS.. BUT DOES NOT WORK");
        });
    });
</script>

I have a controller that sends a simple message to user "niilzon" every 10 seconds (this is just a simple test ofcourse)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;

@Controller
public class WebsocketTestController {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Scheduled(fixedDelay = 10000)
    public void sendStuff() {
        messagingTemplate.convertAndSendToUser("niilzon", "/queue/notify", "SEEING THIS WOULD BE GREAT");
    }

}

Browser console, after the "niilzon" user logged in :

<<< CONNECTED
version:1.1
heart-beat:0,0
user-name:niilzon

connected to server undefined
>>> SUBSCRIBE
id:sub-0
destination:/user/queue/notify

And here is the XML configuration :

dispatcher-servlet.xml :

<!-- TODO this is duplicated in applicationContext !
 If removing the websocket tag in dispatcher-servlet : 404 when client tries to connect to /stomp
 If removing the websocket tag in applicationContext : cannot autowire SimpMessagingTemplate in WebsocketTestController
 -->
<websocket:message-broker>
    <websocket:stomp-endpoint path="/stomp">
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic,/queue"/>
</websocket:message-broker>

applicationContext.xml :

<websocket:message-broker>
    <websocket:stomp-endpoint path="/stomp">
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic,/queue"/>
</websocket:message-broker>

As described in dispatcher-servlet.xml, the websocket configuration is duplicated in applicationContext.xml. If I remove the tag in dispatcher-servlet.xml, the client gets a 404 when trying to connect. If I remove the tag in applicationContext.xml, the SimpMessagingTemplate cannot be autowired in WebsocketTestController.

Could the configuration duplication be part of the issue ? That's the only lead I have left, but I am unable to fix it. An important thing to note is that some other config tags are duplicated between the 2 xml files. Here are ALL the duplications between the 2 config files, put next to each other (+ the websocket config as seen above) :

<import resource="spring-security.xml"/>
<context:component-scan base-package="com.beatboxnow.**"/>
<tx:annotation-driven />
<!-- TODO merge / inherit contexts instead of this dupe ? How ? same with tx:annotationDriven -->
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
    <property name="cacheManager" ref="ehcache"/>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="configLocation" value="classpath:ehcache.xml"/>
    <property name="shared" value="true"/>
</bean>

There are no issues with the rest of the webapp, which has alot of views, controllers, services, repositories etc.

Any help would be greatly appreciated !

like image 741
niilzon Avatar asked Oct 20 '22 05:10

niilzon


1 Answers

Thanks to this StackOverflow post here Loading both mvc-dispatcher-servlet.xml and applicationContext.xml?, I managed to merge the duplicates in the dispatcher-servlet and applicationContext XML's.

The trick was simply to import the applicationContext in the dispatcher-servlet like this :

<import resource="applicationContext.xml" />

, and to remove all the duplicates (not touching any tag in applicationContext.xml obviously).

I had this partial configuration duplication issue hanging since the beginning of this project and planned to remove it later on - tried the import at that time but I did not manage to do it back then. Now this Websocket issue forced me to try it again (duplicating was not blocking before), and surprisingly it worked perfectly, I suppose that I made a silly mistake during the first try, since it was in fact rather trivial :)

like image 81
niilzon Avatar answered Oct 22 '22 01:10

niilzon