• Oct
    • 30
    • 2011

Better Controller Injection with Guice

Posted by In Uncategorized

By request, here’s how to do the better controller injection I outlined in an earlier post, but using Guice instead of Spring.

It’s worth noting however, that JavaFX 2.0.2 is targeted for release in about a month or so (or so Richard has alluded to in this forum topic), and that this should have a way to control how FXML instantiates its controllers. This should make it possible to use both Spring and Guice in more natural ways. If you’re reading this and 2.0.2 has been released, you may want to look for a more recent post.

But for now, here’s how it goes. We’ll use Richard’s example as a basis again, merging in the concepts from my previous post.

Person.java and sample.fxml are unchanged from the previous post.

In SampleController.java, we simply revert back to using Guice’s @Inject instead of Spring’s @Autowired.

public class SampleController
{
    @FXML private Node view;
    @Inject private Person person;

    ...
}

The biggest change is in our application factory. Instead of our SampleAppFactory, which was essentially a Spring configuration file, we have a Guice module instead, called SampleAppModule.

There are a few different options for loading our controllers in this module. The easiest way is to bind our Controller class directly to an instance, using the toInstance() binding method. This allows us to do the instantiation (or rather allows FXMLLoader to do the instantiation at our request) and then Guice takes care of all the injection from there. If we use this option, our SampleAppModule.java looks like this:

import com.google.inject.AbstractModule;
import javafx.fxml.FXMLLoader;

import java.io.IOException;
import java.io.InputStream;

public class SampleAppModule extends AbstractModule
{
    protected void configure()
    {
        // we can use instance binding for the person object, or if it had an empty
        // constructor (as in Richard's example) we could use the default Guice binding
        bind(Person.class).toInstance(new Person("Richard"));

        // OPTION 1: bind to an instance
        bind(SampleController.class).toInstance((SampleController) loadController("/sample.fxml"));
    }

    protected Object loadController(String url)
    {
       // normal loading stuff here - see full code for details
    }
}

The only limitation with this approach is that all our controllers will be created up front when the application starts. Depending on your requirements, this could be a good thing or it could be a bad thing – basically trading startup load time for in-application load time.

If you don’t want to load everything straight away and need to delay the loading, then the alternative is to use Guice Providers. You can create a whole Provider class if you want, however it is much easier to just annotate a provider method in your module for these simple cases.

There is a drawback to this approach however. Once we’ve told Guice we want to use a provider, Guice no longer injects our dependencies for us. The best we can do is ask Guice to inject our provider method with dependencies and then we have to manually inject these into our created class (this seems a little limited, and perhaps I have missed something in Guice here – if anybody knows a way around this, please post in the comments).

Using the provider option, our SampleAppModule looks like this:

<pre>import com.google.inject.AbstractModule;
import javafx.fxml.FXMLLoader;

import java.io.IOException;
import java.io.InputStream;

public class SampleAppModule extends AbstractModule
{
    protected void configure()
    {
        bind(Person.class).toInstance(new Person("Richard"));
    }

    // OPTION 2: use a provider - the person parameter is the one bound in the configure() method
    @Provides
    public SampleController sampleController(Person person)
    {
        System.out.println("Creating controller");
        SampleController controller = (SampleController) loadController("/sample.fxml");

        // we have to manually set our person object since Guice has washed its hands of this
        // controller leaving it all up to us to create and configure (i.e. 'provide') it
        controller.setPerson(person);

         return controller;
    }

    protected Object loadController(String url)
    {
       // normal loading stuff here - see full code for details
    }
}

The full code for this post can be found at: http://code.google.com/p/jfxee/source/browse/trunk/jfxee6/

Continue Reading→
    • Oct
    • 26
    • 2011

Generic Controllers

Posted by In Uncategorized

This entry is part 5 of 15 in the series Building JEE applications in JavaFX 2.0

Now that we’ve created a few of these Controllers we’re seeing a bit of similarity between them. They all have an attached view and up until now we’ve duplicated the same code in all of them for dealing with these.

Let’s take this opportunity then to clean things up a little and define a generic controller framework. This base framework will be very simple for now, but as we start to head into more complicated areas of JEE application building (such as threading, communicating with servers, and navigating between controllers) this Controller setup is going to provide us with a strong foundation to build on.

Our first step is to create a Controller interface that all controller instances will implement. The only thing we need to know from our controllers at this stage is their attached view, so the interface will provide for this:

