4
$\begingroup$

I try to use JLink and Java program for receiving responses from the abstract WebSocket server. WSS not supported by Wolfram Language now, but I can use this java project + JLink for the creating a WebSocket client - simple example of the client here. In Wolfram Language I use this client as following:

Get["JLink`"]; 
ReinstallJava[ClassPath -> <classpath>, CommandLine -> <commandline>]; 
client = JavaNew["ExampleClient", JavaNew["java.net.URI", "wss://host:8888/stream"]]; 
client@connect[]; 

After this in Java console window printing messages from the server. Messages handling in the method onMessage(String message). How can I change the class ExampleClient and method onMessage for the saving result in a DataStructure that created in Wolfram Language?

Dependensies in my environment for the standalone using:
Java ~17 (Default OpenJDK in Wolfram/System Files/Java not supported)
hamcrest-core-1.3.jar
Java-WebSocket-1.5.2.jar
json-20211205.jar
junit-4.12.jar
slf4j-api-1.7.25.jar

All jar-files I got from maven repository

$\endgroup$

1 Answer 1

4
$\begingroup$

I've tested this code with Mathematica's default JDK (version 11.0.12, Mathematica 13.0.1).

Assume I've run an echo server on 127.0.0.1:8000.

Let's import JLink and have a variable to store our result:

Needs["JLink`"];

result = {};

Import Java WebSocket's jar file:

AddToClassPath["C:\\Java-WebSocket-1.5.2.jar"];

Now, you need to define your extended class in Java, like:

import com.wolfram.jlink.*;

import java.net.URI;
import java.util.Map;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.handshake.ServerHandshake;

public class ExampleClient extends WebSocketClient {

  // implement other methods
  // ...

  // send a string on opening
  @Override
  public void onOpen(ServerHandshake handshakedata) {
    send("Hello from java");
    System.out.println("opened connection");
  }

  // manipulate Wolfram variable on receiving message
  @Override
  public void onMessage(String message) {
    KernelLink link = StdLink.getLink();
    if (link != null) {
        try {
            link.evaluate("AppendTo[result,\""+message+"\"]");
        } catch (MathLinkException e) {
            System.out.println("Failed");
            link.clearError();
            link.newPacket();
        }
    }else{
        System.out.println("Null");
    }
  }
}

I couldn't find an easy way to access a defined class, so apply ExternalEvaluate to the above string (" needs to be escaped) and save the output in a variable, like:

temp = ExternalEvaluate["Java", ... ];

Now, the following code will manipulate the result variable in the Wolfram session:

client = JavaNew[temp, JavaNew["java.net.URI", "ws://127.0.0.1:8000"]]
client@connect[]

Checking our variable:

result

(* Out: {"Hello from java"} *)

For better debugging (seeing System.out.print), show the console with:

ShowJavaConsole[]

For further information read Requesting Evaluations by the Wolfram Language.

$\endgroup$
1
  • $\begingroup$ Thank you @ben-izd! $\endgroup$ Commented Mar 11, 2022 at 20:25

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.