VMware Aria

 View Only
Expand all | Collapse all

Automatic Conversion of Java Data Types in JavaScript Data Types

  • 1.  Automatic Conversion of Java Data Types in JavaScript Data Types

    Posted Dec 27, 2022 08:32 AM
    Edited by Stefan Schnell May 07, 2024 12:00 AM

    The last few days I've been experimenting of using native Java data types in the JavaScript execution environment of vRealize Automation. Here, a behavior is visible that I cannot explain.

    I tried to output all types of all Java primitive data types and the non-primitive data type string. But they were converted into JavaScript data types.

    getSystemProperties5.jpg

    If I tried the same with Rhino engine in the REPL mode, but here the data type object is always correctly returned.

    getSystemProperties4.jpg

    Also I tried the same approach directly in the vco-app-server container of the k8s cluster, with exactly the same result. On this way I can be quite sure that the type conversion is not dependent on the OS or the JDK.

    StefanSchnell_0-1673676816166.png

     

     

    var varBool = java.lang.Boolean.TRUE;
    java.lang.System.out.println(typeof varBool + ": " + varBool);
    var testBool = org.mozilla.javascript.Context.jsToJava(varBool, java.lang.Boolean);
    java.lang.System.out.println(typeof testBool + ": " + testBool);
    typeof java.lang.Boolean.TRUE;

     

     

    If the data type object is returned, I can access to the corresponding methods. With the conversion into the JavaScript data types, I cannot use these methods.

    This behavior can be reproduced with the following image:

    getSystemProperties1.jpg

    getSystemProperties2.jpg

    In the first step, a variable of type Boolean is created and its type is output. In the second step I tried to convert it back to the Java data type Boolean, but with the same result as described above. In the third step I used a non-primitive data type, it delivers object but a method call occurs the error message, that the object can not convert into Property. A type conversion seems to have been made here as well.

    How to prevent automatic conversion, aka force conversion, into JavaScript data types? Or the other way around, how can I use native Java data types in the JavaScript execution environment?

    Thanks for hints and tips.

    Addendum 03.05.2023

    How to handle the primitive data types and strings can be read in the reply. Now there is still the question of how to handle the non-primitive data types.

    Addendum 04.06.2023

    StefanSchnell_0-1685871575682.png

     

     

    // Begin----------------------------------------------------------------
    
    try {
    
      var ints = java.lang.reflect.Array.newInstance(java.lang.Integer, 1);
      System.log(ints.constructor.name); //Array
      // System.log(ints.getClass()); // TypeError
    
      var int = java.lang.Integer(2147483647);
      // System.log(int.constructor.name); // TypeError
      System.log(int.getClass()); // class java.lang.Integer
    
    } catch (exception) {
      System.log(exception);
    }
    
    // End------------------------------------------------------------------

     

     

    Addendum 17.09.2023

    It seems that the Dunes framework of Aria Automation changes native Java data types into in its opinion equivalent JavaScript data types automatically, Here an example:

    StefanSchnell_0-1694923410718.png

     

     

    /**
     * Hint: The Method getClass is inherited from the class java.lang.Object
     *       and it is available in both classes, because both extends the
     *       Object class.
     */
    
    /**
     * The variable of the java.io.File class is automatically type casted
     * into the JavaScript data type File from the Dunes Framework.
     */
    var javaIoFile = java.io.File.createTempFile("vco-", null);
    System.log(javaIoFile.constructor.name);
    // System.log(javaIoFile.getClass().getName());
    // TypeError: Cannot find function getClass in object
    // The method getClass is not available here, so this variable could not
    // be from type java.io.File.
    
    /**
     * The variable of the java.nio.file.Files class not type casted,
     * it is a Java data type.
     */
    var javaNioFile = java.nio.file.Files.createTempFile("vco-", null);
    // System.log(javaNioFile.constructor.name);
    // TypeError: Cannot read property "name" from undefined
    System.log(javaNioFile.getClass().getName());

     

     

    The result of creating a temporary file using the java.io.File class is a JavaScript data type File from the Dunes Framework. If I do the same with the java.nio.file.Files class, then a native Java data type is returned. In the latter case, the native Java class methods can be used. This approach is not very sustainable, especially when using native Java data types in arrays. Because any array is automatically type casted into a JavaScript array by the Dunes framework. This makes the result unusable for further use in the native Java context.

    StefanSchnell_1-1694924824155.png

    Addendum 22.12.2023

    List of native types, which are automatically type casted.

    Native TypeConverted Type
    java.lang.reflect.ArrayArray
    java.io.FileFile
    java.util.PropertiesProperties
    java.util.HashMapProperties
    java.net.URLURL
    java.util.DateDate

     



  • 2.  RE: Automatic Conversion of Java Data Types in JavaScript Data Types

    Posted Mar 29, 2023 07:06 PM
    Edited by Stefan Schnell May 07, 2024 12:00 AM

    In the context of my analyses here I read an answer of an interesting old post about inconsistent behaviour when accessing java.util.*-classes.  wrotes: "When you try to invoke a method, the Rhino engine tries to call this method on this NativeObject ... It is a generic problem. If you create a new ArrayList, for example, the JS engine will map it to a native array and you won’t be able to call ArrayList’s methods." Here it is the other way around. Here my code to check the behaviour:

     

    // Begin----------------------------------------------------------------
    
    var javaLangBoolean = java.lang.Boolean.TRUE;
    System.log("Boolean is " + typeof javaLangBoolean + " from " + javaLangBoolean.getClass());
    
    var javaLangByte = java.lang.Byte.valueOf(127);
    System.log("Byte is " + typeof javaLangByte + " from " + javaLangByte.getClass());
    
    var javaLangShort = java.lang.Short.valueOf(32767);
    System.log("Short is " + typeof javaLangShort + " from " + javaLangShort.getClass());
    
    var javaLangInteger = java.lang.Integer.valueOf(2147483647);
    System.log("Integer is " + typeof javaLangInteger + " from " + javaLangInteger.getClass());
    
    var javaLangLong = java.lang.Long.valueOf(9223372036854775295);
    System.log("Long is " + typeof javaLangLong + " from " + javaLangLong.getClass());
    
    var javaLangFloat = java.lang.Float.valueOf(java.lang.Math.PI);
    System.log("Float is " + typeof javaLangFloat + " from " + javaLangFloat.getClass());
    
    var javaLangDouble = java.lang.Double.valueOf(java.lang.Math.PI);
    System.log("Double is " + typeof javaLangDouble + " from " + javaLangDouble.getClass());
    
    var javaLangString = java.lang.String("Hello World");
    System.log("String is " + typeof javaLangString + " from " + javaLangString.getClass());
    
    // End------------------------------------------------------------------

     

    In the debugger, the above statements are confirmed.

    vra_datatypes_debugger.jpg

    This is exactly the opposite of the behavior we see in the vRA.

    var_datatypes_script.jpg

    The getClass method cannot be found, because java.lang.Boolean has been converted into the JavaScript data type boolean.

     

    Addendum 03.05.2023

    The behavior of Rhino Engine differs, when it used directly and when it used in Aria Automation. If the valueOf() method, which delivers an instance of a value, is omitted, the native Java data types are used, without force conversion. The following code works without any problems:

     

    // Begin----------------------------------------------------------------
    
    var javaLangBoolean = java.lang.Boolean(java.lang.Boolean.TRUE);
    System.log("Boolean is " + typeof javaLangBoolean + " from " + javaLangBoolean.getClass());
    
    var javaLangByte = java.lang.Byte(127);
    System.log("Byte is " + typeof javaLangByte + " from " + javaLangByte.getClass());
    
    var javaLangShort = java.lang.Short(32767);
    System.log("Short is " + typeof javaLangShort + " from " + javaLangShort.getClass());
    
    var javaLangInteger = java.lang.Integer(2147483647);
    System.log("Integer is " + typeof javaLangInteger + " from " + javaLangInteger.getClass());
    
    var javaLangLong = java.lang.Long(9223372036854775295);
    System.log("Long is " + typeof javaLangLong + " from " + javaLangLong.getClass());
    
    var javaLangFloat = java.lang.Float(java.lang.Math.PI);
    System.log("Float is " + typeof javaLangFloat + " from " + javaLangFloat.getClass());
    
    var javaLangDouble = java.lang.Double(java.lang.Math.PI);
    System.log("Double is " + typeof javaLangDouble + " from " + javaLangDouble.getClass());
    
    var javaLangString = java.lang.String("Hello World");
    System.log("String is " + typeof javaLangString + " from " + javaLangString.getClass());
    
    // End------------------------------------------------------------------

     

    It delivers this result:

    Boolean ist object from class java.lang.Boolean
    Byte is object from class java.lang.Byte
    Short is object from class java.lang.Short
    Integer is object from class java.lang.Integer
    Long is object from class java.lang.Long
    Float is object from class java.lang.Float
    Double is object from class java.lang.Double
    String is object from class java.lang.String

    On this way the native primitive data types and strings of Java can be used in the Rhino JavaScript engine in Aria Automation.
    Note the different behavior of using Rhino Engine directly and in the context of Aria Automation.