import javafx.scene.Node;

public interface Controller
{
    Node getView();
}

Next we can create an abstract base class and we can move the duplicated code from our controllers into this so it’s defined in one nice spot:

import javafx.scene.Node;

public abstract class AbstractController implements Controller
{
    // Problem! This value will not be set by the FXMLLoader since the
    // loader does not detect annotated fields in base classes
    @FXML private Node view;

    public Node getView()
    {
        return view;
    }
}

This looks pretty good, but unfortunately the current version of FXML does not map fields that are defined in a base class of the controller, even if that field is annotated with @FXML. There is a JIRA issue for this, but for the time being we have to find a work around.

Our cheat here is to manually inject our view into our controller when loading it in the factory. Luckily we can get hold of the root of the view from the FXMLLoader and then we can just pass this to our Controller in code.

Our factory load method now looks like this:

protected Controller loadController(String url) throws IOException
{
    InputStream fxmlStream = null;
    try
    {
        fxmlStream = getClass().getResourceAsStream(url);
        FXMLLoader loader = new FXMLLoader();
        Node view = (Node) loader.load(fxmlStream);
        Controller controller = (Controller) loader.getController();
        controller.setView(view);
        return controller;
    }
    finally
    {
        if (fxmlStream != null)
        {
            fxmlStream.close();
        }
    }
}

And we’ve had to expose a setView() method on our controller Interface, and implement this in our AbstractController class. This is not ideal since we don’t want anyone actually ever calling this setView() method, but it does get the job done.

Controller.java

import javafx.scene.Node;

public interface Controller
{
    Node getView();

    /**
     * This method is needed only to allow the loadController() method in SampleAppFactory to
     * inject the view into this controller. Ideally FXML would allow us to specify @FXML on
     * in AbstractController on the 'view' field and this method would not be needed.
     */
    void setView(Node view);
}

AbstractController.java

import javafx.scene.Node;

public abstract class AbstractController implements Controller
{
    private Node view;

    public Node getView()
    {
        return view;
    }

    public void setView(Node view)
    {
        this.view = view;
    }
}

It’s a simple case now to refactor all of our controllers to use these base classes. For more details see the full source code for this post at: http://code.google.com/p/jfxee/source/browse/trunk/jfxee5/

Continue Reading→
    • Oct
    • 25
    • 2011

Views within Views, Controllers within Controllers

Posted by In Uncategorized

This entry is part 4 of 15 in the series Building JEE applications in JavaFX 2.0

GUIs are like onions (and Ogres) – they have layers. There are very few GUIs out there that show a single screen and that’s it. In traditional desktop applications we often end up with a screen full of complex sub-views, some tab panes perhaps, and often way too many popup dialogs. In a web app, we usually end up with a series of interconnected pages that hyperlink between each other, many of which contain sub-pages of information within them.

In either case we end up with the problem of how to embed and link our views and yet still keep them as nice, contained, reusable modules of code. At the core of it, all the presentation frameworks and architectures out there aim to address this issues in some way or another and FXML is no different. We just specify <fx:include> in our FXML file and the loader will magically pull in a second FXML file and drop it into our parent file. Great!

But there’s a problem. We’ve just come up with a great way to use dependency injection with our controllers and share resources between them, but this requires us to expose our controllers through the factory with the @Bean annotation. If the FXMLLoader magically creates our sub-views and sub-controllers for us, we’re back to square one.

So we need another way. In fact we need to make a mental gear change for this and come at it from another angle. The FXML approach assembles views by creating aggregates of other views, the controllers are somewhat of an afterthought. Sub-controllers have no real knowledge of their parent or child controllers, yet the views do. When we stop and think about this, shouldn’t it be the other way around? Our controllers should be the ‘brains’ of the operation, the views are just there to look pretty and smile.

Looking at if from this new angle, what we really need is a way to assemble controllers with sub-controllers and have these tell their corresponding views how to connect up with each other. As it turns out we’ve just put a mechanism in place for doing just that – dependency injection and a factory is exactly what we need to make this work.

In the rest of this post, I’m going to walk through a small example that has a three controllers. The MainController provides the outer container and a way to switch between the two sub-controllers (Page1Controller and Page2Controller) using a tab pane style approach. I’ll keep the controllers deliberately simple to get the idea across and, as usual, we’ll add more complexity in later posts.

