Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8141386

Unable to pass values to java functions which takes wrapper objects as arguments

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 9
    • 8u51
    • javafx
    • web
    • x86_64
    • linux

        FULL PRODUCT VERSION :
        java version "1.8.0_65"
        Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
        Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)


        ADDITIONAL OS VERSION INFORMATION :
        Linux linux-hj5y 3.11.10-29-desktop #1 SMP PREEMPT Thu Mar 5 16:24:00 UTC 2015 (338c513) x86_64 x86_64 x86_64 GNU/Linux

        A DESCRIPTION OF THE PROBLEM :
        I'm writing a connector for a solution written in JavaScript with a library written in Java. Several methods of this library are invoked from JavaScript scripts.
        When I invoke methods that have arguments java.lang.Double type, the argument values ​​are being converted to null.
        If these methods use double native types as arguments , it works perfectly.

        I made a simple class to exemplify:


        public class SimpleJavaObject {

            private Double doubleAttribute = null;
            
            private final StringBuilder sbDebugText = new StringBuilder();

            public SimpleJavaObject() {

            }
            
            public void setDoubleAttribute(Double doubleAttributeArgument) {
                debug("Double setter: "+doubleAttributeArgument);
                doubleAttribute = doubleAttributeArgument;
            }

        // public void setDoubleAttribute(double doubleAttributeArgument) {
        // debug("double setter: "+doubleAttributeArgument);
        // doubleAttribute = doubleAttributeArgument;
        // }

        // public void setDoubleAttribute(Object doubleAttributeArgument) {
        // debug("Object setter: "+doubleAttributeArgument);
        // doubleAttribute = (Double) doubleAttributeArgument;
        // }

        // public void setDoubleAttribute(String doubleAttributeArgument) {
        // debug("String setter: "+doubleAttributeArgument);
        // doubleAttribute = Double.valueOf(doubleAttributeArgument);
        // }

            public Double getDoubleAttribute() {
                return doubleAttribute;
            }
            
            private void debug(String str) {
                sbDebugText.append(str);
                sbDebugText.append("\n");
            }
            
            public String getDebugText() {
                return sbDebugText.toString();
            }

        }

        And a simple html page with one simple script:


        <!DOCTYPE html>
        <html>
            <head>
                <title>WebView tests</title>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <script type="text/javascript">
                    
                    var simpleJavaObject = null; // setted from outside like jsWindow.setMember("simpleJavaObject", new SimpleJavaObject());
                    function test() {
                        alert("simpleJavaObject: " + simpleJavaObject); // shows - simpleJavaObject: webviewtests.SimpleJavaObject@8abb96e

                        simpleJavaObject.setDoubleAttribute(15.5); // try to change the attribute value

                        alert("simpleJavaObject.getDoubleAttribute(): " + simpleJavaObject.getDoubleAttribute()); // shows - simpleJavaObject.getDoubleAttribute(): null

                        alert("Test summary:\n"+simpleJavaObject.getDebugText()); // Shows - Test summary:
                                                                                  // Double setter: null
                                                                                  // indicating the setter invoked
                    }

                </script>
            </head>
            <body>
                
            </body>
        </html>


        As I uncomment the overloaded setters (keeping commented the method with native double argument) I have the following precedence:

         - setDoubleAttribute(Object doubleAttributeArgument)
         - setDoubleAttribute(String doubleAttributeArgument)
         - setDoubleAttribute(Double doubleAttributeArgument) - with doubleAttributeArgument = null

        The question is: Why this method only works with native double, String and Object, and not work with java.lang.Double?

        Many thanks in advance for your attention.


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Call any method with java.lang.Double or java.lang.Integer argument from html page using javascript inside a webview component.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Show the message with 15.5 value.
        ACTUAL -
        Show the message with null value.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        // Create all classes and resources in the same package named webviewtests in a simple JavaFX project

        // Main class WebViewTests.java


        package webviewtests;

        import javafx.application.Application;
        import javafx.fxml.FXMLLoader;
        import javafx.scene.Parent;
        import javafx.scene.Scene;
        import javafx.stage.Stage;

        /**
         *
         * @author Marcos Martinewski Alves
         */
        public class WebViewTests extends Application {
            
            @Override
            public void start(Stage stage) throws Exception {
                Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
                
                Scene scene = new Scene(root);
                
                stage.setMaximized(true);
                stage.setScene(scene);
                stage.show();
            }

            /**
             * @param args the command line arguments
             */
            public static void main(String[] args) {
                launch(args);
            }
            
        }

        // FXMLDocument.xml

        <?xml version="1.0" encoding="UTF-8"?>

        <?import java.lang.*?>
        <?import java.util.*?>
        <?import javafx.scene.*?>
        <?import javafx.scene.control.*?>
        <?import javafx.scene.layout.*?>

        <StackPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="webviewtests.FXMLDocumentController">
            <javafx.scene.web.WebView fx:id="webview"/>
        </StackPane>

        // FXMLDocumentController.java

        package webviewtests;

        import java.net.URL;
        import java.util.ResourceBundle;
        import javafx.beans.value.ObservableValue;
        import javafx.concurrent.Worker;
        import javafx.fxml.FXML;
        import javafx.fxml.Initializable;
        import javafx.scene.web.WebErrorEvent;
        import javafx.scene.web.WebEvent;
        import javafx.scene.web.WebView;
        import javax.swing.JOptionPane;
        import netscape.javascript.JSObject;

        /**
         *
         * @author Marcos Martinewski Alves
         */
        public class FXMLDocumentController implements Initializable {

            @FXML
            private WebView webview;

            @Override
            public void initialize(URL url, ResourceBundle rb) {
                initializeWebView();
                loadTestPage();
            }

            private void initializeWebView() {
                webview.getEngine().setOnAlert((WebEvent<String> event) -> {
                    JOptionPane.showMessageDialog(null, event.getData());
                });
                webview.getEngine().setOnError((WebErrorEvent event) -> {
                    event.getException().printStackTrace(System.err);
                });
                webview.getEngine().getLoadWorker().stateProperty().addListener((ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) -> {
                    if (Worker.State.SUCCEEDED.equals(newValue)) {
                        initSimpleJavaObject();
                    }
                });
            }

            private void loadTestPage() {
                webview.getEngine().load(getClass().getResource("test.html").toExternalForm());
            }

            private void initSimpleJavaObject() {
                SimpleJavaObject simpleJavaObject = new SimpleJavaObject();
                JSObject jsWindow = (JSObject) webview.getEngine().executeScript("window");
                jsWindow.setMember("simpleJavaObject", simpleJavaObject);
                webview.getEngine().executeScript("test();");
            }

        }

        // SimpleJavaObject.java

        package webviewtests;

        /**
         *
         * @author Marcos Martinewski Alves
         */
        public class SimpleJavaObject {

            private Double doubleAttribute = null;
            
            private final StringBuilder sbDebugText = new StringBuilder();

            public SimpleJavaObject() {

            }
            
            public void setDoubleAttribute(Double doubleAttributeArgument) {
                debug("Double setter: "+doubleAttributeArgument);
                doubleAttribute = doubleAttributeArgument;
            }

        // public void setDoubleAttribute(double doubleAttributeArgument) {
        // debug("double setter: "+doubleAttributeArgument);
        // doubleAttribute = doubleAttributeArgument;
        // }

        // public void setDoubleAttribute(Object doubleAttributeArgument) {
        // debug("Object setter: "+doubleAttributeArgument);
        // doubleAttribute = (Double) doubleAttributeArgument;
        // }

        // public void setDoubleAttribute(String doubleAttributeArgument) {
        // debug("String setter: "+doubleAttributeArgument);
        // doubleAttribute = Double.valueOf(doubleAttributeArgument);
        // }

            public Double getDoubleAttribute() {
                return doubleAttribute;
            }
            
            private void debug(String str) {
                sbDebugText.append(str);
                sbDebugText.append("\n");
            }
            
            public String getDebugText() {
                return sbDebugText.toString();
            }

        }

        // test.html

        <!DOCTYPE html>
        <html>
            <head>
                <title>WebView tests</title>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <script type="text/javascript">
                    var simpleJavaObject = null;
                    function test() {
                        alert("simpleJavaObject: " + simpleJavaObject);
                        simpleJavaObject.setDoubleAttribute(15.5);
                        alert("simpleJavaObject.getDoubleAttribute(): " + simpleJavaObject.getDoubleAttribute());
                        alert("Test summary:\n"+simpleJavaObject.getDebugText());
                    }
                </script>
            </head>
            <body>
                
            </body>
        </html>



        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        There is a one workaround, reimplementing all methods that use java.lang.Double as arguments, to use native double, but this may imply in some alterations of expected behaviour of the app.

          1. hs_err_pid27657.log
            45 kB
            Kevin Rushforth
          2. test.log
            183 kB
            Kevin Rushforth

              arajkumar Arunprasad Rajkumar
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: