5

I have a following class with one variable of type Long

package com.nm.poc;

public class JSLong{

private Long longValue;

public Long getLongValue() {
    return longValue;
}

public void setLongValue(Long longValue) {
    this.longValue = longValue;
}

public Long testLongValue(Long longValue){
    return longValue;
}

}

I am calling method testLongValue from JavaScript as follows ways

package com.nm.poc;

import java.util.function.Consumer;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

    JSLong jsLong = new JSLong();

    //WORKS
    engine.put("jsLong", jsLong);     
    engine.eval("print(jsLong.testLongValue(20))");

    //Throws ClassCast Integer to Long
    engine.put("jsLong2", (Consumer<Long>)jsLong::testLongValue);
    engine.eval("print(jsLong2(20))");
   }
}

engine.eval("print(jsLong.testLongValue(20))"); works

engine.eval("print(jsLong2(20))"); throw class cast exception

Can I make engine.eval("print(jsLong2(20))"); work for Long type

Exception trace

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
at jdk.nashorn.internal.scripts.Script$1$\^eval\_.:program(<eval>:1)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(Unknown Source)
at com.nm.poc.Main.main(Main.java:20)
Martin Schneider
  • 3,268
  • 4
  • 19
  • 29
Nitesh
  • 97
  • 1
  • 10

1 Answers1

0

First of all: Consumer represents method/function that doesn't return any value. In order to print the returned value You should use Function.

Anyway, using Function will cause the same exception.

//Throws ClassCast Integer to Long
engine.put("jsLong2", (Function<Long, Long>)jsLong::testLongValue);
engine.eval("print(jsLong2(20))");

There must be explicit casting somewhere in the Nashorn code that does work for int/long but obviously doesn't work for Integer/Long.

To make Your example works You can use LongUnaryOperator.

//This works
engine.put("jsLong2",  (LongUnaryOperator)jsLong::testLongValue);
engine.eval("print(jsLong.testLongValue(20))");

LongUnaryOperator uses raw long type instead of Long class, so that It can be cast to/from integer.

You should be aware that there is no 64 bit integer in JS so passing long to js thru Nashorn may cause some isues:

Javascript long integer

Java 8/Javascript (Nashorn) long interoperatiblity

Dominik Kunicki
  • 1,037
  • 1
  • 12
  • 35