views:

580

answers:

3

I am utilizing the javax.scripting with Rhino in this project.

I have a Java method that returns a Java Object (Double, Long, Integer, etc). I want to call that method from javascript and reference the result as a Javascript primitive type. However, javacript recognizes the return type as an Object.

How do I force it to convert to a javascript primitive?

This question is very similar to http://groups.google.com/group/mozilla.dev.tech.js-engine.rhino/browse%5Fthread/thread/2f3d43bb49d5288a/dde79e1aa72e1301

The problem with that is how do I get a reference to the context and the WrapFactory?

Sample Code:

public class data 
{ 
   Double value = 1.0d; 
   public Number get()  {  return value; } 
} 


  public static void main(String[] args) 
    { 
            ScriptEngine engine = new ScriptEngineManager().getEngineByName ("rhino"); 
            data data = new data(); 
            try 
            { 
                    engine.eval("function test(data) { return data.getD('value1') + 5;};"); 
                    System.out.println("Result:" + ((Invocable)engine).invokeFunction("test", data)); 
            } 
            catch (Exception e) 
            { 
                    e.printStackTrace(); 
            } 
    }

Output: Result: 15

+1  A: 

Try the following

 public static void main(String [] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName ("rhino"); 
        data data = new data();
        Context.enter().getWrapFactory().setJavaPrimitiveWrap(false);

        try 
        { 
                engine.eval("function test(data) { return data.get('value1') + 5;};"); 
                System.out.println("Result:" + ((Invocable)engine).invokeFunction("test", data)); 
        } 
        catch (Exception e) 
        { 
                e.printStackTrace(); 
        } 
    }

    public static class data 
    { 
       Double value = 1.0d; 
       public Number get(String arg)  {  return value; } 
    }


Alternatively, you could modify the javascript function to explicitly cast the value to a number:

function test(data) { return parseInt(data.get('value1'), 10) + 5;}
Kevin
That gives me a NullPointerException. Context.getCurrentContext() is null
Tazzy531
Edited to provide correct implementation
Kevin
No effect. Still get: Result: 15
Tazzy531
Double check, that code gives me 6.0
Kevin
Sorry, my previous response was before you update with the "alternatively" part.Hmm... the alternative works! It's less than ideal.. but it works.I'm going to leave this question open a couple more days in case there is a more formal way of doing this that's not so work-around
Tazzy531
Ya, it looks like it's being passed in as a string. Try casting as @Kevin suggested or with `engine.eval("function test(data) { return (+data.getD('value1')) + 5;};");`
Justin Johnson
A: 

Use the following as the output in your JavaScript code :

function aFunction(data)
{
  return parseInt(data);
}
A: 

I developed this application where you enter a set of mathematical formulas that will be evaluated by the JavaScript engine built into Java 6, which I believe is a port of rhino. The idea was that we would have a set of maps and these maps would contain variables, such as:

MAP["VALUE 1"] MAP["VALUE 2"]

I used that approach as some of the expressions for the formulas came from variables that were under my control and that could be invalid JS identifiers. My first approach was to declare a map and add it to the JS engine, but it failed in the same way that it's failing with you - it was interpreting it as a string, and not as a number.

The solution was to parse the formula, figure out what variables are being used by it, and then declare the object inside the JS engine.

Something like this:

var MAP = new Object(); MAP["VALUE 1"] = 1; MAP["VALUE 2"] = 2;

And then MAP["VALUE 1"] + MAP["VALUE 2"] will return 3, and not 12.

There may be a better solution around, but once you go around the initial coding/ parsing, the above will always work. In our case there's a phase where we execute the "declarative" statements, and another phase where we execute the formulas. The JS engine is REALLY fast, so it's not a problem for us.

Ravi Wallau