Things are getting pretty exciting in the land of JavaFX. The platform seems to be gaining traction and we’re starting to see a real community build up around the forums and the open source channels. As a result we’re also seeing more developers moving beyond the ‘hello world’, and ‘colourful circles’ stage and setting their sights on real application development. With that comes a need for design patterns and best practices and these are currently lacking, or at least lacking in documentation.
In this post, I’m going to run through a few options for implementing the Model View Presenter (MVP) pattern using JavaFX. If you’re not familiar with MVP it’s basically the latest re-branding of the MVC pattern. The ‘Controller’ has been replaced with a ‘Presenter’ but the same big concepts apply. To be honest there’s so many variations and interpretations on MVC that you may already be using MVP under the guise of MVC anyway. This article does a decent job of quickly outlining the key differences, but there are loads more articles on the web. Martin Fowler, has provided a lot of analysis on MVP as well, and has split the term further.
We’re not going to get too hung up on theoretical purity and academic classifications however. Our goal is to get a usable pattern in place that just works, making it easier to develop and maintain a complex, production grade project. The theoretical semantics can be left to the academics who don’t have to build real world apps for a Monday deadline.
First things first, we need an application to build. Something a little more complex than HelloWorld but still simple enough for us to easily work with. A very basic contact management system (i.e. an address book) should do the job. We’ll call it ‘First Contact’, and for the sake of simplicity it will have only two screens: a search screen that lets you filter the list of contacts, and a detail screen that lets you view and edit the basic details of each Contact.
The ‘search’ screen will look a little like this:
And the ‘detail’ screen will look something like:
The Business Layer
We’ll design the system as if the data was coming from a remote server (and probably a database) but since this post is all about UI design patterns we will just provide a local stub for this and not worry about the remote aspects (though you can easily use my earlier post on using Hessian to replace the local implementation with a remote one).
Our business layer consists of just a simple Contact bean, a ContactService interface for accessing the store of contacts and a local stub-implementation of this service for us to work with. The code for each of these is fairly trivial:
A note on Dependency Injection
If you’ve read my previous posts you’ll know that I’m a bit of a Dependency Injection (DI) fan, and I’d definitely recommend using either Guice or Spring as a DI toolkit to wire up your JavaFX applications.
I realise however that DI can seem like a magical and perhaps complex thing for a lot of people unfamiliar with it (a lot of desktop developers have not had a lot of exposure to it yet). I’m going to let you in on a little secret though: there is no magic to dependency injection. Seriously, all it means is to pass an instance into anther class rather than instantiating or looking it up from within that class itself. This has the rather fancy name of “Inversion of Control”, which just means the bean is no longer in control of looking up the resources, the thing that creates the bean has to look it up and pass it in.
public class MyClass
private MyOtherClass myOtherClass;
this.myOtherClass = new MyOtherClass(); // or jndi.lookup("myOtherClass"), etc;
public class MyClass
private MyOtherClass myOtherClass;
public MyClass(MyOtherClass myOtherClass)
this.myOtherClass = myOtherClass;
If you’ve never taken the plunge into DI before, you’re probably wondering what all the fuss is about; if it’s just passing variables around, why is everyone always banging on about it. The answer to that is that while the pattern itself is incredibly simple, when you combine it with things like aspect-oriented-programming, annotations, mock objects for testing, etc this tiny shift starts to have powerful advantages.
So, in the interest of not scaring anyone off, and just to demonstrate how simple DI actually is, I’m going to avoid using any DI framework in these patterns. You won’t see any Guice or Spring in the following code. I’ll still use DI (i.e. I’ll pass variables in instead of instantiating them) but I’ll just wire it all up in plain, regular Java with no magical help from Guice or Spring.
Obviously, I’d recommend that you get familiar with and use a DI toolkit in your apps – depending on how I go for time, I may post the Spring and Guice equivalents of the below MVP patterns in a future post. If you’re keen to see this, post a comment to let me know.
Enough pre-amble, let’s get to it! Below are five different ways to build the same First Contact GUI outlined above. They all work, they are all OK. Some people will like one and others will prefer another. I have my favourites but it is totally up to you which one you choose to use.
Option 1: Keeping it Simple
In this option we use the most basic approach possible. Since we’re using MVP we obviously have a Model a View and a Presenter for each component on the screen.
Our View is focused solely on the visual representation of the screen; it is what the user sees. The View builds the layout of the controls and sets the styling but does none of the processing logic. When a user action occurs (such as a button click) the View passes this on to the Presenter for handling.
Our Presenter is then responsible for the ‘control’ logic. In this case it is responsible for interacting with our ContactService to load and save contact information. The Presenter is responsible for all threading and error handling. It is the brains behind the view and in many ways is the ‘boss’ of the view. If a button is clicked in the view, it is the Presenter that decides what happens and it then tells the View what information to show.
In this simple MVP scenario, our Model is just the Contact bean, which we defined as part of our Service model. It is a regular Plain Old Java Object returned by the ContactService. Unlike the more traditional MVC approach, the model in this case is somewhat temporal; the Presenter grabs a fresh Contact or list of Contacts from the Service every time the screen is loaded and passes this to the View. Once the data is loaded into the fields within the view, the bean is then discarded. In this approach our Model is more like a Data Transfer Object (DTO), used to transfer the data between our view and our ‘true’ model, which is the database hidden by our server.
Looking at our proposed UI, we obviously have two main screens: the ‘search’ screen and the ‘detail’ screen. As such, we’ll need a View and a Presenter for each of these. We’ll step through the more interesting bits of these now, but for reference, the full code for each of these is here:
Looking at our two views, the ContactSearchView and ContactDetailView, we see that these just create the controls needed and lay them out appropriately. When it comes time to handle a button click however, they simply call onto their Presenter (which has been passed into them via the constructor following the DI pattern).
In both views, the data they display (i.e. the search results and the contact details) is passed to them and neither view has any knowledge of how that data was loaded or the semantics behind that data. The ContactSearchView for example has no idea whether the terms in the search TextField match the data in the results ListView – this is not it’s job, like a good soldier, it just does what it is told, whether that’s right or not.
The Presenters are the more interesting players in this game. At the request of the View, these Presenters perform some threading to access the ContactService. This threading is overkill when we have a local service implementation (as we currently do), however if you are making remote calls you need to use Threads (see this slightly outdated post about it). I use a Task here, and given our Presenters are simply calling onto a service, Tasks are nearly always sufficient. You could easily substitute a Service but that is only useful if the code you are executing within the thread is complex and you want to reuse that code in several places.
So we have our two Views and two Presenters and they are nice, stand-alone modules. We need to integrate them however into our bigger application and provide a way to switch between these two views. To do this I have introduced another View, called the MainView, and a corresponding Presenter, called the MainPresenter. The MainPresenter contains the ‘search’ and ‘detail’ presenter and it controls which one is currently active and showing. The MainView is basically just a BorderPane with a header. Its content area (i.e. its center) acts much like a ‘CardLayout’, allowing the MainPresenter to swap the SearchView and DetailView in and out.
We provide both the ContactSearchPresenter and the ContactDetailPresenter access to the MainPresenter (via DI), so that they can request a change in the currently active screen. For example, the ContactSearchPresenter detects when a Contact has been selected in the search results and then it asks the MainPresenter to show the details for that Contact. This provides us with some reasonable decoupling, although it would be even better to use an event bus of some kind to control this navigational change. That’s one of the things JFX Flow does however, so if you want to go down that road I would suggest looking into JFX Flow before rolling your own solution (see option 5 below).
All we need to do now is wire up our three modules. As mentioned in the pre-amble, I’m not going to use Spring or Guice, which just means I have to do a bit more coding. All I really have to do is create a Factory for the whole UI and provide a factory method for each of the components of the application. To wire everything up I just call onto the factory methods as needed. This is really quite simple and you can see the code for yourself here:
Finally we just create an Application class to be the entry point for our First Contact application. Since most of the heavy lifting happens in our factory, the Application class is really quite simple; it just needs to create a new factory and extract the MainView from this and add it as the root of the scene. The code for this can be seen here:
Option 2: Interfaces for the purists
This second option is very similar to Option 1, however we introduce interfaces for all our Views and Presenters. This approach will probably be popular with purists and people from a strong dependency injection and aspect-oriented-programming background as it allows you to totally decouple your view and presentation implementations from each other. GWT developers also may find this approach comfortable as it is the recommended GWT design pattern (not surprising, since Guice and GWT are close friends).
The code changes are really quite simple, where we had a single View before we now have a View (which is an interface) and a ViewImpl (which is the implementation of that View). Similar for the Presenter. These classes all then reference each other only by their interface, and only the factory class actually has any awareness of the implementations, which is what any purist will tell you is “as it should be”.
We end up with the following:
And our Factory now looks like this:
One of the big benefits of this approach is that it allows you to easily use Mock objects to test your components (although UI testing is still a messy topic at best so the benefits of this are only valid if you are going to put in the effort to actually test your GUI).
Option 3: MVP with a PresentationModel
In this option we introduce the concept of a PresentationModel, which is a model that represents the state of the view. In the case of the search view, for example, the model holds the current text in the search text field and the list of results showing in the results list.
So we end up with a Model for each of our three modules, like so:
Our Presenters then populate these models when they get data back from the server (instead of passing the data to the view directly). Our Views bind to the model properties (bidirectionally), so that whenever a change happens on the model it is reflected on the screen, and vice versa.
Our MainModel may look a little weird. Why does a Model have a Node in it? Remember that this is a ‘presentation’ model, and the ‘state’ of the MainView is really which sub-view it is showing. A node in the model is ok in this case. If we wanted to get pedantic (and someone always does) then we could have an enumerated type for the currently showing sub-view and this could be our model value, with the MainView mapping that to the appropriate Node. If you like that sort of stuff however, you might want to have a look at JFX Flow, which uses a ‘Place’ to represent the current active page and a whole lot more.
One positive with this approach is that it does allow us to make use of JavaFX bindings, which have been sadly unhelpful in our other options. On that basis, you would think the resulting code would be simpler and cleaner, but I don’t find it overly nice – there’s a lot of extra code for no obvious gain that I find useful. You are free to make up our own mind.
This pattern could be a lot more useful if we weren’t designing for a client-server application. If our Model could live in memory on the client side then having a shared model between the screens might become a lot more useful. These kind of applications are not overly common these days though (I haven’t had to make one since 2002).
You could also argue that we already have a PresentationModel in our other options. Each JavaFX Control contains a ‘model’ of sorts. For a TextField, this is the ‘text’ property, for a ListView it is the list of items. In this scenario however we create a model that is ‘control agnostic’ (meaning the model has no idea what type of control is being used to display the data) and then we expose that model to both the view and the presenter.
A quick academic side note: if we look at Fowler’s descriptions of MVP, then this approach is more in line with his Supervising Presenter pattern, whereas our previous options have been more the flavour of his Passive View pattern (where we use a DTO to pass the attributes to the view, and this DTO just happens to be our domain object).
Option 4: FXML and the MVP compromise
If you haven’t had a chance to play with FXML yet, I recommend giving it a go. FXML is an XML-based toolkit for building JavaFX scenes using a syntax that is simple enough for designers and junior coders to use, while still allowing your power coders to hook in and do the real work.
I’m usually the last person to advocate anything other than data being defined in XML and I’ve always hated XML GUI coding tools in the past. It’s strange then that I’ve come to like FXML but the key difference between FXML and other XML coding toolkits that I’ve seen is the clear separation of roles between view and control. In many other platforms, the XML ends up as a scripting language, and it is so verbose and clumsy for this that the resulting scripts are almost comical. In FXML the XML part is used only for layout, for any actual coding/logic, there is a natural fall-out to a ‘backing bean’ or controller.
So if FXML provides the controls and visual layout for our screen it is obviously a prime candidate for replacing the Java-based View’s we’ve defined in our previous options. This is good news, but it’s not all roses however. FXML has been designed with RAD tooling in mind (i.e. visual screen design tools), and seems to draw from backgrounds that are a little less rigorous in their design patterns than Java normally encourages.
As a result there are a number of areas where using FXML forces us to compromise on our pure MVP pattern. Here’s a few of them:
- You have to specify your presenter (which FXML directly calls a controller) implementation inside your FXML. This breaks a fundamental concept of MVP, that the view and presenter should be decoupled as much as possible, and means you cannot reuse your view with another controller without copying the whole view again.
- You can’t use interfaces for your presenter (as per option 2 above), since FXML needs a concrete class to instantiate.
- The FXML loader instantiates the controller in internal code that we have no access to, so to make this work with a DI framework you have to jump through hoops to get setter injection to work (and constructor injection doesn’t work at all).
- In order to access the fields of your view within your presenter (i.e. to show data on the screen), you have to expose the fields directly to the presenter using @FXML annotations. This means your presenter ends up knowing far too much intimate detail about your view.
There are a number of other smaller issues (like Controller inheritance not being supported) but for me, the end result is still better than not using FXML – the compromises are worth the benefits of the concise view syntax and simple notation for designers (i.e. it’s not too far a stretch for someone who know how to write HTML). There are also a couple of enhancements in the pipeline for JFX 2.1 that will improve (but not completely solve) some of these issues. You can make up your own mind whether the benefits are worth it to your or not.
So how does this FXML/MVP compromise look? First, the easy bits. We can directly convert our Views to FXML. This is very simple and the resulting code is quite a bit nicer:
There is one hurdle however, there’s no easy way to define our custom list renderer (i.e. the CellFactory) in FXML, it’s just too cumbersome. We end up having to define this within our presenter, which is not ideal.
Our Presenters are quite significantly different. Instead of interacting with a nice, contained view, the Presenters now have to access the plumping of the view directly. That is, they need to get a reference to the actual controls they want to interact with and manipulate them directly.
It’s worth noting that in the next release of FXML there is plans for bidirectional binding support, which will improve this somewhat, but it is unlikely to decouple our Presenter completely from the internal workings of the FXML defined View. The custom CellFactory is one example of this, and another is the need to have our callbacks include ‘view’ events such as the ActionEvent parameter needed for the ‘search’ method.
Here’s how our FXML-based Presenters look:
As I mentioned, we also now have some extra complexities in loading and wiring up our Presenters. The FXMLLoader does the instantiating for us, so we can’t use constructor based injection, instead we have to fall back to manually calling ‘set’ for every resource needed by each view.
You can see all the gory details here:
All in all, a definite compromise on purity for the sake of convenience. I personally feel it is one worth making and am using FXML in all my applications. You can make up your own mind.
Option 5: JFX Flow and MVP
And finally, we have JFX Flow, which is a framework I’ve put together to provide some extra tools when working with JEE style applications, especially those you want to look more like a browser-based web-app. If you haven’t done so yet, check out the runnable showcase on the homepage for a general overview.
JFX Flow can actually be used with any of the design patterns above. It is however designed with FXML in mind and encourages a pattern similar to that outlined in option 4. One of the biggest changes however, is that you don’t need a MainPresenter or MainView at all. These are provided for you out of the box with JFX Flow via the Browser class.
The FXML for the JFX Flow option is identical to option 4, with no actual changes needed. The Presenters are similar in structure, however there are a couple of key changes.
- Each Presenter needs to extend the JFX Flow AbstractActivity* base class.
- Since we no longer have a MainPresenter, we need to use a NavigationManager instead. Each Presenter gets registered with Browser with a unique ‘place name’ that the NavigationManager can be used to navigate to.
- We can use the activated() method to detect when a Presenter is made the active page. Any parameters needed for the page are passed to fields marked with the @Param annotation.
- When we execute a task, instead of creating a new Thread directly we make use of the AbstractActivity.execute(Task) method. This gives us better error handling and blocks the screen while the load is in progress – two things we conveniently ignored in our earlier patterns.
* Note: In JFX Flow I have opted for the term ‘Activity’ instead of Presenter and you will see this throughout the documentation. The two terms are interchangeable and just for consistency in this post I have left it as Presenter in the sample code. The Activity term has been popularised by GWT and I feel is a better fit than either ‘Controller’ or ‘Presenter’ (especially since JFX Flow does not dictate the use of either of these). The end result is quite nice and logical: a user navigates to a ‘Place’ to carry out an ‘Activity’.
Here are the JFX Flow versions of our Presenters:
Our factory is where the Presenters are registered with the Browser:
And our Application entry point now needs to use the Browser instead of the MainView:
If we run this application as is, we see a GUI like following:
Notice that the Browser bar has appeared for us, and we now have a back, forward and refresh buttons all for free. As we navigate between screens we see page transitions (the default is to fade in and fade out, but you can configure your own), and the screen will be blocked while our background threads are running.
This is all pretty neat and more powerful than our previous patterns (otherwise there wouldn’t be much point to JFX Flow!). However it is not exactly the task we were given. We wanted to build an app identical to the others and currently we have this toolbar up the top and we don’t see our nice blue header.
Luckily we can change that. The JFX Flow Browser provides a setHeader() method which can be used to completely replace the toolbar at the top. All we have to do is create a small class for our header and set this in its place. I’ve been lazy and just done this in code, but you could of course do this in FXML as you want:
This is a very simple way to customise the Browser, however JFX Flow fully supports you totally redesigning your Browser and structuring it however you want. You can set the header (or set it to null) as described, or provide your own custom skin class, and if that isn’t enough for you, the tools are there to piece together your own Browser completely and build whatever layout you want with side-docking panes, shortcut bars and history lists (I’m working on this docco for this, promise!).
Well I hope that’s been a helpful introduction to JavaFX with the MVP pattern. There are plenty of other ways to put together a clean JFX application (and I’d love to hear from people out there if they have any improvements or alternatives) but the ones listed above should provide you with a nice base to work off.
Obviously I have a strong preference to the JFX Flow approach and would suggest that your life will be a lot easier when building large, page-based GUIs if you make use of this framework. When it comes to design patterns however, it’s a case of finding the right shoe for the foot: I hope this article helps a few of you on your path to finding your Cinderella.