0 Replies Latest reply on Nov 19, 2016 2:44 AM by jdalecki-JavaNet

    Invoking invokeFunction("someJSbject") twice both have same properties

    jdalecki-JavaNet

      Hi Guys,

      We are moving from rhino to javax.script. Well you can guess that is a major step in our development of our software. Of course I didn’t expect it to just be a breeze. I have found a very strange feature of javax.script package.

      I have a very simple js script:

      load("nashorn:mozilla_compat.js");

      function JSDevice() {

                     this.deviceType = "";

                     this.deviceId = "";

                     return this;

      }

      And a Java code:

      import java.io.File;

      import java.io.FileReader;

      import java.io.Reader;

      import java.util.ArrayList;

      import java.util.List;

       

      import javax.script.Bindings;

      import javax.script.Invocable;

      import javax.script.ScriptEngine;

      import javax.script.ScriptEngineManager;

       

      /**

      * @author jdalecki

      *

      */

      public class Main {

       

        /**

         * @param args

         */

        public static void main(String[] args) {

          Main m = new Main();

          m.exposeTheBug();

        }

       

        private void exposeTheBug() {

          ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("JavaScript");

          List<Bindings> allDevices = new ArrayList<Bindings>();

          String scriptFilename = <point to the folder where you saved the js script file>

       

          try {

            File fName = new File(scriptFilename);

            Reader scriptReader = new FileReader(fName);

            engine.eval(scriptReader);

            Invocable invocable = (Invocable) engine;

       

            System.out.println("Creating two different JSDevice objects:");

            System.out.println("\tFirst with the properties:");

            System.out.println("\t\tdeviceType=JSDevice1.type");

            System.out.println("\t\tdeviceId=JSDevice1.id");

           

            System.out.println("\tSecond with the properties:");

            System.out.println("\t\tdeviceType=JSDevice2.type");

            System.out.println("\t\tdeviceId=JSDevice2.id");

       

            // Step 1

            System.out.println("First object created:");

            Bindings jsDevice1 = (Bindings)invocable.invokeFunction("JSDevice");

            jsDevice1.put("deviceType", "JSDevice1.type");

            jsDevice1.put("deviceId", "JSDevice1.id");

            for(String key :  jsDevice1.keySet())

            {

              if(key.equals("deviceType") || key.equals("deviceId"))

              {

                Object obj = jsDevice1.get(key);

                System.out.println(obj);

              }

            }

            allDevices.add(jsDevice1);

            System.out.println("");

       

            // Step 2

            System.out.println("Second object created:");

            Bindings jsDevice2 = (Bindings)invocable.invokeFunction("JSDevice");

            jsDevice2.put("deviceType", "JSDevice2.type");

            jsDevice2.put("deviceId", "JSDevice2.id");

            for(String key :  jsDevice2.keySet())

            {

              if(key.equals("deviceType") || key.equals("deviceId"))

              {

                Object obj = jsDevice2.get(key);

                System.out.println(obj);

              }

            }

            allDevices.add(jsDevice2);

       

            System.out.println("");

       

            // Summary

            System.out.println("In summary: Both JSDevice objects point to the properties I set in the second JSDevice object, why?");

           

            for(Bindings b : allDevices)

            {

              for(String key : b.keySet())

              {

                if(key.equals("deviceType") || key.equals("deviceId"))

                {

                  System.out.println("Device: "+key+" Value="+b.get(key));

                }

              }

            }

          } catch (Exception ex) {

            ex.printStackTrace();

          }

        }

      }

       

      The problem description:

      As you can see I am creating sequentially two Java Script object calling engine invokeFunction("JSDevice"). That is all good so far.
      However when I set the properties (“deviceType” and “deviceId”) on both of them, the last setting seems to overwrite the properties of the first object.
      Both “JSDevice” objects point to the properties I set in the second JSDevice object, why?

       

      Regards,

      Janusz