Our end GUI is going to look something like this:

Let’s start with the simple stuff. Our two sub-pages will be simple, dumb controllers and views, just to give us something to work with. You can see the code for these here:

Now for the interesting stuff. Our MainController needs to provide a way to switch between the views – two buttons will do for this for now. It also needs a place for the sub-views to appear, and in our FXML this will just be a panel that acts as a container. Our FXML looks like this:

Main.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<BorderPane fx:id="view"
            fx:controller="com.zenjava.jfxspring.MainController"
            xmlns:fx="http://javafx.com/fxml">

  <styleClass> <String fx:value="welcome"/> </styleClass>

  <top>
    <HBox spacing="4">
      <children>
        <Button text="Show Page 1" onAction="#showPage1"/>
        <Button text="Show Page 2" onAction="#showPage2"/>
      </children>
    </HBox>
  </top>

  <center>
    <BorderPane fx:id="contentArea"/>
  </center>

</BorderPane>

So it’s left to our MainController to actually show the appropriate view when each button is selected. To do this it needs to get hold of the Page1 and Page2 controllers and then it can happily access the views for each. Using Spring’s @Autowired annotation we can easily achieve this, so long as all three controllers are exposed by our factory class. It all looks a little like this:

MainController.java

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.layout.BorderPane;
import org.springframework.beans.factory.annotation.Autowired;

public class MainController
{
    @FXML private Parent view;
    @FXML private BorderPane contentArea;

    @Autowired private Page1Controller page1Controller;
    @Autowired private Page2Controller page2Controller;

    public Parent getView()
    {
        return view;
    }

    public void showPage1(ActionEvent event)
    {
        contentArea.setCenter(page1Controller.getView());
    }

    public void showPage2(ActionEvent event)
    {
        contentArea.setCenter(page2Controller.getView());
    }
}

SampleAppFactory.java

import javafx.fxml.FXMLLoader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;

@Configuration
public class SampleAppFactory
{
    @Bean
    public MainController mainController() throws IOException
    {
        return (MainController) loadController("/Main.fxml");
    }

    @Bean
    public Page1Controller page1Controller() throws IOException
    {
        return (Page1Controller) loadController("/Page1.fxml");
    }

    @Bean
    public Page2Controller page2Controller() throws IOException
    {
        return (Page2Controller) loadController("/Page2.fxml");
    }

    protected Object loadController(String url) throws IOException
    {
        // as before (see full code for details)
    }
}

In the end, embedding views and controllers is actually quite simple with this approach. Architecturally it feels pretty clean, each of our child controllers is a stand-alone, reusable piece of code. Our parent controller has some fairly intimate relations with its children, and often this will be OK. In a lot of cases however, we will want a parent that is less tightly bound to its children. In the next post we’ll have a go at achieving that.

The full code for this post can be found at: http://code.google.com/p/jfxee/source/browse/trunk/jfxee4

Continue Reading→
    • Oct
    • 24
    • 2011

Multiple Controllers with Shared Resources

Posted by In Uncategorized

This entry is part 3 of 15 in the series Building JEE applications in JavaFX 2.0

In this post we’re going to create two controllers that share a common resource. We will start with something simple and unimpressive in this post and refine it into something more useful in subsequent posts.

For now we will create two controllers, one that allows us to edit our Person object, and another that provides a friendly welcome message for that person. Here’s how it will look:

To keep things simple, I’ve just placed the two views on the same top-level page and we’re not using property bindings so you will have to hit the ‘save’ button before hitting the ‘show welcome’ button. The goal here is to simply show how two controllers can share resources – we’ll create a more architecturally elegant solution soon enough.

Our code now consists of two controllers, EnterDetailsController and WelcomeController, and these each have a corresponding FXML file, EnterDetails.fxml and Welcome.fxml. These are pretty unexciting and straight forward – you can check out the code directly for more details. The only interesting thing in our controllers is that they both define the following:


@Autowired private Person person;

This tells Spring that we want the Person to be injected (aka ‘wired up’) automatically.

In our factory, we now load each of the controllers in separate methods in the factory and annotate these methods with @Bean. Spring will then inject the same person instance into each. Even though we create a new Person in the person() factory method, Spring knows to cache the result and reuse it for all injection because of the @Bean annotation.

Our factory now looks like this:

@Configuration
public class SampleAppFactory
{
    @Bean
    public Person person()
    {
        return new Person();
    }

