title: Javafx WebView can not access a member of class ... with modifiers "public"
body: <p>In a project I am working on, I need to define an abstract class with some methods implemented in packageone. In packagetwo the remainder of the abstract methods will be implemented when the class is instantiated. The instance is then exposed to Javascript code in a JavaFX webview. (An online example from Oracle - <a href="https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx" rel="nofollow noreferrer">https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx</a>)</p>
  
  <p>My problem is, the methods implemented in packagetwo are not callable from the Javascript environment. I get the following error:</p>
  
  <pre><code>Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: java.lang.IllegalAccessException: Class sun.reflect.misc.Trampoline can not access a member of class packagetwo.MainWindow$1 with modifiers "public"
      at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:128)
      at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
      at com.sun.webkit.WebPage.executeScript(WebPage.java:1439)
      at javafx.scene.web.WebEngine.executeScript(WebEngine.java:982)
      at packagetwo.MainWindow.makeUpCall(MainWindow.java:130)
      at packagetwo.MainWindow.access$000(MainWindow.java:22)
      at packagetwo.MainWindow$2.changed(MainWindow.java:83)
      at packagetwo.MainWindow$2.changed(MainWindow.java:68)
      at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
      at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
      at javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
      at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
      at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
      at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
      at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:1260)
      at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1371)
      at javafx.scene.web.WebEngine$LoadWorker.access$1200(WebEngine.java:1253)
      at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1240)
      at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2400)
      at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2244)
      at com.sun.webkit.network.URLLoader.twkDidFinishLoading(Native Method)
      at com.sun.webkit.network.URLLoader.notifyDidFinishLoading(URLLoader.java:838)
      at com.sun.webkit.network.URLLoader.lambda$didFinishLoading$96(URLLoader.java:829)
      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)
  Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.Trampoline can not access a member of class packagetwo.MainWindow$1 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 sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
      at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
      at com.sun.webkit.Utilities.lambda$fwkInvokeWithContext$55(Utilities.java:94)
      at java.security.AccessController.doPrivileged(Native Method)
      at com.sun.webkit.Utilities.fwkInvokeWithContext(Utilities.java:94)
      ... 29 more
  </code></pre>
  
  <p>Though calling methods implemented in packageone works fine. Calling both sets of methods from Java also works fine. Below are My classes and Javascript calls.</p>
  
  <p>Packagetwo</p>
  
  <pre><code>package packagetwo;
  
  import packageone.Calls;
  
  
  
  import java.io.File;
  import java.net.URL;
  import java.util.ResourceBundle;
  import java.util.concurrent.Callable;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javafx.beans.value.ChangeListener;
  import javafx.beans.value.ObservableValue;
  import javafx.concurrent.Worker;
  import javafx.fxml.FXML;
  import javafx.fxml.Initializable;
  import javafx.scene.layout.AnchorPane;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.web.WebView;
  import netscape.javascript.JSObject;
  
  
  public class MainWindow implements Initializable
  {
  
       @FXML
      private BorderPane mainWindow;
  
      @FXML
      private WebView mainWebView;
  
      @FXML
      private AnchorPane mainWebViewLayout;
  
      @Override
      public void initialize(URL url, ResourceBundle rb)
      {           
          Calls jc = new Calls()
          {
              @Override
              public void aMethod1()
              {
                  System.out.printf("Calls: Abstract Method Impl 1 Called.\n");
              }
          };
  
          // Add new load complete listener.
          ChangeListener&lt;Worker.State&gt; onLoadComplete = buildOnLoadCompleteListener(mainWebView, jc);
          mainWebView.getEngine()
                  .getLoadWorker()
                  .stateProperty()
                  .addListener(
                      onLoadComplete);
  
  
          // Attempt to load the current web package.
          mainWebView.getEngine().load("file:///" + new File("index.html").getAbsolutePath());
  
      }
  
      private ChangeListener&lt;Worker.State&gt; buildOnLoadCompleteListener(
              WebView webview, Calls javaUpCalls)
      {
          return new ChangeListener&lt;Worker.State&gt;()
          {
              @Override
              public void changed(
                      ObservableValue&lt;? extends Worker.State&gt; ov,
                      Worker.State lastState, Worker.State currentState)
              {
                  if (currentState == Worker.State.SUCCEEDED)
                  {                       
                      // Hook up Java up calls in the Javascript environment.
                      JSObject jsEnvironment = (JSObject) webview.getEngine().executeScript("window");
                      jsEnvironment.setMember("JavaUpCalls", javaUpCalls);
  
                      makeUpCall(webview);
                  }
              }
          };
      }
  
      private void makeUpCall(WebView webview)
      {           
          String setUpUpCall = 
              "function makeAnUpCall()" +
              "{" +
                  "if(typeof JavaUpCalls !== \"undefined\")" +
                  "{" + 
                      "JavaUpCalls.method2();" +
                      "JavaUpCalls.aMethod1();" +
                  "}" +
              "}";
  
  
          webview.getEngine().executeScript(setUpUpCall);
          webview.getEngine().executeScript("makeAnUpCall()");
      }
  }
  </code></pre>
  
  <p>Packageone</p>
  
  <pre><code>package packageone;
  
  public abstract class Calls()
  {
      public abstract void aMethod1();
      public void method2()
      {
          System.out.printf("Calls: Method 1 Called.\n");
      }
  }
  </code></pre>
  
  <p>Index.html is just a standard html page that load successfully with a <code>&lt;p&gt;</code> tag that says the page loaded.</p>
  
  <p>Any idea why the Javascript environment can't call my methods implemented in packagetwo?</p>
  
  <p>EDIT:</p>
  
  <p>I researched a bit online and found this StackOverflow question:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/13681142/can-not-access-a-member-of-class-org-springframework-aop-truepointcut-with-modif">can not access a member of class org.springframework.aop.TruePointcut with modifiers public</a></li>
  </ul>
  
  <p>I attempted the solution listed there (calling setAccessible(true) on the packagetwo method instance) and the error was still thrown.</p>
  
  <p>I also tried initializing and calling the Javascript methods from packageone, but the still got the error.</p>