Calling standalone application from java MatlabEngine

14 次查看(过去 30 天)
I am developing a microservice that uses Websockets to send data to and from MATLAB functions. On my development machine, I have a jar that opens a socket for listening after starting an Engine instance. When I receive a json message on the socket, it sends this to the engine, along with the state of the session:
WebSocket conn = event.getConn();
String message = event.getMessage();
String attachment = conn.getAttachment();
Object[] output = matlabEngine.feval(2, dispatchCommand, message, attachment);
attachment = (String) output[1];
String result = (String) output[0];
conn.setAttachment(attachment);
conn.send(result);
dispatchCommand is a .m file that processes everything. This runs, and I can launch the jar from the command line (specifying the port), or from a systemd socket service (specifying LD_LIBRARY_PATH as an environment variable).
So now I want to deploy this to a docker container, and I'm trying to figure out how (or if) MATLAB Compiler fits into all of this, or whether all I need to do is use a Docker image with the runtime libraries installed.My thought is to launch the compiled application which reads from and writes to a Unix domain socket, but I don't know if this is any more efficient than matlabEngine.feval.
In either situation, I want the MATLAB process to launch on demand and exit when done. The current implementation starts in about 10 seconds, way less time than it takes the user to enter the data in the form that is sent to the MATLAB routine. While I've written the system to open the Websocket in MATLAB, System.inheritedChannel(); gets clobbered by MATLAB, mazking it impossible to inherit the socket from systemd.

回答(1 个)

Jeff Mandel
Jeff Mandel 2025-11-8,22:24
I persisted.
I had previously figured out how to pass in event handlers:
import org.jeffmandel.websocketserver.*;
try
server = org.jeffmandel.websocketserver.Server();
catch exception
fprintf("%s", exception.message);
end
myServerObj = handle(server,'CallbackProperties');
%#function dispatchMessage
set(myServerObj, 'OnMessageCallback', @dispatchMessage);
I haven't confirmed this, but I think the import of my class causes the jar to get loaded into the standalone app, and the %#function causes dispatchMessage to get scanned for inclusion. To make the 'OnMessageCallback' work, you need several methods in the Server class:
public synchronized void addSocketListener(SocketListener listener) {
if (listeners.isEmpty()) {
listeners.add(listener);
}
}
public synchronized void removeSocketListener(SocketListener listener) {
listeners.remove(listener);
}
public synchronized void dispatchEvent(SocketEvent event) {
for (SocketListener listener : listeners) {
listener.onMessage(event);
}
}
public interface SocketListener extends EventListener {
void onMessage(SocketEvent event);
}
public class SocketEvent extends EventObject {
private String message;
private WebSocket conn;
public SocketEvent(WebSocket source, String message) {
super(source);
this.message = message;
this.conn = source;
}
public String getMessage() {
return this.message;
}
public WebSocket getConn() {
return this.conn;
}
}
So now I build the standalone:
compiler.build.standaloneApplication('doServer.m','AdditionalFiles',{'allstates.mat'});
This carps:
Warning: Your personal MATLAB preferences are set to use the version of Java that is installed on this system. Users of this application may not have the same version of Java installed on their system causing the application to fail. This preference setting has been removed.
>> version -java
'Java is not enabled'
Odd, but
$ java -version
openjdk version "21.0.8" 2025-07-15
and System.getProperty("java.version") reports 21.0.8, so I can live with having to make sure I've got the correct JRE in my Docker build.
I create two systemd files:
# /etc/systemd/system/websocketserver.socket
[Unit]
Description=Socket listener for websocketserver
PartOf=websocketserver.service
[Socket]
ListenStream=127.0.0.1:3000
Accept=false
[Install]
WantedBy=sockets.target
and
# /etc/systemd/system/websocketserver.service
[Unit]
Description=Starts the MATLAB Websocket Server
Requires=websocketserver.socket
After=network.target websocketserver.socket
[Service]
Type=oneshot
WorkingDirectory=/home/jeffemandel/MATLAB-Drive/dise_service
ExecStart=/home/jeffemandel/MATLAB-Drive/dise_service/server/doServer
Environment="LD_LIBRARY_PATH=/usr/local/MATLAB/R2025b/runtime/glnxa64:/usr/local/MATLAB/R2025b/bin/glnxa64:/usr/local/MATLAB/R2025b/sys/os/glnxa64:/usr/local/MATLAB/R2025b/extern/bin/glnxa64"
StandardInput=socket
TimeoutStopSec=10
StandardError=journal
StandardOutput=journal
User=jeffemandel
[Install]
WantedBy=multi-user.target
I enable and start :
sudo systemctl daemon-reload
sudo systemctl enable websocketserver.socket
sudo systemctl start websocketserver.socket
journalctl -u tyrusserver -f
Now when my client connects to port 3000, the .socket activates the oneshot service, which runs my standalone app. The app figures out that it has been called from a socket in the constructor :
import org.java_websocket.WebSocket;
public class Server {
private WebSocketServer matlabSocketServer;
private List<SocketListener> listeners = new ArrayList<>();
public Server() throws IOException {
Channel channel = System.inheritedChannel();
if (channel == null) {
int port = 3000;
matlabSocketServer = new WebSocketServer(new java.net.InetSocketAddress(port));
} else if (channel instanceof ServerSocketChannel) {
matlabSocketServer = new WebSocketServer((ServerSocketChannel) channel);
} else {
throw new IOException("No channel available");
}
matlabSocketServer.start();
}
}
Note that you can call the standalone app from the command line; useful for testing. The java library makes use of the Java_websocket library.
I'll consider putting the MATLAB code on File Exchange, and maybe even put the java code on Github if there's interest.

类别

Help CenterFile Exchange 中查找有关 Java Package Integration 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by