    @Bean
    public WelcomeController welcomePageController() throws IOException
    {
        return (WelcomeController) loadController("/Welcome.fxml");
    }

    @Bean
    public EnterDetailsController enterDetailsController() throws IOException
    {
        return (EnterDetailsController) loadController("/EnterDetails.fxml");
    }

    protected Object loadController(String url) throws IOException
    {
        InputStream fxmlStream = null;
        try
        {
            fxmlStream = getClass().getResourceAsStream(url);
            FXMLLoader loader = new FXMLLoader();
            loader.load(fxmlStream);
            return loader.getController();
        }
        finally
        {
            if (fxmlStream != null)
            {
                fxmlStream.close();
            }
        }
    }
}

That’s it – sharing resources in a nice way via Dependency Injection is actually incredibly simple. It ought to be, that’s really what dependency injection is all about!

Of course, our example is still pretty raw and clunky but we’ll work on this over the next few posts to clean it all up.

The full source code for this post can be found at: http://code.google.com/p/jfxee/source/browse/trunk/jfxspring3/

Continue Reading→
    • Oct
    • 23
    • 2011

Better Controller Injection

Posted by In Uncategorized

This entry is part 2 of 15 in the series Building JEE applications in JavaFX 2.0

There are two things about our controller injection in our last post that I’m not entirely happy with. The first is that the SampleApp is the one responsible for loading the FXML file and wiring it up to the controller. We have a factory class for our UI (SampleAppFactory) so ideally all the work of creating and wiring up all the GUI elements should be done in here.

The second s that Richard’s post came from his earlier exploration of future directions for FXML and the discussions around that. Some of these features are not available yet, so Richard has found some creative ways to demo the concepts using scripting and the namespace. We probably don’t want to be using this style of coding for commercial apps so until the next release of FXML we need to work with what we’ve got – i.e. we need to have an explicitly named controller class in the FXML and let the loader instantiate our class and do our bindings. This has some drawbacks but using Spring (or Guice’s) annotation based configuration, we can make it work well enough.

For those that want to skip the details and just see the code: http://code.google.com/p/jfxee/source/browse/trunk/jfxspring2

So let’s first revert to the standard way of loading controllers in FXML and ditch the magical namespace and scripting. This standard way is well documented in the official FXML guide: http://download.oracle.com/javafx/2.0/api/javafx/fxml/doc-files/introduction_to_fxml.html

Our controller is now going to be defined and created in the FXML file, but using Spring’s (or Guice’s) annotation based injection we can still inject all the dependencies (so long as we use field injection and not constructor injection). One challenge though will be that both our controller and our view need to be available through the factory. The controller needs to be  exposed in order to get the Person bean injected into it, but our view needs to be exposed so that it can be added to the scene. The complication is that the FXML loader creates both in a single call, so we need to get creative.

There are a lot of ways to solve this problem, but the one that works best both now and for future benefits is to give the controller a reference to its view. Anyone wanting the view, can then just access the controller from the factory and retrieve the view from it.

So if we revert our controller back to the more traditional form, giving it access to its view is a simple case of binding the root node of the FXML to a variable in the controller. To keep life simple we’re not going to bother including the Person name on the button for now – we’ll add this back in later, it just confuses things at this stage. Here’s how it looks:

SampleController.java

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import org.springframework.beans.factory.annotation.Autowired;

public class SampleController
{
    @FXML private Node view;
    @Autowired private Person person;

    public Node getView()
    {
        return view;
    }

    public Person getPerson()
    {
        return person;
    }

    public void print(ActionEvent event)
    {
        System.out.println("Well done, " + person.getFirstName() + "!");
    }
}

sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?language javascript?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<StackPane fx:id="view"
           fx:controller="com.zenjava.jfxspring.SampleController"
           xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me" fx:id="printBtn" onAction="#print" />
    </children>
</StackPane>

Great, we now have a nice, simple, traditional controller. The whole point of this however was to get dependency injection working. Haven’t we lost this now that the controller is being created by the FXMLLoader? Not quite, luckily with Spring’s annotation based configuration we are free to create the controller anyway we want, the injected properties are set only when we return the controller from a factory method marked with @Bean. Let’s update our factory then to use the new controller. At the same time we will also remove the FXML loading from the SampleApp class and move it inside the factory – this was the second problem we wanted to solve.

Here’s how our factory now looks:

import javafx.fxml.FXMLLoader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;

@Configuration
public class SampleAppFactory
{
    @Bean
    public Person person()
    {
        return new Person("Richard");
    }

    @Bean
    public SampleController sampleController() throws IOException
    {
        return (SampleController) loadController("/sample.fxml");
    }

    protected Object loadController(String url) throws IOException
    {
        InputStream fxmlStream = null;
        try
        {
            fxmlStream = getClass().getResourceAsStream(url);
            FXMLLoader loader = new FXMLLoader();
            loader.load(fxmlStream);
            return loader.getController();
        }
        finally
        {
            if (fxmlStream != null)
            {
                fxmlStream.close();
            }
        }
    }
}

And here’s the start method for our SampleApp class. We’ve been able to remove the FXMLLoading from here – the application has no knowledge of how the views are loaded. If we wanted to change the view to be a normal Java class instead of FXML neither the controller, nor the application would need to be updated. Only the factory, which is responsible for creating the view, would need to be changed as you would expect.


public void start(Stage stage) throws Exception
{
    AnnotationConfigApplicationContext context
            = new AnnotationConfigApplicationContext(SampleAppFactory.class);

    SampleController sampleController = context.getBean(SampleController.class);
    Scene scene = new Scene((Parent) sampleController.getView(), 320, 240);
    scene.getStylesheets().add("fxmlapp.css");
    stage.setScene(scene);
    stage.setTitle("JFX2.0 Sprung");
    stage.show();
}

All in all, a somewhat cleaner setup.

It’s worth noting that there are some definite limitations and disadvantages to using the traditional controller binding approach. All of these have been raised with the JFX team (in JIRA) and several are being actively explored for future releases. In my opinion, although these drawbacks are annoying, at this stage they are worth living with since by using the official controller option we don’t have to use scripting or namespaces, so our app will be easier to maintain and be better supported by RAD tools and will be easier to get help and find docco on.

For the record however the limitations to be aware of are these:

  • The Controller class is specified in two places – the FXML and then cast-to in the factory. If you forget to update your FXML (very easy to do) then you will get a class cast exception in the factory. Ideally we would not have to specify the controller in the FXML at all.
  • You cannot use constructor injection – since the FXML is instantiating the controller, it must have an empty constructor.
  • Callback methods for button clicks must have an ActionEvent as part of the signature. This is easy to forget and will result in a runtime method. With the scripting option you did not have this restriction (the tradeoff being that you could not get the MouseEvent for mouse-style callbacks).
  • You cannot use the same FXML definition with different instances of a controller, i.e. you cannot attach sample.fxml to a controller other than SampleController without duplicating the FXML file.
  • You are limited to a single controller per FXML file, so you couldn’t have sample.fxml trigger callbacks in both SampleController and another controller.
  • You cannot share the same controller across multiple views as the loader will create a new controller for each FXML file. You couldn’t reuse the same SampleController instance used by sample.fxml with another fxml file, there will be two instances of SampleController created.
  • FXML does not support controller base classes. If your controller extends a base class and that base class has an @FXML annotated field on it, it will not get picked up by the FXMLLoader. You must define all @FXML attributes in the actual controller class itself.
There are probably a few other minor limitations but they are the big ones that I can think of.
In the next post we're going to look at what happens when you have a couple of controllers and ways to share information and navigate between them.

Continue Reading→
    • Oct
    • 23
    • 2011

JavaFX 2.0, FXML and Spring

Posted by In Uncategorized

This entry is part 1 of 15 in the series Building JEE applications in JavaFX 2.0

Richard Bair recently posted the results of his experiments with FXML Dependency Injection using Guice. I’m a big fan of Guice but Spring is the most popular application development framework for enterprise Java (that’s what their website says anyway), mainly because it offers much more than just a DI framework, with support for databases, transactions, remoting, security and much more.

As such, I’m intending for this post to be the first in a series, called Building JEE applications in JavaFX 2.0, where I’m going to explore various options for doing just that. This is new territory for everyone, so I welcome all feedback and comments that can help us refine the ‘best practices’ in this ares.

In this first post I’m just going to do a direct port of Richard’s FXML+Guice example into Spring. A lot of people still think Spring is all about XML configuration files, but it has evolved a lot since those early days. I’m going to use Spring’s annotation based configuration to create a pure Java example (i.e. zero Spring XML) that looks almost identical to the Guice one.

For those that want to skip the details and get straight to the code, you can find it here: http://code.google.com/p/jfxee/source/browse/trunk/jfxspring/

Note that this is a Maven project – I’m not going to go into detail on this in this post (I will later though), but it is a very simple project structure. If you’ve not used Maven before you can add your own ant scripts to the project or work out how to use Maven (both Eclipse and IntelliJ can open the pom.xml for you and just work).  

Step 1: create a Person bean:

This is pretty much the same as Richard’s


public class Person
{
    private String firstName;

    public Person(String firstName)
    {
        this.firstName = firstName;
    }

    public String getFirstName()
    {
        return firstName;
    }
}

Step 2: create a SampleController

This is similar to Richard’s however instead of using Guice’s @Inject annotation, we use Spring’s @Autowire one (I’ve annotated the parameter but you could use constructor injection if you want):

import org.springframework.beans.factory.annotation.Autowired;

public class SampleController
{
    @Autowired
    private Person person;

    public Person getPerson()
    {
        return person;
    }

    public void print()
    {
        System.out.println("Well done, " + person.getFirstName() + "!");
    }
}

Step 3: create the FXML file

This is identical to Richard’s, except I used the getPerson().getFirstName() instead of a getPersonName() – Richard could have done the same, no real difference on this.

<?xml version="1.0" encoding="UTF-8"?>

<?language javascript?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<StackPane fx:id="root" xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button fx:id="printBtn" onAction="controller.print()" />
        <fx:script>printBtn.text = 'Click Me ' + controller.getPerson().getFirstName() + '!';</fx:script>
    </children>
</StackPane>

Step 4:  Create a Spring Application Context

Here’s where things start to get interesting. Instead of the Guice ‘Module’ we need to define a Spring equivalent. In this case I have defined a class called SampleAppFactory (but you can call it anything) – the important bit is that it is annotated with Spring’s @Configuration. Each of the methods that are then annotated with @Bean belong to the context and Spring can do magic wiring for us. In our case the SampleController will get wired up with the Person because of the @Autowired annotation on it.

For anyone used to Spring XML, this class is pretty much a direct replacement of the XML configuration file:

import org.springframework.context.annotation.Configuration;

@Configuration
public class SampleAppFactory
{
    @Bean
    public Person person()
    {
        return new Person("Richard");
    }

    @Bean
    public SampleController sampleController()
    {
        return new SampleController();
    }
}

Step 5: Build a custom FXML loader

We can easily build the Spring equivalent of Richard’s GuiceFXMLLoader. It just needs to load the controller from the application context instead of the Guice Injector. In my next post I’m going to look at how we can simplify this and clean things up a little.

import javafx.fxml.FXMLLoader;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.io.InputStream;

public class SpringFxmlLoader
{
    private ApplicationContext context;

    public SpringFxmlLoader(ApplicationContext context)
    {
        this.context = context;
    }

    public Object load(String url, Class<?> controllerClass) throws IOException
    {
        InputStream fxmlStream = null;
        try
        {
            fxmlStream = controllerClass.getResourceAsStream(url);
            Object instance = context.getBean(controllerClass);
            FXMLLoader loader = new FXMLLoader();
            loader.getNamespace().put("controller", instance);
            return loader.load(fxmlStream);
        }
        finally
        {
            if (fxmlStream != null)
            {
                fxmlStream.close();
            }
        }
    }
}

Step 6: Create an ‘Application’ to launch it all

This is quite similar to the Guice approach, except we load our application context instead of the Guice injector:

import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SampleApp extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }

    public void start(Stage stage) throws Exception
    {
        AnnotationConfigApplicationContext context
                = new AnnotationConfigApplicationContext(SampleAppFactory.class);
        SpringFxmlLoader loader = new SpringFxmlLoader(context);

        Parent root = (Parent) loader.load("/sample.fxml", SampleController.class);
        Scene scene = new Scene(root, 320, 240);
        scene.getStylesheets().add("/fxmlapp.css");
        stage.setScene(scene);
        stage.setTitle("JFX2.0 Sprung");
        stage.show();
    }
}

That’s it! As you can see the code is extremely similar to Guice so the choice between Guice and Spring should depend on the other features offered by each and how these may benefit you. I’m going to stick with Spring for this series, but a lot of what I go through could easily be adapted back to Guice.

Continue Reading→