Search code examples
angularwebsocketquarkusjava-websocket

How can I listen to a Quarkus Websocket using Angular 9?


As the questions suggests, I want to build a service that syncs JSON data between users using a Websocket. But I am quite new to websockets, so I need your help.

I use the following Versions:

Frontend: Angular: 9.1.0

Backend: Quarkus: 1.3.2.Final + Quarkus-undertow-websockets

I have the following code in an Angular Service:

import {Injectable} from '@angular/core';


@Injectable({
  providedIn: 'root',
})
export class SocketService {

  private ws: any;

  constructor() {
  }

  public connect(): void {

    this.ws = new WebSocket('ws://localhost:8080/sync/breit');

    this.ws.onmessage = (msg) => {
      console.log(msg);
    };
  }

  public sendData(data: any): void {
    this.ws.send('/' + name, {}, 'Testmessage');
  }
}

The function connect gets called in an ngOninit() and sendData() when a button is pressed.

Now, that is the backend code:

package io.sync.websocket;

import org.jboss.logging.Logger;

import javax.enterprise.context.ApplicationScoped;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/sync/{username}")
@ApplicationScoped
public class SyncSocket {

    private static final Logger LOG = Logger.getLogger(SyncSocket.class);
    Map<String, Session> sessions = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessions.put(username, session);
    }

    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessions.remove(username);
    }

    @OnError
    public void onError(Session session, @PathParam("username") String username, Throwable throwable) {
        sessions.remove(username);
        LOG.error("onError", throwable);
    }

    @OnMessage
    public void onMessage(String message, @PathParam("username") String username) {
        System.out.println("Message came through");
        broadcast(message);
    }

    private void broadcast(String message) {
        sessions.values().forEach(s -> {
            s.getAsyncRemote().sendObject(message, result -> {
                if (result.getException() != null) {
                    System.out.println("Unable to send message: " + result.getException());
                }
            });
        });
    }

}

I have this code from the Quarkus Websocket Tutorial. Just modified it a little bit.

Now, when I hit the send button, which calls the sendData() function in the Service, I expect to receive Testmessage, but I just get /:

Output in Webconsole:

Output in Webconsole

I do not know how to add an additional "listener" URL to Quarkus, I can just define the ServerEndpoint. In Spring boot it would be the @SendTo('URL_COMES_HERE') annotation. Does something like this exist in Quarkus?


Solution

  • Please check your sendData method. I think the behavior of data being "/" is expected. Where is "name" coming from? it simply seems to be an empty string at this point. Also, regarding "Testmessage": If you check the Websocket.send method, you will find that there is only a single parameter to the method; so the "Testmessage" parameter will be ignored.