1

Does anyone know if there is any easy way to use dependency injection within the FXML controllers of a Gluon Desktop (ParticleApplication) app? There is already @Inject used for things like

public class HomeController {

    @Inject ParticleApplication app;

    @Inject private ViewManager viewManager;

    @Inject private StateManager stateManager;

(as part of the framework) but I would like to be able to @Inject my own objects.


EDIT: An answer suggested to use Gluon Ignite, but I'm still having trouble figuring it out. Here is some of my attempted code:

My ParticleApplication class:

package com.gluonapplication;

import com.gluonhq.ignite.guice.GuiceContext;
import com.gluonhq.particle.application.ParticleApplication;
import com.google.inject.AbstractModule;
import javafx.scene.Scene;

import java.util.Arrays;

public class GluonApplication extends ParticleApplication {

    private GuiceContext context = new GuiceContext(this, () -> Arrays.asList(new GuiceModule()));

    public GluonApplication() {
        super("Gluon Desktop Application");

        context.init();
        System.out.println("From within GluonApplication Constructor: " +
                context.getInstance(TestClassToInject.class).testDependancy.testString
        );
    }

    @Override
    public void postInit(Scene scene) {
        setTitle("Gluon Desktop Application");
    }

    class GuiceModule extends AbstractModule {
        @Override protected void configure() {
            // Use just in time injection.
        }
    }
}

My controller class:

package com.gluonapplication.controllers;

import com.gluonapplication.TestClassToInject;
import com.gluonhq.particle.application.ParticleApplication;
import com.gluonhq.particle.state.StateManager;
import com.gluonhq.particle.view.ViewManager;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javax.inject.Inject;

public class PrimaryController {

    @Inject ParticleApplication app;

    @Inject private ViewManager viewManager;

    @Inject private StateManager stateManager;

    @Inject private TestClassToInject testClassToInject;

    @FXML
    private Label label;

    public void initialize() {
    }

    public void postInit() {
        System.out.println("From within controller's postInit() method: " +
                testClassToInject.testDependancy.testString
        );
    }

    public void dispose() {
    }
}

And then my two classes created as the dependancies:

package com.gluonapplication;

import javax.inject.Inject;

public class TestClassToInject {
    @Inject
    public TestDependancy testDependancy;

    public TestClassToInject() {
    }
}

package com.gluonapplication;

public class TestDependancy {
    public String testString = "This is a test string";

    public TestDependancy() {
    }
}

And finally my Gradle file:

apply plugin: 'java'
apply plugin: 'application'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'com.gluonapplication.GluonApplication'

dependencies {
    compile 'com.gluonhq:particle:1.1.0'
    compile 'com.gluonhq:ignite-guice:1.0.0'
}

The "From within GluonApplication Constructor: " + context.getInstance(TestClassToInject.class).testDependancy.testString prints out just fine, so I think I have the dependancy classes and Guice configured OK. However, the System.out.println("From within controller's postInit() method: " + testClassToInject.testDependancy.testString); doesn't work from within the controller because the testClassToInject is null at time of use.

1 Answers1

0

You can use Gluon Ignite (http://gluonhq.com/open-source/ignite/) which supports dependency injection with Dagger, Guice and Spring. Gluon Ignite is an open source project, and you can find an example in the test directory on the repository website: https://bitbucket.org/gluon-oss/ignite/src/c85197b33852/src/test/java/com/gluonhq/ignite/?at=default

Joeri Sykora
  • 514
  • 3
  • 8
  • That seems like what I was looking for, but I still can't get it to work. Inside my controller I'm still getting null for my injected classes. Do you know if it makes any difference that I am extending `ParticleApplication` instead of `Application` like in the example? `ParticleApplication` doesn't have the `start` method, should I use `postInit` for `context.init()`? I will try to post some of my code in my question soon. –  Apr 19 '16 at 23:24
  • Usually, to be injected, `TestClassToInject` should be defined in one of your modules. Only than it becomes injectable. That means that class has to be created by Guice. In `Ignite` there is a way to emulate that behavior if you cannot do it for some reason: create an instance of `TestClassToInject` your self and than call `context.injectMembers(instance)` – Eugene Ryzhikov Apr 20 '16 at 12:14
  • Thanks your patience, I'm still learning DI so I might be missing something. I am already able to create the `TestClassToInject` class using `context.getInstance(TestClassToInject.class)` inside of my main application class `GluonApplication` which extends `ParticleApplication` (so I think the Guice stuff is working OK, since TestClassToInject has a noarg public constructor). The problem is that I'm not able to inject it into the controllers (like the `PrimaryController` class created by the IntelliJ Gluon plugin when you make a `Gluon Desktop - Multiple View Project with FXML`). –  Apr 23 '16 at 21:26
  • A year and half later and I am trying to do the same thing with similar lack of results. The ignite examples given do not show how to work with the Gluon Desktop framework. The Desktop blurbs say that it is pre-built to work with ignite, but for the life of my I can not figure out how this works either. Under the cover, Gluon Desktop has a ParticleInjector that does all the injecting, and I just don't see how an external (e.g. guice/ignite) injector can work with this without a huge kludge. If any gluon devs are watching, would love to hear your take. Until then, bye bye gluon desktop. – chooks Nov 02 '17 at 14:24