Spring stomp websockets with vue.js

pressbyron picture pressbyron · Oct 18, 2017 · Viewed 10.5k times · Source

I'm trying to use Spring websockets (STOMP) with Vue but can't figure out how to do it or if it's even possible. My websockets work with plain JS but when i try with Vue i get stuck. Here is my vue code:

var app = new Vue({
el: '#app',
data: {
    stompClient: null,
    gold: 0
},
methods: {
    sendEvent: function () {
        this.stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
    }
},
created: function () {
    this.stompClient = Stomp.over(new SockJS('/gs-guide-websocket'));
    this.stompClient.connect()
    this.stompClient.subscribe('/topic/greetings', function (greeting) {
        console.log(JSON.parse(greeting.body).content);
    });
},

})

My connect and send function is working and i can see the message in the backend but the problem is the subscribe function. It needs a callback function but this never fire. I have also tried to create a method in vue and call that

this.stompClient.subscribe('/topic/greetings', vueFunc())

but that does not work either. I have found some library at https://github.com/FlySkyBear/vue-stomp but I can't figure out how to use that and it looks really messy. I rather use plain JS then.

Anyone got an solution? Thanks

Answer

kojot picture kojot · Feb 16, 2018

Here is the working example with Spring Boot Websocket (STOMP) and Vue CLI. (more detailed description here http://kojotdev.com/2019/07/using-spring-websocket-stomp-application-with-vue-js/)

  1. Download the Spring Boot demo from https://spring.io/guides/gs/messaging-stomp-websocket/
  2. Add allowed origin in WebSocketConfig

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket")
                .setAllowedOrigins("http://localhost:8081")
                .withSockJS();
    }
    
  3. Run the project

Now initiate the Vue CLI project and:

  1. Install SockJS npm install sockjs-client
  2. Install STOMP npm install webstomp-client
  3. I use bootstrap classes, so you need npm install bootstrap@3 just for layout

Add .vue component:

<template>
    <div>
        <div id="main-content" class="container">
            <div class="row">
                <div class="col-md-6">
                    <form class="form-inline">
                        <div class="form-group">
                            <label for="connect">WebSocket connection:</label>
                            <button id="connect" class="btn btn-default" type="submit" :disabled="connected == true" @click.prevent="connect">Connect</button>
                            <button id="disconnect" class="btn btn-default" type="submit" :disabled="connected == false" @click.prevent="disconnect">Disconnect
                            </button>
                        </div>
                    </form>
                </div>
                <div class="col-md-6">
                    <form class="form-inline">
                        <div class="form-group">
                            <label for="name">What is your name?</label>
                            <input type="text" id="name" class="form-control" v-model="send_message" placeholder="Your name here...">
                        </div>
                        <button id="send" class="btn btn-default" type="submit" @click.prevent="send">Send</button>
                    </form>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <table id="conversation" class="table table-striped">
                        <thead>
                            <tr>
                                <th>Greetings</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="item in received_messages" :key="item">
                                <td>{{ item }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import SockJS from "sockjs-client";
import Stomp from "webstomp-client";

export default {
  name: "websocketdemo",
  data() {
    return {
      received_messages: [],
      send_message: null,
      connected: false
    };
  },
  methods: {
    send() {
      console.log("Send message:" + this.send_message);
      if (this.stompClient && this.stompClient.connected) {
        const msg = { name: this.send_message };
        this.stompClient.send("/app/hello", JSON.stringify(msg), {});
      }
    },
    connect() {
      this.socket = new SockJS("http://localhost:8080/gs-guide-websocket");
      this.stompClient = Stomp.over(this.socket);
      this.stompClient.connect(
        {},
        frame => {
          this.connected = true;
          console.log(frame);
          this.stompClient.subscribe("/topic/greetings", tick => {
            console.log(tick);
            this.received_messages.push(JSON.parse(tick.body).content);
          });
        },
        error => {
          console.log(error);
          this.connected = false;
        }
      );
    },
    disconnect() {
      if (this.stompClient) {
        this.stompClient.disconnect();
      }
      this.connected = false;
    },
    tickleConnection() {
      this.connected ? this.disconnect() : this.connect();
    }
  },
  mounted() {
    // this.connect();
  }
};
</script>

<style scoped>

</style>

Run the project and test, it should start at 8081 port by default.