How can i use Guice in JavaFX controllers?


Question

I have a JavaFX application where I would like to introduce Guice because my Code is full of factorys right now, only for the purpose of testing.

I have one use case where i have a controller class of a certain view. This controller class has a viewmodel and I pass the model to the viewmodel via the constructor of the controller class.

In the controller class I have a contactservice object that provides the edit/save/delete operations. As of now I have an interface of that object and provide an implementation and a Mock. This object can be retrieved by a Factory.getInstance() method.

What I want to do is something like this:

public class NewContactController implements Initializable {
    // ------------------------------------------------------------------------
    // to inject by guice
    // ------------------------------------------------------------------------
    private ContactService contactService;

    @Inject
    public void setContactService(ContactService srv) {
        this.contactService = srv;
    }
    // edit window
    public NewContactController(Contact c) {
        this.viewModel = new NewContactViewModel(c);
    }
    // new window
    public NewContactController() {
        this.viewModel = new NewContactViewModel();
    }

    @FXML
    void onSave(ActionEvent event) {
        //do work like edit a contcat, 
        contactService.editContact(viewModel.getModelToSave());
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // bind to viewmodel---------------------------------------------------
    }
}

How can I achive this? Is it a good a idea to do something like that? While I was searching for a solution I found fx-guice and similar frameworks but how can i combine these two? Specially how can I let this fields be injected AND instanciate the controller myself or at least give it some constructor args?

1
4
5/5/2014 11:19:16 AM

I don't use Guice, but the simplest approach would appear to be just to use a controller factory on the FXMLLoader. You can create a controller factory that instructs the FXMLLoader to use Guice to initialize your controllers:

final Injector injector = Guice.createInjector(...);
FXMLLoader loader = new FXMLLoader(getClass().getResource(...));
loader.setControllerFactory(new Callback<Class<?>, Object>() {
   @Override
   public Object call(Class<?> type) {
       return injector.getInstance(type);
   }
});
// In Java 8, replace the above with 
// loader.setControllerFactory(injector::getInstance);
Parent root = loader.<Parent>load();
14
9/7/2017 2:06:30 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon