Google Guice module that loads two kinds of views











up vote
2
down vote

favorite












The code of my Guice Module looks like this:



public class FXMLModule extends AbstractModule {

private final Locale locale = Locale.getDefault();
private final ResourceBundle messages = ResourceBundle.getBundle("i18n.messages", locale);

@Override
protected void configure() {
bind(Controller.class).annotatedWith(MainView.class).to(MainController.class);
bind(Controller.class).annotatedWith(MovieView.class).to(MovieViewController.class);
}

@Provides @MainView
public FXMLLoader mainViewLoader(@MainView Controller controller) {
FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MainView.fxml"), messages);
loader.setController(controller);
return loader;
}

@Provides @MovieView
public FXMLLoader movieViewLoader(@MovieView Controller controller) {
FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MovieView.fxml"), messages);
loader.setController(controller);
return loader;
}

private URL locate(String location) {
return getClass().getResource(location);
}

}


Basically I want to inject fully configured FXMLLoaders into some Controller classes, so that they can work with the root nodes returned from the loaders without having to know anything about other controllers. The MainViewLoader gets injected into the Application class, and the MovieViewLoader gets injected into MainViewController. It works, but I'd have to write a provide method (with almost the same code) for every loader/controller. Any ideas how to make this more generic?










share|improve this question
















