title: JavaFX FXML communication between Application and Controller classes
body: <p>I am trying to get and destroy an external process I've created via ProcessBuilder in my FXML application close, but it's not working.  This is based on the helpful advice <a href="https://stackoverflow.com/a/12322123/492404">Sergey Grinev gave me here</a>.</p>
  
  <p>I have tried running with/without the "// myController.setApp(this);" and with "// super.stop();" at top of subclass and at bottom (see commented out/in for that line in MyApp), but no combination works.</p>
  
  <p>This probably isn't related to FXML or JavaFX, though I imagine this is a common pattern for developing apps on JavaFX.  I suppose I'm asking for a Java best practice for closing dependent processes in a UI-based app like this one (in this case: FXML / JavaFX based), where there is a controller class and an application class.</p>
  
  <p>Can you explain what I'm doing wrong?  Or better: advise what I <em>should</em> be doing instead?  Thanks.</p>
  
  <p>In my Application I do this:</p>
  
  <pre><code>public class MyApp extends Application {
  
      @Override
      public void start(Stage primaryStage) throws Exception {
          FXMLLoader fxmlLoader = new FXMLLoader();
          Scene scene = (Scene)FXMLLoader.load(getClass().getResource("MyApp.fxml"));
          MyAppController myController = (MyAppController)fxmlLoader.getController();
  
          primaryStage.setScene(scene);
          primaryStage.show();
  
  //        myController.setApp(this);
      }
  
      @Override
      public void stop() throws Exception {
  //      super.stop();
  
        // this is called on fx app close, you may call it in an action handler too
        if (MyAppController.getScriptProcess() != null) {
          MyAppController.getScriptProcess().destroy();
        }
        super.stop();
      }
      public static void main(String[] args) {
          launch(args);
      }
  }
  </code></pre>
  
  <p>In my Controller I do this:</p>
  
  <pre><code>public class MyAppController implements Initializable {
  
    private Application app;
    private static Process scriptProcess;
  
  
    public void setApp(Application a) {
      app = a;
    }
  
    public static Process getScriptProcess() {
      return scriptProcess;
    }
  }
  </code></pre>
  
  <p>The result when I run with the "commented-out setApp()" <em>not</em> commented out (that is, left in the start method), is the following, immediately upon launch (the main Scene flashes, then disappears, then this dialog appears:</p>
  
  <pre><code>"JavaFX Launcher Error:
  Exception while running Application"
  </code></pre>
  
  <p>And it gives an, "Exception in Application start method" in the console as well.</p>
  
  <p>The result when I leave out the "commented-out code" in my MyApp above (that is, remove the "setApp()" from the start method), is that my app <em>does</em> indeed close, but gives this error when it closes:</p>
  
  <pre><code>Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
      at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
      at javafx.event.Event.fireEvent(Event.java:171)
      at javafx.scene.Node.fireEvent(Node.java:6863)
      at javafx.scene.control.Button.fire(Button.java:179)
      at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
      at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
      at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
      at javafx.event.Event.fireEvent(Event.java:171)
      at javafx.scene.Scene$MouseHandler.process(Scene.java:3324)
      at javafx.scene.Scene$MouseHandler.process(Scene.java:3164)
      at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119)
      at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559)
      at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
      at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
      at com.sun.glass.ui.View.notifyMouse(View.java:922)
      at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
      at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82)
      at java.lang.Thread.run(Thread.java:722)
  Caused by: java.lang.reflect.InvocationTargetException
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
      ... 44 more
  Caused by: java.lang.NullPointerException
      at mypackage.MyController.handleCancel(MyController.java:300)
      ... 49 more
  Clean up...
  </code></pre>