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

Reply via email to