Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8143573 | 8u92 | Arunprasad Rajkumar | P3 | Resolved | Fixed | b02 |
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.
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.
- backported by
-
JDK-8143573 Unable to pass values to java functions which takes wrapper objects as arguments
-
- Resolved
-