2 Replies Latest reply: Feb 12, 2013 1:08 PM by 990159 RSS

    Spring dependency injection too late

    990159
      I am using JavaFX 2 in conjunction with the Spring Framework, however the injection happens to late. My Controller is instanciated by the FXML-Loader, the Spring injection for member variables of this Controller works, but it works only too late, this means that in (1) injection yet didn't happen and in (2) injection did happen:
          public class MainController extends AbstractController
          {
               @Autowired
               public StatusBarController statusbarController;
          
               // Implementing Initializable Interface no longer required according to
              // http://docs.oracle.com/javafx/2/fxml_get_started/whats_new2.htm:
               private void initialize() {
                  BorderPane borderPane = (BorderPane)getView();        
                  borderPane.setBottom(statusbarController.getView()); // (1) null exception!
              }
              
               // Linked to a button in the view
              public void sayHello() {
                  BorderPane borderPane = (BorderPane)getView();        
                  borderPane.setBottom(statusbarController.getView()); // (2) works!
              }
          }
      Any way to let Spring inject statusbarController in an earlier state? I can't let the user have to click a button to load my GUI ;-)

      My AppFactory is this:
          @Configuration
          public class AppFactory 
          {
               @Bean
               public MainController mainController() throws IOException
               {
                    return (MainController) loadController("/main.fxml");
               }
          
               protected Object loadController(String url) throws IOException
              {
                  InputStream fxmlStream = null;
                  try
                  {
                      fxmlStream = getClass().getResourceAsStream(url);
                      FXMLLoader loader = new FXMLLoader();
                      Node view = (Node) loader.load(fxmlStream);
                      AbstractController controller = (AbstractController) loader.getController();
                      controller.setView(view);
                      return controller;            
                  }
                  finally
                  {
                      if (fxmlStream != null)
                      {
                          fxmlStream.close();
                      }
                  }
              }
          }
      Thanks for any hint!

      Edited by: srynoname on 12.02.2013 04:43
        • 1. Re: Spring dependency injection too late
          James_D
          It's a while since I used Spring, but if I remember correctly you can define a set method for injection. So you could do this:
          public class MainController extends AbstractController
              {
                   
                   private StatusBarController statusbarController;
          
                  @Autowired
                  public void setStatusbarController(StatusBarController controller) {
                     this.statusbarController = controller ;
                     Platform.runLater(new Runnable() {
                       @Override public void run() {           
                          BorderPane borderPane = (BorderPane)getView();
                          if (borderPane != null) {
                            borderPane.setBottom(statusbarController.getView());
                          }
                        }
                     });
                  }
              
                   // Implementing Initializable Interface no longer required according to
                  // http://docs.oracle.com/javafx/2/fxml_get_started/whats_new2.htm:
                   private void initialize() {
                      BorderPane borderPane = (BorderPane)getView();
                      if (statusbarController != null) {  
                        borderPane.setBottom(statusbarController.getView()); // 
                      }
                  }
                  
                   // Linked to a button in the view
                  public void sayHello() {
                      BorderPane borderPane = (BorderPane)getView();        
                      borderPane.setBottom(statusbarController.getView()); // (2) works!
                  }
              }
          I may not have remember Spring setter injection correctly, but it's something like that.
          • 2. Re: Spring dependency injection too late
            990159
            Thank you James, however I ended up using FXMLLoader.setControllerFactory, I assume this is the "cleanest" way to solve this problem. For the records: An example for this can be found on http://koenserneels.blogspot.de/2012/11/javafx-2-with-spring.html