5

Okay, I have practically read every single stackoveflow post on spring websocket. I want to send a message to a particular client once it connects to the server, simple!

I have been able to connect from the client, and I can listen for new connections on the server side. But when I try to send a message from the server side, nothing happens. Even though my client has subscribed.

Below is my client js.

var stompClient = null;
$(document).ready(function() {
    connect();
});

function connect() {
var socket = new SockJS('/context_path/stockfeeds');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
    console.log('Connected: ' + frame);
    stompClient.subscribe('/topic/share', function(message) {
        console.log("Subscription successful............");
        console.log(JSON.parse(message.body));
    });

    stompClient.subscribe('/user/queue/reply', function(message) {
        console.log("Subscribed to user ...");
    });
}, function (error) {
    console.log("Stomp protocol error: "+ error);
});
}

$('#livetext').click(function () {
    stompClient.send('/app/stockfeeds', {}, 'This is BS');
});

The send send function works when I click '#livetext'. And a response is received on the client. Below is my Controller.

@Controller
public class StockDispatchController {

    @Autowired
    LoggerService loggerService;

    @MessageMapping("/stockfeeds")
    @SendTo("/topic/share")
    public String fetchStocks(String message) throws Exception {
        loggerService.info("-----------------------------"+ message);

        return message;
    }

}

Below is my Connect event listener

import org.springframework.messaging.simp.SimpMessagingTemplate;

@Component
public class StompConnectEvent implements ApplicationListener<SessionConnectEvent> {

@Autowired
LoggerService logger;

@Autowired
private SimpMessagingTemplate messagingTemplate;

public void onApplicationEvent(SessionConnectEvent event) {

    this.messagingTemplate.convertAndSend("/topic/share", "A new client just connected");
    this.messagingTemplate.convertAndSendToUser(event.getUser().getName(), "/queue/reply", "I just connected");
    logger.info("message template sent");
}

}

When a new client connects, the event listener is fired and runs to the end, but I don't get any response on the client.

Finally, below is my application context xml

<websocket:message-broker application-destination-prefix="/app">
    <websocket:stomp-endpoint path="/stockfeeds">
        <websocket:handshake-interceptors>
            <bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
        </websocket:handshake-interceptors>
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic, /queue"/>
</websocket:message-broker>
Charles
  • 251
  • 4
  • 12

3 Answers3

4

I haven't found a solution yet, but I found an alternative that works. So, instead of listening for SessionConnectedEvent, I added a controller method that gets fired when a user subscribes to it.

See below.

@SubscribeMapping("/reply")
public String initialReply() throws Exception {
    return "Welcome to the chat room.";
}

And I subscribe to it as below.

stompClient.subscribe('/app/reply', function(message) {
    alert(message.body);
});
Charles
  • 251
  • 4
  • 12
2

Quite late here but just in case anyone might need this. Instead of using SessionConnectEvent which didn't work for me, I used SessionSubscribeEvent after reading the documentations and it worked.

@Component
public class StompConnectEvent implements ApplicationListener<SessionSubscribeEvent> {

@Autowired
private SimpMessagingTemplate messagingTemplate;

public void onApplicationEvent(SessionSubscribeEvent event) {

    this.messagingTemplate.convertAndSend("/topic/share", messageObject);

    }
}

The SessionSubscribeEvent is called once the client subscribes to the websocket endpoint, so it can pick up messages sent to the endpoint by the server. But SessionConnectEvent is called when the client initially attempts to connect with the websocket, so the client isn't listening to the endpoint yet.

LittlePail
  • 21
  • 1
0

I had similar use case and this is what i implemented successfully.

  1. You can create some random string e.g clientId23 at client side which you can send to server over established websocket.
  2. Add same random string in subscribe URL e.g /app/reply/clientId23.
  3. on server side, you can persist that clientId in db or something.. using which you can message that particular client e.g. this.messagingTemplate.convertAndSend("/app/reply/clientId23", "A new client just connected");

Happy coding!

NotABot
  • 781
  • 7
  • 24