Return value from jar file created from Matlab
Asked Answered
V

2

8

I have got a Matlab code which at last calculates a vector of indexes. I used library compiler in order to compile matlab code to a java package .jar file. I exported the jar file in order to run it for my main Java project. The name of the package class is Epidemic. I imported the jar file (add it as an external jar). In main code I tried to create an object of my class (in jar file). I have already defined the name of the class as Epidemic. Thus, my code:

import epidemic.Epidemic;
...
public static void main(String[] args) throws IOException {

    List<Double> list1 = new ArrayList<Double>();
    List<Double> list2 = new ArrayList<Double>();

    Epidemic object = new Epidemic(); 
    object.epidemic(list1, list2);
    System.out.println(list1);
}

I add the .jar file to java project using project->Libraries right click add external jars. Netbeans automatically detects object's methods. However I am getting the following errors:

Exception in thread "main" java.lang.NoClassDefFoundError:  
com/mathworks/toolbox/javabuilder/internal/MWComponentInstance
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at twittertrendsetters.TwitterTrendSetters.main(TwitterTrendSetters.java:70)
Caused by: java.lang.ClassNotFoundException:
com.mathworks.toolbox.javabuilder.internal.MWComponentInstance
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 13 more

What is the issue here? Am I supposed to add something else in order the jar to work properly?

EDIT: I add the .jar file located in MATLABROOT/toolbox/javabuild/jar/javabuild.jar to my classpath and the class it seems to work. Now I am facing another problem. When I print the list1 which based on html docs takes the output of matlab .m file I got an empty arrayList. Matlab function returns an array Nx1 of doubles. How can I parse it correctly to the java arrayList.

My matlab code:

function eP = epidemic() // zero input

graph = dlmread('graph.edges'); //a graph
graph_ids=importdata('cms_V3_id.txt');  // indexes of the graph

for index = 1:length(graph)
 grph(index,1) = find(graph_ids == graph(index,1));
 grph(index,2) = find(graph_ids == graph(index,2));
end
grph(:,3)= graph(:,3);

grph(end + 1, :, :) = [max(max(grph)) max(max(grph)) 1 ];
grph =  spconvert(grph);

[S, prev] = brutte_topk2(grph, 3707); //function approximate pagerank result
eP = graph_ids(S); // returning a list of indexes

I tried to use your approach. I create a table of OBject and parse the result into it.

    Epidemic object = new Epidemic(); 
    Object[] result;
    result = object.epidemic(1);
    System.out.println((Double)result[0]);

However I am getting javabuilder.MWNumericArray cannot be cast to java.lang.Double. When I print just the reuslt

Vanwinkle answered 9/12, 2014 at 8:39 Comment(0)
R
8

There are two things you need to add to the Java project classpath:

  • the deployed JAR file you created from the MATLAB code.
  • Java Builder's own JAR files. If you have MATLAB installed on the target machine, you can find those inside $MATLABROOT\toolbox\javabuilder\jar\javabuilder.jar, otherwise install the appropriate MCR runtime (available for free), and locate the JAR file in a similar path.

See here for the full instructions.


EDIT:

