javawebsocketjavalin

Javalin Websocket Client silently fails to connect


I'm trying to create a Websocket client that talks to a Websocket server. My server code seems to run ok as I can connect to it using a web based client. But my Java implementation just fails silently to connect, then throws an exception on send().

This is my scratch rig for trying this out:

UPDATE: I found the problem was the example code was using a deprecated version of DRAFT. I updated and can now get the two threads to talk to each other. I've updated the code to show the working version.

One question I have now is how do I shut down the server?

package com.github.museadmin.api;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.net.URISyntaxException;

public class WsThreadRig {

  private static final String threadName = "ism_thread";

  public static void main(String[] args) throws InterruptedException, URISyntaxException {

    ISMWebSocket server = new ISMWebSocket.Builder()
        .port(7000)
        .uri("/websocket")
        .identity("server")
        .host("localhost")
        .build();

    Thread thread = new Thread (server, threadName);
    thread.start ();
    Thread.sleep(1000L);

    WebSocketClient mWs = new WebSocketClient(
        new URI( "ws://127.0.0.1:7000/websocket" ),
        new Draft_6455()
    )
    {
      @Override
      public void onMessage( String message ) {
        System.out.println(
            String.format("Message received from server (%s)",
            message)
        );
      }

      @Override
      public void onOpen( ServerHandshake handshake ) {
        System.out.println( "Client opened connection" );
      }

      @Override
      public void onClose( int code, String reason, boolean remote ) {
        System.out.println(
            String.format("Client closed connection because (%s)", reason)
        );
      }

      @Override
      public void onError( Exception ex ) {
        ex.printStackTrace();
      }

    };

    //open websocket
    mWs.connectBlocking();
    Thread.sleep(1000L);
    String message = "Test message from client";
    //send message
    mWs.send(message);
    mWs.close();
  }
}

I'll include the Websocket builder code below but as I said, I can connect to it ok on ws://localhost:7000/websocket using https://websocketking.com/ when I run main and am sitting in the loop with the server running in the background thread.

package com.github.museadmin.api;

import io.javalin.Javalin;

import java.util.Optional;

public class ISMWebSocket implements Runnable {

  private Integer port;
  private String uri;
  private String identity;
  private String host;

  private ISMWebSocket(Builder builder) {
    this.port = builder.port;
    this.uri = builder.uri;
    this.identity = builder.identity;
  }

  @Override
  public void run() {
    Javalin app = Javalin.create().start(this.host, this.port);
    app.ws(this.uri, ws -> {
      ws.onConnect(ctx -> {
          System.out.println("Client connected to server");
          ctx.send("Test message from server");
        }
      );
      ws.onClose(ctx -> {
          System.out.println("Client disconnected from server");
        }
      );
      ws.onMessage(ctx -> System.out.println(
          String.format("Message received from client (%s)", ctx.message())
        )
      );
      ws.onError(ctx -> {
        System.out.println(
            String.format("ERROR: (%s)", ctx.error().getMessage())
        );
      });
    });
  }

  public Optional<Integer> getPort() {
    return Optional.ofNullable(port);
  }

  public Optional<String> getUri() {
    return Optional.ofNullable(uri);
  }

  public Optional<String> getIdentity() {
    return Optional.ofNullable(identity);
  }

  public Optional<String> getHost() {
    return Optional.ofNullable(host);
  }


  public static class Builder {
    private Integer port;
    private String uri;
    private String identity;
    private String host;

    public Builder port(Integer port) {
      this.port = port;
      return this;
    }

    public Builder uri(String uri) {
      this.uri = uri;
      return this;
    }

    public Builder identity(String identity) {
      this.identity = identity;
      return this;
    }

    public Builder host(String host) {
      this.host = host;
      return this;
    }

    public Builder fromPrototype(ISMWebSocket prototype) {
      port = prototype.port;
      uri = prototype.uri;
      identity = prototype.identity;
      host = prototype.host;
      return this;
    }

    public ISMWebSocket build() {
      return new ISMWebSocket(this);
    }
  }
}

This is the output:

Client opened connection
Client connected to server
Message received from server (Test message from server)
Message received from client (Test message from client)
Client disconnected from server
Client closed connection because ()

Brad

PS:

I changed the connection to a blocking connection and added a print out of the reason in the onClose() method for the client which now reports:

org.java_websocket.drafts.Draft_10@2025740c refuses handshake

I don't know what the drafts library is doing to be honest, so will read up on that next.


Solution

  • So the DRAFT_10 reference was deprecated. Updated it to the latest release

    WebSocketClient mWs = new WebSocketClient(
            new URI( "ws://127.0.0.1:7000/websocket" ),
            new Draft_6455()
        )