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

Reflection of SelectionModel.select(i) throws Exception

XMLWordPrintable

    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_101"
      Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      I've tried it on Linux also with the same results.

      A DESCRIPTION OF THE PROBLEM :
      In trying to auto select a javafx.scene.control.SelectionModel index, direct manipulation calling the select function directly works fine. However, if trying to access the select function via reflection, an exception is thrown.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Save the code below in a file called FxSelectionModelIssue.java.
      Compile it: javac FxSelectionModelIssue.java
      Run it: java FxSelectionModelIssue 1 // works
      Run it: java FxSelectionModelIssue 2 // fails

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Running the enclosed program will bring up a ListView window with a button at the bottom. Initially, the first item is highlighted/selected. Pressing the "next" button at the bottom of the ListView will increment the selected ListView Item. This works fine when providing the command line option 1. When providing command line option 2, the expected behavior should be the same as using option 1.
      ACTUAL -
      When using command line option 2, The application starts with an exception being thrown.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.IllegalAccessException: Class FxSelectionModelIssue can not access a member of class javafx.scene.control.MultipleSelectionModelBase with modifiers "public"
              at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
              at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
              at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
              at java.lang.reflect.Method.invoke(Method.java:491)
              at FxSelectionModelIssue.selectIndirect(FxSelectionModelIssue.java:84)
              at FxSelectionModelIssue.start(FxSelectionModelIssue.java:60)
              at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
              at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
              at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
              at java.security.AccessController.doPrivileged(Native Method)
              at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
              at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
              at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
              at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
              at java.lang.Thread.run(Thread.java:745)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      /*
       compile: javac FxSelectionModelIssue.java
       usage: java FxSelectionModelIssue 1 // calls select directly
       usage: java FxSelectionModelIssue 2 // calls select indirectly via reflection
      */

      public class FxSelectionModelIssue extends javafx.application.Application {

          public void start(javafx.stage.Stage stage) {
              String usage = "java FxSelectViaIntrospection 1|2";
              java.util.List<String> listParm = getParameters().getRaw();
              if (listParm.size() != 1) {
                  System.err.println(usage);
                  System.exit(1);
              }
              String call = listParm.get(0).intern();
              if (call != "1" && call != "2") {
                  System.err.println(usage);
                  System.exit(1);
              }

              javafx.scene.control.ListView ListView =
                  new javafx.scene.control.ListView();
              javafx.scene.control.MultipleSelectionModel msm =
                  ListView.getSelectionModel();
              msm.setSelectionMode(javafx.scene.control.SelectionMode.SINGLE);

              javafx.scene.control.Button Button = new javafx.scene.control.Button();
              Button.setText("next");
              Button.setUserData(ListView);
              Button.setOnAction(
                  event -> {
                      javafx.scene.control.Button b =
                          (javafx.scene.control.Button)event.getSource();
                      javafx.scene.control.ListView lv =
                          (javafx.scene.control.ListView)b.getUserData();
                      javafx.scene.control.SelectionModel sm = lv.getSelectionModel();
                      int i = sm.getSelectedIndex();
                      int size = lv.getItems().size();
                      i = (i < size - 1) ? i + 1 : 0;
                      if (call == "1") {
                          selectDirect(sm, i); // works
                      } else if (call == "2") {
                          selectIndirect(sm, i); // fails
                      }
      System.err.println(sm.getSelectedIndex()+" => "+sm.getSelectedItem());
                  }
              );

              ListView.getItems().add("a");
              ListView.getItems().add("b");
              ListView.getItems().add("c");
              ListView.getItems().add("d");
              ListView.getItems().add("e");

              if (call == "1") {
                  selectDirect(msm, 0); // works
              } else if (call == "2") {
                  selectIndirect(msm, 0); // fails
              }

              javafx.scene.layout.VBox vbox = new javafx.scene.layout.VBox();
              vbox.getChildren().add(ListView);
              vbox.getChildren().add(Button);
              javafx.scene.Scene scene = new javafx.scene.Scene(vbox);
              stage.setScene(scene);
              stage.show();
          }

          // works
          private void selectDirect(javafx.scene.control.SelectionModel sm, int i) {
              sm.select(i);
          }

          // The following exception is thrown upon invoke call:
          // java.lang.IllegalAccessException: Class FxSelectViaIntrospection can not access a member of class javafx.scene.control.MultipleSelectionModelBase with modifiers "public"

          // fails
          private void selectIndirect(javafx.scene.control.SelectionModel sm, int i) {
              try {
                  java.lang.reflect.Method m =
                      sm.getClass().getMethod("select", int.class);
                  m.invoke(sm, i);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }

      }

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

            aroy Abhijit Roy (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: