Using com.mathwo​rks.matlab​.types.Str​uct in servlet

2 views (last 30 days)
I am trying to pass environment values to a MATLAB routine as a struct. I have tried this on both my Mac (2020b) and my Linux server (2020a). My /opt/tomcat/bin/setenv.sh properly sets MATLABROOT and [Dy]LD_LIBRARY_PATH. I have compiled a class:
mcc -W 'java:testStruct_java,testStruct' -d '/home/jeffemandel/testStruct/matlab/target/lib' testStruct.m
function [names] = testStruct(input)
names = fieldnames(input);
end
In my Maven pom.xml I put a dependency for javabuilder.jar. The compilation fails:
package com.mathworks.matlab.types does not exist
In MATLAB on the Linux server:
>> a = com.mathworks.matlab.types.Struct();
>> a.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
ans = /usr/local/MATLAB/R2020a/java/jar/matlab.jar
I add the dependency for this jar, and Maven compiles, installs, and deploys my war. In my servlet, I construct a struct:
log.info("fContext init");
Struct fContext = new Struct("test", "struct");
log.info("fContext: " + fContext.toString());
I call the servlet from my browser while running tail -f /opt/tomcat/logs/catalina.out on the server, and the process dies after fContext init. No core dump, stacktrace, etc. Trust me, I've been calling MATLAB from servlets for years, and I've never had it die silently until trying to use this class. OK, I write a really simple java program:
import com.mathworks.matlab.types.*;
public class structTest {
public static void main(String[] args)
{
Struct myStruct = new Struct("a","b");
System.out.println("myStruct: " + myStruct.toString());
}
}
javac -classpath .:/usr/local/MATLAB/R2020a/java/jar/matlab.jar structTest.java
java -classpath .:/usr/local/MATLAB/R2020a/java/jar/matlab.jar structTest
Exception in thread "main" java.lang.NoClassDefFoundError: com/mathworks/mvm/MvmFactory
at com.mathworks.matlab.types.Struct.<init>(Struct.java:48)
at structTest.main(structTest.java:7)
mvm seems to be in matlabengine:
java -classpath .:/usr/local/MATLAB/R2020a/java/jar/matlab.jar:/usr/local/MATLAB/R2020a/extern/engines/java/jar/engine.jar structTest
myStruct: com.mathworks.matlab.types.Struct@3
However, adding this dependency to the pom.xml doesn't resolve the problem. I'll admit I'm new at maven, but I had the servelet compiling and running just fine before I got the bright idea to pass in the environment variables in a struct. How can I improve on my results?

Answers (1)

Jeff Mandel
Jeff Mandel on 29 Nov 2020
I'm still unable to utilize com.mathworks.matlab.types.Struct, but I figured out how to do what I wanted with com.mathworks.toolbox.javabuilder.MWStructArray using the fromMap static method:
try {
Context theContext = new InitialContext();
Map<String,Object> contextMap = new HashMap<String,Object>();
NamingEnumeration<Binding> list = theContext.listBindings("java:comp/env");
while (list.hasMoreElements()) {
Binding binding = list.next();
contextMap.put(binding.getName(),binding.getObject());
}
fContextStruct = MWStructArray.fromMap(contextMap);
Object[] result = new Object[1];
result = fTestStruct.testStruct(1, fContextStruct);
} catch (NamingException e) {
log.error("Naming error reading context");
} catch (Exception e) {
log.error("Other error: " + e.getMessage());
}
}
This takes the environment variables defined in META-INF/context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="simtime"
value="4"
type="java.lang.Double"/>
<Environment name="xlabel"
value="Time (min)"
type="java.lang.String"/>
</Context>
and creates a structure:
context =
struct with fields:
simtime: 4
xlabel: "Time (min)"
Note that the only dependency needed is javabuilder

Categories

Find more on Java Package Integration in Help Center and File Exchange

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!