Following up on this thread...
While writing the unit tests and documentation for this it became clear
to me that it requiring applications to export as public API all
packages used by FXML, Java Beans, and JavaScript callbacks from WebView
is not a reasonable requirement.
The fact that we use sun.misc.reflect.MethodUtil.invoke is an
implementation detail that should not dictate our API specification. As
such, I have been working on a proposed fix as opposed to just
documenting the existing limitation and producing a more understandable
error message.
The fix will allow applications to "open" their package to just the
javafx.base module (for Java Beans), or the javafx.fxml module (for
FXML), or the javafx.web module (for JavaScript callbacks). This will
allow applications to keep their FXML controller, for example, in a
non-pubilc package, which is as it should be since the FXML controller
is in almost all cases an implementation detail of the application.
I have a fix that should be ready for review early next week. It will
also have the more descriptive error message in case the package is not
open to the javafx module in question.
-- Kevin
On Tue, 11 Apr 2017 at 01:36 Trisha Gee <trisha....@gmail.com> wrote:
From a user/developer point of view, a more descriptive error message
would be a big help. I was completely at a loss to understand why I
needed to unconditionally export my packages, I figured there was a
requirement from the JavaFX-side of things but it wasn't clear what it
was or why. A helpful error plus updated documentation would reduce
confusion.
On Tue, 11 Apr 2017 at 01:54 Mandy Chung <mandy.ch...@oracle.com
<mailto:mandy.ch...@oracle.com>> wrote:
It may be useful to point to the javadoc where it specifies to
require the module to export the packages unconditionally.
It would be a good RFE to relax the exports to at least javafx.beans.
Mandy
On Apr 10, 2017, at 3:56 PM, Kevin Rushforth
<kevin.rushfo...@oracle.com <mailto:kevin.rushfo...@oracle.com>>
wrote:
Sorry for the delay in responding.
I added a simple test program to the JBS bug that shows the same
behavior as the application and also an evaluation of the bug.
The short version is that JavaFX beans is (mostly) working as
expected, except for the misleading exception message. In JDK 9
it is required that any object that is reflected on by JavaFX
beans, specifically the items passed to TableView, which are
accessed via a PropertyValueFactory, will need to be in a package
that is exported unconditionally. In JDK 10 we can look into
relaxing this requirement such that the package only needs to be
exported to javafx.beans.
I do think we need to make the exception message less confusing
in JDK 9 and also document the requirement in the appropriate
places (at least in TableView and probably in a couple of
javafx.beans.property.adapter classes).
Comments?
-- Kevin
Mandy Chung wrote:
Hi Trisha,
Thanks for the report and stack trace. I created
https://bugs.openjdk.java.net/browse/JDK-8177566 for further
investigation.
Mandy
On Mar 24, 2017, at 2:34 PM, Trisha Gee <trisha....@gmail.com>
<mailto:trisha....@gmail.com> wrote:
Hi,
I was chatting to Alex Buckley at DevoxxUS about my experiences migrating a
project to using Java 9 modules (specifically, this project:
https://github.com/trishagee/sense-nine) and mentioned some surprising
behaviour in a module that uses JavaFX. I've been asked to send the
details so people can take a look at it.
My module-info.java is here:
https://github.com/trishagee/sense-nine/blob/master/src/com.mechanitis.demo.sense.client/module-info.java
Note that I have to export two additional packages (mood and user), and I
did not expect (or really want) to. This is because I was getting this
error if I did not:
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:482)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:381)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at
java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:912)
Caused by: java.lang.RuntimeException: Exception in Application start method
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:982)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:200)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.RuntimeException: *java.lang.IllegalAccessException:
class sun.reflect.misc.Trampoline cannot access class
com.mechanitis.demo.sense.client.user.TwitterUser (in module
com.mechanitis.demo.sense.client) because module
com.mechanitis.demo.sense.client does not export
com.mechanitis.demo.sense.client.user to unnamed module @779d6cc6*
at
javafx.base/com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:200)
at
javafx.controls/javafx.scene.control.cell.PropertyValueFactory.getCellDataReflectively(PropertyValueFactory.java:145)
at
javafx.controls/javafx.scene.control.cell.PropertyValueFactory.call(PropertyValueFactory.java:119)
at
javafx.controls/javafx.scene.control.cell.PropertyValueFactory.call(PropertyValueFactory.java:98)
at
javafx.controls/javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:579)
at
javafx.controls/javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:564)
at
javafx.controls/javafx.scene.control.TableCell.updateItem(TableCell.java:645)
at
javafx.controls/javafx.scene.control.TableCell.indexChanged(TableCell.java:468)
at
javafx.controls/javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at
javafx.controls/javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:534)
at
javafx.controls/javafx.scene.control.skin.TableRowSkinBase.<init>(TableRowSkinBase.java:159)
at
javafx.controls/javafx.scene.control.skin.TableRowSkin.<init>(TableRowSkin.java:89)
at
javafx.controls/javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212)
at
javafx.controls/javafx.scene.control.Control.doProcessCSS(Control.java:895)
at javafx.controls/javafx.scene.control.Control.access$000(Control.java:83)
at
javafx.controls/javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
at
javafx.controls/com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
at
javafx.graphics/com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:147)
at javafx.graphics/javafx.scene.Node.processCSS(Node.java:9356)
at javafx.graphics/javafx.scene.Node.applyCss(Node.java:9443)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1697)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1674)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1781)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2618)
at
javafx.controls/javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1242)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1226)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1233)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1233)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1233)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:585)
at javafx.graphics/javafx.scene.Scene.preferredSize(Scene.java:1767)
at javafx.graphics/javafx.scene.Scene$2.preferredSize(Scene.java:389)
at
javafx.graphics/com.sun.javafx.scene.SceneHelper.preferredSize(SceneHelper.java:66)
at javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1092)
at
javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at
javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.graphics/javafx.stage.Window.setShowing(Window.java:1180)
at javafx.graphics/javafx.stage.Window.show(Window.java:1195)
at javafx.graphics/javafx.stage.Stage.show(Stage.java:267)
at
com.mechanitis.demo.sense.client/com.mechanitis.demo.sense.client.Dashboard.start(Dashboard.java:45)
at
javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:928)
at
javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
at
javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at
javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
at
javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native
Method)
at
javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:189)
... 1 more
Caused by: java.lang.IllegalAccessException: class
sun.reflect.misc.Trampoline cannot access class
com.mechanitis.demo.sense.client.user.TwitterUser (in module
com.mechanitis.demo.sense.client) because module
com.mechanitis.demo.sense.client does not export
com.mechanitis.demo.sense.client.user to unnamed module @779d6cc6
at
java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:423)
at
java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:414)
at
java.base/jdk.internal.reflect.Reflection.ensureMemberAccess(Reflection.java:112)
at
java.base/java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:632)
at
java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:624)
at java.base/java.lang.reflect.Method.invoke(Method.java:539)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:72)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:547)
at java.base/sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:261)
at
javafx.base/com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:198)
... 48 more
When I discovered this I was a bit stumped about what was in the unnamed
module, given this appears to be JavaFX code causing this.
I'm running this from inside IntelliJ IDEA, this is the command it's
calling: "C:\Program Files\Java\jdk-9\bin\java"
-Djava.util.logging.config.file=logging.properties
-javaagent:C:\Users\Trisha\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\171.3780.107\lib\idea_rt.jar=54310:C:\Users\Trisha\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\171.3780.107\bin
-Dfile.encoding=UTF-8 -p
C:\Users\Trisha\Projects\trishagee\sense-nine\out\production\com.mechanitis.demo.sense.client;C:\Users\Trisha\Projects\trishagee\sense-nine\out\production\com.mechanitis.demo.sense.service;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\javax-websocket-server-impl\9.4.1.v20170120\javax-websocket-server-impl-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-annotations\9.4.1.v20170120\jetty-annotations-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-plus\9.4.1.v20170120\jetty-plus-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-webapp\9.4.1.v20170120\jetty-webapp-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-xml\9.4.1.v20170120\jetty-xml-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-util\9.4.1.v20170120\jetty-util-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-servlet\9.4.1.v20170120\jetty-servlet-9.4.1
.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-security\9.4.1.v20170120\jetty-security-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-server\9.4.1.v20170120\jetty-server-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\javax\servlet\javax.servlet-api\3.1.0\javax.servlet-api-3.1.0.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-http\9.4.1.v20170120\jetty-http-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-io\9.4.1.v20170120\jetty-io-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-jndi\9.4.1.v20170120\jetty-jndi-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\javax\annotation\javax.annotation-api\1.2\javax.annotation-api-1.2.jar;C:\Users\Trisha\.m2\repository\org\ow2\asm\asm\5.1\asm-5.1.jar;C:\Users\Trisha\.m2\repository\org\ow2\asm\asm-commons\5.1\asm-commons-5.1.jar;C:\Users\Trisha\.m2\repository\org\ow2\asm\asm-tree\5.1\asm-tree-5.1.jar;C:\Users\Trisha\.m
2\repository\org\eclipse\jetty\websocket\javax-websocket-client-impl\9.4.1.v20170120\javax-websocket-client-impl-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-client\9.4.1.v20170120\websocket-client-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\jetty-client\9.4.1.v20170120\jetty-client-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-common\9.4.1.v20170120\websocket-common-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-api\9.4.1.v20170120\websocket-api-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\javax\websocket\javax.websocket-api\1.0\javax.websocket-api-1.0.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-server\9.4.1.v20170120\websocket-server-9.4.1.v20170120.jar;C:\Users\Trisha\.m2\repository\org\eclipse\jetty\websocket\websocket-servlet\9.4.1.v20170120\websocket-servlet-9.4.1.v20170120.jar
-m
com.mechanitis.demo.sense.client/com.mechanitis.demo.sense.client.Dashboard
Thanks,
Trisha