JavaFX Gluon Ignite Guice Inject Controller

I had to inject a whole controller into another controller with the guice implementation of gluon ignite. I will show an approach doing so. This is applicable if you have set the controller id in your fxml. Otherwise this snipped requires slightly modifications. I assume you have ignite already running and injecting stuff already but facing the “inject a controller for me” problem.

Create a new provider for your controller you want to inject and register it. If you decide to create this as inner class of your module you have to use a static inner class.

public class GUIConfig extends AbstractModule {

    @Override
    protected void configure() {
        install(new ApplicationConfig());
        bind(ControllerError.class).toProvider(ControllerErrorProvider.class);
    }

    /**
     * Provides the {@link ControllerError}.
     * This Controller has it's own stage.
     */
    @Singleton
    static class ControllerErrorProvider implements Provider<ControllerError> {

        @Inject
        FXMLLoader fxmlLoader;

        @Inject
        Injector injector;

        @Override
        public ControllerError get() {
            ControllerError controllerError = null;
            Parent node = null;
            try {
                // The fxml can't load the same fxml twice with the same instance but setRoot is a workaround
                // http://stackoverflow.com/questions/21424843/exception-has-occuredroot-value-already-specified-in-javafx-when-loading-fxml-p
                fxmlLoader.setRoot(null);
                fxmlLoader.setController(null);
                // The path to your fxml  
                fxmlLoader.setLocation( getClass().getResource(Resources.getErrorFXML()) );
                // Disable the controller factory since the reference to the controller in the fxml would be a circular dependency.
                fxmlLoader.setControllerFactory(null);
                node = fxmlLoader.load();
                controllerError = fxmlLoader.getController();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if( null == controllerError) {
                throw new IllegalStateException("Failed to create the ControllerError!");
            }
            if( null == node ) {
                throw new IllegalStateException("Failed to load the fxml for the controller! Check the path is valid");
            }
            // Inject eventual other dependencies (that are not @FXML annotations)
            injector.injectMembers(controllerError);
            // This is not relevant for this snippet but might be useful anyway
            // I create a new stage and set it to the controller so it is ready to use and call show() on it.
            Stage stage = new Stage();
            stage.setScene(new Scene(node));
            controllerError.setStage(stage);

            return controllerError;
        }
    }
}

Use it to inject

public class MyController {
    @Inject
    private ErrorController;
    @FXML
    Button button1;
    @Inject
    FXMLLoader fxmlLoader;
}

You are done! Use the injected controller as usual.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Spelling error report

The following text will be sent to our editors: