NOTE: the original test will be modified as a part of JDK-8349750 to call show() only in the FX application thread.
SplitMenuButton/ MenuButton fail to initialize in a background thread when adding a series, throwing an exception with a java.lang.NullPointerException: Cannot invoke "javafx.scene.Scene.getStylesheets()" because the return value of "javafx.scene.Node.getScene()" is null
To reproduce, use the newly developed NodeInitializationStressTest:
```
@Test
public void splitMenuButton() {
test(() -> {
SplitMenuButton c = new SplitMenuButton();
c.setSkin(new SplitMenuButtonSkin(c));
return c;
}, (c) -> {
c.getItems().setAll(new MenuItem("SplitMenuButton"));
c.setPopupSide(Side.RIGHT);
accessControl(c);
c.show();
});
}
```
Exception:
java.lang.NullPointerException: Cannot invoke "javafx.scene.Scene.getStylesheets()" because the return value of "javafx.scene.Node.getScene()" is null
at javafx.controls/javafx.scene.control.ContextMenu.show(ContextMenu.java:250)
at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.show(MenuButtonSkinBase.java:297)
at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.lambda$4(MenuButtonSkinBase.java:163)
at javafx.controls/com.sun.javafx.scene.control.ListenerHelper$4.changed(ListenerHelper.java:212)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:192)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
at javafx.base/javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:78)
at javafx.base/javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:103)
at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:111)
at javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.controls/javafx.scene.control.MenuButton.setShowing(MenuButton.java:220)
at javafx.controls/javafx.scene.control.MenuButton.show(MenuButton.java:377)
at test.robot.javafx.scene.NodeInitializationBackgroundThreadTest.lambda$48(NodeInitializationBackgroundThreadTest.java:457)
at test.robot.javafx.scene.NodeInitializationBackgroundThreadTest$1.run(NodeInitializationBackgroundThreadTest.java:561)
## Root Cause
The ContextMenu (PopupWindow) cannot be shown in a background thread.
## Solution
Bail out of `show()` if in a background thread.
SplitMenuButton/ MenuButton fail to initialize in a background thread when adding a series, throwing an exception with a java.lang.NullPointerException: Cannot invoke "javafx.scene.Scene.getStylesheets()" because the return value of "javafx.scene.Node.getScene()" is null
To reproduce, use the newly developed NodeInitializationStressTest:
```
@Test
public void splitMenuButton() {
test(() -> {
SplitMenuButton c = new SplitMenuButton();
c.setSkin(new SplitMenuButtonSkin(c));
return c;
}, (c) -> {
c.getItems().setAll(new MenuItem("SplitMenuButton"));
c.setPopupSide(Side.RIGHT);
accessControl(c);
c.show();
});
}
```
Exception:
java.lang.NullPointerException: Cannot invoke "javafx.scene.Scene.getStylesheets()" because the return value of "javafx.scene.Node.getScene()" is null
at javafx.controls/javafx.scene.control.ContextMenu.show(ContextMenu.java:250)
at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.show(MenuButtonSkinBase.java:297)
at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.lambda$4(MenuButtonSkinBase.java:163)
at javafx.controls/com.sun.javafx.scene.control.ListenerHelper$4.changed(ListenerHelper.java:212)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:192)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
at javafx.base/javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:78)
at javafx.base/javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:103)
at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:111)
at javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.controls/javafx.scene.control.MenuButton.setShowing(MenuButton.java:220)
at javafx.controls/javafx.scene.control.MenuButton.show(MenuButton.java:377)
at test.robot.javafx.scene.NodeInitializationBackgroundThreadTest.lambda$48(NodeInitializationBackgroundThreadTest.java:457)
at test.robot.javafx.scene.NodeInitializationBackgroundThreadTest$1.run(NodeInitializationBackgroundThreadTest.java:561)
## Root Cause
The ContextMenu (PopupWindow) cannot be shown in a background thread.
## Solution
Bail out of `show()` if in a background thread.
- blocks
-
JDK-8348987 ☂ Thread safety in Node initialization
-
- In Progress
-
- duplicates
-
JDK-8350048 Enforce threading restrictions for show and hide methods in Window, Control, and Skin
-
- Resolved
-
- relates to
-
JDK-8350048 Enforce threading restrictions for show and hide methods in Window, Control, and Skin
-
- Resolved
-
-
JDK-8349004 DatePicker: NPE in show() when initialized in a background thread
-
- Closed
-
- links to
-
Review(master) openjdk/jfx/1709