bumped to the homepage by Community 38 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.



















    up vote
    2
    down vote

    favorite












    The code of my Guice Module looks like this:



    public class FXMLModule extends AbstractModule {

    private final Locale locale = Locale.getDefault();
    private final ResourceBundle messages = ResourceBundle.getBundle("i18n.messages", locale);

    @Override
    protected void configure() {
    bind(Controller.class).annotatedWith(MainView.class).to(MainController.class);
    bind(Controller.class).annotatedWith(MovieView.class).to(MovieViewController.class);
    }

    @Provides @MainView
    public FXMLLoader mainViewLoader(@MainView Controller controller) {
    FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MainView.fxml"), messages);
    loader.setController(controller);
    return loader;
    }

    @Provides @MovieView
    public FXMLLoader movieViewLoader(@MovieView Controller controller) {
    FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MovieView.fxml"), messages);
    loader.setController(controller);
    return loader;
    }

    private URL locate(String location) {
    return getClass().getResource(location);
    }

    }


    Basically I want to inject fully configured FXMLLoaders into some Controller classes, so that they can work with the root nodes returned from the loaders without having to know anything about other controllers. The MainViewLoader gets injected into the Application class, and the MovieViewLoader gets injected into MainViewController. It works, but I'd have to write a provide method (with almost the same code) for every loader/controller. Any ideas how to make this more generic?










    share|improve this question
















    bumped to the homepage by Community 38 mins ago


    This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.

















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      The code of my Guice Module looks like this:



      public class FXMLModule extends AbstractModule {

      private final Locale locale = Locale.getDefault();
      private final ResourceBundle messages = ResourceBundle.getBundle("i18n.messages", locale);

      @Override
      protected void configure() {
      bind(Controller.class).annotatedWith(MainView.class).to(MainController.class);
      bind(Controller.class).annotatedWith(MovieView.class).to(MovieViewController.class);
      }

      @Provides @MainView
      public FXMLLoader mainViewLoader(@MainView Controller controller) {
      FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MainView.fxml"), messages);
      loader.setController(controller);
      return loader;
      }

      @Provides @MovieView
      public FXMLLoader movieViewLoader(@MovieView Controller controller) {
      FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MovieView.fxml"), messages);
      loader.setController(controller);
      return loader;
      }

      private URL locate(String location) {
      return getClass().getResource(location);
      }

      }


      Basically I want to inject fully configured FXMLLoaders into some Controller classes, so that they can work with the root nodes returned from the loaders without having to know anything about other controllers. The MainViewLoader gets injected into the Application class, and the MovieViewLoader gets injected into MainViewController. It works, but I'd have to write a provide method (with almost the same code) for every loader/controller. Any ideas how to make this more generic?










      share|improve this question















      The code of my Guice Module looks like this:



      public class FXMLModule extends AbstractModule {

      private final Locale locale = Locale.getDefault();
      private final ResourceBundle messages = ResourceBundle.getBundle("i18n.messages", locale);

      @Override
      protected void configure() {
      bind(Controller.class).annotatedWith(MainView.class).to(MainController.class);
      bind(Controller.class).annotatedWith(MovieView.class).to(MovieViewController.class);
      }

      @Provides @MainView
      public FXMLLoader mainViewLoader(@MainView Controller controller) {
      FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MainView.fxml"), messages);
      loader.setController(controller);
      return loader;
      }

      @Provides @MovieView
      public FXMLLoader movieViewLoader(@MovieView Controller controller) {
      FXMLLoader loader = new FXMLLoader(locate("/jfx/fxml/MovieView.fxml"), messages);
      loader.setController(controller);
      return loader;
      }

      private URL locate(String location) {
      return getClass().getResource(location);
      }

      }


      Basically I want to inject fully configured FXMLLoaders into some Controller classes, so that they can work with the root nodes returned from the loaders without having to know anything about other controllers. The MainViewLoader gets injected into the Application class, and the MovieViewLoader gets injected into MainViewController. It works, but I'd have to write a provide method (with almost the same code) for every loader/controller. Any ideas how to make this more generic?







      java dependency-injection javafx dynamic-loading guice






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 16 '17 at 17:32









      200_success

      127k15149412




      127k15149412










      asked Aug 14 '17 at 1:06









      guicy

      111




      111





      bumped to the homepage by Community 38 mins ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







      bumped to the homepage by Community 38 mins ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          What this is looking for is "Binding by Convention". Since Guice is intended to be as lightweight (and fast) as possible, it does not contain facilities to enable binding by convention.



          Neither does Spring for that matter. I think you might be able to automate the bindings injected into the methods if you use Plexus.
          Do note that none of this will alleviate you from the actual problem you're facing:



          Why?



          You write:




          Basically I want to inject fully configured FXMLLoaders into some
          Controller classes, so that they can work with the root nodes returned
          from the loaders without having to know anything about other
          controllers.




          This makes no sense: You're injecting FXMLLoaders into Controllers, specifically into a controller that's not the Controller you set on the FXMLLoader itself. To access the rootNode returned by the loader.



          This violates the Law of Demeter. You're grabbing into the responsibilities of another controller.



          The solution to this problem is to expose a method on the controller and inject a the controller instance you need, instead of the loader.



          This whole module seems to me like it's solving the wrong problem in the first place ...






          share|improve this answer





















            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f172920%2fgoogle-guice-module-that-loads-two-kinds-of-views%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            What this is looking for is "Binding by Convention". Since Guice is intended to be as lightweight (and fast) as possible, it does not contain facilities to enable binding by convention.



            Neither does Spring for that matter. I think you might be able to automate the bindings injected into the methods if you use Plexus.
            Do note that none of this will alleviate you from the actual problem you're facing:



            Why?



            You write:




            Basically I want to inject fully configured FXMLLoaders into some
            Controller classes, so that they can work with the root nodes returned
            from the loaders without having to know anything about other
            controllers.




            This makes no sense: You're injecting FXMLLoaders into Controllers, specifically into a controller that's not the Controller you set on the FXMLLoader itself. To access the rootNode returned by the loader.



            This violates the Law of Demeter. You're grabbing into the responsibilities of another controller.



            The solution to this problem is to expose a method on the controller and inject a the controller instance you need, instead of the loader.



            This whole module seems to me like it's solving the wrong problem in the first place ...






            share|improve this answer

























              up vote
              0
              down vote













              What this is looking for is "Binding by Convention". Since Guice is intended to be as lightweight (and fast) as possible, it does not contain facilities to enable binding by convention.



              Neither does Spring for that matter. I think you might be able to automate the bindings injected into the methods if you use Plexus.
              Do note that none of this will alleviate you from the actual problem you're facing:



              Why?



              You write:




              Basically I want to inject fully configured FXMLLoaders into some
              Controller classes, so that they can work with the root nodes returned
              from the loaders without having to know anything about other
              controllers.




              This makes no sense: You're injecting FXMLLoaders into Controllers, specifically into a controller that's not the Controller you set on the FXMLLoader itself. To access the rootNode returned by the loader.



              This violates the Law of Demeter. You're grabbing into the responsibilities of another controller.



              The solution to this problem is to expose a method on the controller and inject a the controller instance you need, instead of the loader.



              This whole module seems to me like it's solving the wrong problem in the first place ...






              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                What this is looking for is "Binding by Convention". Since Guice is intended to be as lightweight (and fast) as possible, it does not contain facilities to enable binding by convention.



                Neither does Spring for that matter. I think you might be able to automate the bindings injected into the methods if you use Plexus.
                Do note that none of this will alleviate you from the actual problem you're facing:



                Why?



                You write:




                Basically I want to inject fully configured FXMLLoaders into some
                Controller classes, so that they can work with the root nodes returned
                from the loaders without having to know anything about other
                controllers.




                This makes no sense: You're injecting FXMLLoaders into Controllers, specifically into a controller that's not the Controller you set on the FXMLLoader itself. To access the rootNode returned by the loader.



                This violates the Law of Demeter. You're grabbing into the responsibilities of another controller.



                The solution to this problem is to expose a method on the controller and inject a the controller instance you need, instead of the loader.



                This whole module seems to me like it's solving the wrong problem in the first place ...






                share|improve this answer












                What this is looking for is "Binding by Convention". Since Guice is intended to be as lightweight (and fast) as possible, it does not contain facilities to enable binding by convention.



                Neither does Spring for that matter. I think you might be able to automate the bindings injected into the methods if you use Plexus.
                Do note that none of this will alleviate you from the actual problem you're facing:



                Why?



                You write:




                Basically I want to inject fully configured FXMLLoaders into some
                Controller classes, so that they can work with the root nodes returned
                from the loaders without having to know anything about other
                controllers.




                This makes no sense: You're injecting FXMLLoaders into Controllers, specifically into a controller that's not the Controller you set on the FXMLLoader itself. To access the rootNode returned by the loader.



                This violates the Law of Demeter. You're grabbing into the responsibilities of another controller.



                The solution to this problem is to expose a method on the controller and inject a the controller instance you need, instead of the loader.



                This whole module seems to me like it's solving the wrong problem in the first place ...







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Aug 17 '17 at 10:54









                Vogel612

                21.3k346128




                21.3k346128






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f172920%2fgoogle-guice-module-that-loads-two-kinds-of-views%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Costa Masnaga

                    Fotorealismo

                    Sidney Franklin