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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.