- JavaFX 2.0, FXML and Spring
- Better Controller Injection
- Multiple Controllers with Shared Resources
- Views within Views, Controllers within Controllers
- Generic Controllers
- Client Server with JavaFX 2 and Hessian (+Guice +FXML)
- JFX Flow early access
- JavaFX and MVP – a smörgåsbord of design patterns
- JavaFX and Maven
- Porting “First Contact” to Spring
- Going Remote – JavaFX and Spring Remoting
- JavaFX and persistence: adding database support
- Search like you mean it
- Captains Log
- JavaFX and Spring Security
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/

Hi Zonski!
Is the default behavior of Spring to share the resource?
Hi Alan,
If I understand your question correctly, then ‘yes’ – when you annotate a factory method with @Bean then Spring will, by default, make sure only one instance of the object is created and so it is shared.
So if my factory method is:
@Bean
public SomeThing createSomeThing()
{
return new SomeThing();
}
Then when you inject SomeThing into other classes, only one Object will exist in memory and will be shared. Spring basically caches it and shares it everywhere. Spring actually does this by rewritting the Java class at runtime (pretty hard core stuff) so even if you directly call the method from within the factory class the instance will be cached.
Sometimes you don’t want this behaviour, in that case you can add the annotation of @Prototype, which tells Spring you want the resulting Object to be created every time it is injected so then it is not shared.
That was my doubt.
Thanks for the explanation.