For the sake of completeness, below is a working example.

  1. Assume we have the following MATLAB function that returns a array of numbers.

    epidemic.m

    function list = epidemic()
        list = randi(100, [1, 10]);
    end
    
  2. Using the applicationCompiler MATLAB app, create a new project to build a "Java Package". Add the above function to the project, set class and method names, then build the package. We should get a JAR file, say: Epidemic.jar

  3. Next we create a Java program to test the above package. For example:

    TestEpidemic.java

    import java.util.*;
    import com.mathworks.toolbox.javabuilder.*;  // MATLAB Java Builder
    import Epidemic.*;                           // our compiled package
    
    public class TestEpidemic {
        public double[] getArray() throws MWException {
            Epidemic obj = null;
            Object[] out = null;
            double [] arr = null;
            try {
                obj = new Epidemic();
                out = obj.epidemic(1);  // request one output
                arr = (double[]) ((MWArray)out[0]).getData();
            } catch (MWException e) {
                System.out.println("Exception: " + e.toString());
            } finally {
                MWArray.disposeArray(out);
                obj.dispose();
            }
            return arr;
        }
    
        public static void main (String[] args) {
            try {
                TestEpidemic e = new TestEpidemic();
                double[] arr = e.getArray();
                for(double x : arr) {
                    System.out.println(x);
                }
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }
    
  4. Finally we compile and run the test program:

    javac.exe -classpath "%MATLABROOT%\toolbox\javabuilder\jar\javabuilder.jar";.\Epidemic.jar TestEpidemic.java
    
    java.exe -classpath .;"%MATLABROOT%\toolbox\javabuilder\jar\javabuilder.jar";.\Epidemic.jar TestEpidemic
    

    you should see an array of 10 double numbers printed.

Regnal answered 12/12, 2014 at 4:42 Comment(9)
In matlabroot I have got bot javabuilder/jar folder and javabuilder/jar/win64. Which of the two folder I have got to add to path? Moreover I have got to add it to enviroment path or classpath? Which is the difference?Vanwinkle
@FereRes: No you must add the JAR files to your NetBeans project (add them to the Java classpath), just like you did the other ones. You should pick the version that matches the architecture of the machine, JVM and MATLAB (32-bit or 64-bit).Regnal
Yea I think that this solved the problem. However now I am getting another problem: Exception in thread "main" ... Matlab M-code Stack Trace ... file C:\Users\chrathan\AppData\Local\Temp\chrathan\mcrCache8.3\epidem0\epidemic\epidemic.m, name epidemic, line 20. com.mathworks.toolbox.javabuilder.MWExceptionVanwinkle
@FereRes: that's a runtime exception thrown by the MATLAB code. Could be that you gave the function the wrong kind of input? Check your original code in the epide‌​mic.m file at line 20...Regnal
In .m file in the following which is actually return on list of integers eP function eP = epidemic(). In java code I create an object Epidemic object = new Epidemic(). The next step to use the function epidemic. In the html docs it shows me that there are three ways to use that method. Either using as method arguments two lists, or two Object obj or one integer and one Object. In Matlab code I haven't any argument. So when I am using two lists as argument it shows me the previous error.Vanwinkle
@Armo, the problem was in Matlab code, I compmile again the .m file now it works fine. However As a result I am getting an empty arraylist. I have updated the code.Vanwinkle
@FereRes: it would also help to see the MATLAB code.. What are the expected inputs and outputs? Usually compiled functions are called as result = obj.method(nout, a, b, c, ...) where nout is the number of requested outputs, and the rest of arguments a,b,c,... are the inputs. result should be defined as an object array Object[], then cast each result[i] to a more specific MWArray class depending on the type of outputs (there is support for automatic conversions). This is all explained in the docs.Regnal
@FereRes: MWNumericArray class has a getDoubleData() method to retrieve the double[] values.Regnal
@FereRes: I added a full exampleRegnal
B
7

A JAR file can only return an exit code if it contains a main method. The type of the return value is an integer. You can achieve this if you use System.exit(returnCode).

If you mean that you have another project in which you want to embedd this project, you have to get rid of the right dependencies and just call the method from the JAR you want.

Bharat answered 9/12, 2014 at 8:46 Comment(4)
I ve got a java project and I want to embed there a jar file(from matlab code). Is it possible to create a function in matlab code which will return a vector of integers, and call it to java code from jar?Vanwinkle
@FereRes So you've got a JAR file from matlab. Containing what? Code? Other files? Main method? If it is a normal JAR file with classes you can go to your project and edit the included libraries.Bharat
In Matlab code I got a function which I compile it as a jar using a class name for example class1. How can I see the structure of the jar file? I mean I don't know what it's inside.Vanwinkle
@FereRes Just extract it with 7Zip for example.Bharat

© 2022 - 2024 — McMap. All rights reserved.