1

I have the following method in the file test.js:

function avg(input, period) {
var output = []; 
if (input === undefined) {
      return output;
} 
var i,j=0;
 for (i = 0; i < input.length- period; i++) {
    var sum =0;
    for (j = 0; j < period; j++) {
        //print (i+j)
        sum =sum + input[i+j];
        }
    //print (sum + " -- " + sum/period)
    output[i]=sum/period;        
}

 return output;
 }

I want to pass an array from java to this function and to get the js output array in java. I used the following java code:

double[] srcC = new double[] { 1.141, 1.12, 1.331, 1.44, 1.751, 1.66, 1.971, 1.88, 1.191, 1.101 };

    try {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("nashorn");

        String location = "test.js";
        engine.eval("load(\"" + location + "\");");
        Invocable invocable = (Invocable) engine;
        // double[] a = (double[]) invocable.invokeFunction("avg", srcC, 2);

        System.out.println("obj " + invocable.invokeFunction("avg", srcC, 2));
    } catch (Exception ex) {
        LOGGER.error(ex.getLocalizedMessage());
    }

I am able to see the output of the avg js function but I do not know how to get the js output arrays from the js avg function in java

Any support is appreciated.

Best Regards, Aurelian

2 Answers 2

7

The return type from Invocable.invokeFunction is implementation defined. The Nashorn scripting engine returns an instance of an object that implements jdk.nashorn.api.scripting.JSObject

This interface has a method Collection<Object> values(), so the only required changes are to cast the result of invokeFunction and then extract the collection of values:

 JSObject obj = (JSObject)invocable.invokeFunction("avg", srcC, 2);
 Collection result = obj.values();
 for (Object o : result) {
      System.out.println(o);
 }

output:

1.1305
1.2255
1.3855
1.5955
1.7054999999999998
1.8155000000000001
1.9255
1.5354999999999999
Sign up to request clarification or add additional context in comments.

1 Comment

I just saw your answer. Is better then mine. thanks alot
2

Thanks for your replies. The following code is better because uses the java 8 js engine instead of rhino from previous java versions:

    double[] output = {};
    try {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("nashorn");

        String locationTemp = "D:/test.js";
        engine.eval("load(\"" + locationTemp + "\");");
        Invocable invocable = (Invocable) engine;

        ScriptObjectMirror obj = (ScriptObjectMirror) invocable.invokeFunction("avg",
        input, period);

        Collection<Object> values = obj.values();
        if (values.size() == 0) {
            return output;
        }
        output = new double[values.size()];
        int i = 0;
        for (Iterator<Object> iterator = values.iterator(); iterator.hasNext();) {
            Object value = iterator.next();
            if (value instanceof Double) {
                Double object = (Double) iterator.next();
                output[i] = object;
            }
        }

    } catch (NullPointerException | NoSuchMethodException | ScriptException ex) {
        log.error(ex.getLocalizedMessage());
    }

Thanks ninad for his quickly answer

Best Regards, Aurelian,

2 Comments

You have Java 8 - no need to use an explicit interator, just use for (Object value: values) { ... } as I did in my answer. Also, you forgot to increment i ... ;-)
indeed... i observed that i forgot the increment. Thanks again for your answer.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.