Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value from jar file created from Matlab

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

like image 265
Jose Ramon Avatar asked Dec 09 '14 08:12

Jose Ramon


2 Answers

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.

like image 186
Amro Avatar answered Oct 02 '22 22:10

Amro


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.

like image 37
Marcel Avatar answered Oct 02 '22 22:10

Marcel