Search This Blog

JavaFX 2 with Spring

I'm going to start this one with a bold statement: I always liked Java Swing, or applets for that matter. There, I said it.
If I perform some self analysis, this admiration probably started when I got introduced to Java.
Swing was (practically) the first thing I ever did with Java that gave some statisfactionary result and made me able to do something with the language at the time.
When I was younger we build home-brew fat clients to manage our 3.5" floppy/CD collection (written in VB and before that in basic) this probably also played a role.

Anyway, enough about my personal rareness. Fact is that Swing has helped many build great applications but as we all know Swing has it drawbacks.
For starters it hasn't been evolving since well, a long time. It also requires a lot of boiler plate code if you want to create high quality code.
It comes shipped with some quirky design "flaws", lacks out of the box patterns such as MVC.
Styling is a bit of a limitation since you have to fall back on the limited L&F architecture, I18N is not build in by default and so on.
One could say that developing Swing these days is well, basically going back into time.

Fortunately Oracle tried to change this some years ago by Launching JavaFX.
I recall getting introduced to JavaFX on Devoxx (or Javapolis as it was named back then).
The nifty demo's looked very promising, so I was glad to see that a Swing successor was finally on its way.
This changed from the moment I saw its internals. One of its major drawbacks was that it was based on a dark new syntax (called JavaFX script).
In case you have never seen JavaFX script; it looks like a bizarre breed between Java, JSON and JavaScript.
Although it is compiled to Java byte-code, and you could use the Java API's from it, integration with Java was never really good.

The language itself (although pretty powerful) required you to spend a lot of time understanding the details, for ending up with, well, again source code, but this time less manageable and supported then plain Java code.
As it turned out, I wasn't the only one. A lot of people felt the same (for sure there were other reasons as well) and JavaFX never was a great success.

However, a while ago Oracle changed the tide by introducing JavaFX 2.
First of all they got rid of JavaFX script (which is no longer supported) and turned it into a real native Java SE API (JavaFX 2.2.3 is part of the Java 7 SE update 6)
. The JavaFX API now looks more like the familiar Swing API, which is a good thing.
It gives you layout managers lookalikes, event listeners, and all those other components you were so used to, but even better.
So if you want you can code JavaFX like you did Swing you can, albeit with slightly different syntax and improved architecture.
It is also possible now to intermix existing Java Swing applications with JavaFX.

But there is more. They introduced an XML based markup language that allows you to describe the view. This has some advantages, first of all coding in XML works faster then Java.
XML can be more easily be generated then Java and the syntax for describing a view is simply more compact.
It is also more intuitive to express a view using some kind of markup, especially if you ever did some web development before.
So, one can have the view described in FXML (thats how its called), the application controllers separate from the view, both in Java, and your styling in CSS (yeah, so no more L&F, CSS support is standard).
You can still embed Java (or other languages) directly in the FXML; but this is probably not what you want (scriptlet anti-pattern).
Another nice thing is support for binding. You can bind each component in your view to the application controller by putting an fx:id attribute on the view component and an @FXML annotation on the instance variable in the application controller.
The corresponding element will then be auto injected, so you can change its data or behavior from inside your application controller.
It also turns out that with some lines of code you can painlessly integrate the DI framework of your choice, isn't that sweet?

And what about the tooling?
Well, first of all there is a plug-in for Eclipse (fxclipse) which will render you FXML on the fly. You can install it via Eclipse market place:

The plug-in will render any adjustment you make immediately:

Note that you need at least JDK7u6 for this plug-in to work. If your JDK is too old you'll get an empty pane in eclipse. Also, if you create a JavaFX project I needed to put the jfxrt.jar manually on my build classpath. You'll find this file in %JAVA_HOME%/jre/lib.

Up until know the plug-in doesn't help you visually (by drag& drop) but that there a separate IDE: scene builder. This builder is also integrated in Netbeans, for AFAIK there is no support for eclipse yet so you'll have to run it separately if you want to use it. The builder lets you develop FXML the visual way, using drag&drop. Nice detail; scene builder is in fact written in JavaFX. Then you also have a separate application called scenic view which does introspection on a running JavaFX application and shows how it is build up. You get a graph with the different nodes and their hierarchical structure. For each node you can see its properties and so forth:

Ok, so lets start with some code examples. The first thing I did was design my demo application in scene builder:

I did this graphically by d&d the containers/controlers on to the view. I also gave the controls that I want to bind to my view and fx:id, you can do that also via scene builder:

For the buttons in particular I also added an onAction (which is the method that should be executed on the controller once the button is clicked):

Next I added the controller manually in the source view in eclipse. There can only be one controller per FXML and it should be declared in the top level element. I made two FXML's, one that represents the main screen and one that acts as the menu bar. You probably want a division of your logic in multiple controllers, rather then stuffing to much in a single controller – single responsibility is a good design guideline here. The first FXML is “search.fxml” and represents the search criteria and result view:

On line 7 you can see that it uses a different controller.
In Eclipse, if you open the fxclipse view from the plug-in you will get the same rendered view as in scene builder. Its however convenient if you want to make small changes in the code to see them directly reflected:
The code for launching the application is pretty standard:

The only special thing to note is that we extend from Application. This is a bit boiler plate code which will for example make sure that creating of the UI happens on the JavaFX application thread. You might remember such stories from Swing, where every UI interaction needs to occur on the event dispatcher thread (EDT), this is the same with JavaFX. You are by default on the “right thread” when you are called back by the application (in for example action listeners alike methods). But if you start the application or perform long running tasks in separate threads you need to make sure you start UI interaction on the right thread. For swing you would use SwingUtilities.invokeLater() for JavaFX: Platform.runLater().
More special is our SpringFxmlLoader:

The highlighted lines show the custom ControllerFactory. Without setting this JavaFX will simply instantiate the class you specified as controller in the FXML without anything special. In that case the class will not be Spring managed (unless you would be using CTW/LTW AOP). By specifying a custom factory we can define how the controller should be instantiated. In this case we lookup the bean from the application context.
Finally we have our two controllers, the SearchController:

After playing a bit with JavaFX2 I was pretty impressed. There are also more and more controls coming (I believe there is already a browser control and such). So I think we are on the right track here.

Comments

The "SpringApplicationConfig" in my example is the Spring annotated Java class (@Configuration) which functions as "application context configuration" and thus contains the bean declarations (@Bean). I left it out since it just the plain Spring configuration annotation style. If you want to see an example checkout the code ApplicationConfiguration.java belonging to my post: unit-testing

I have a FX-Spring-Hibernate project with a tabPane-like frontend (1 main window with 2 buttons and a BorderPane).I have 1 MainController that has 2 @Autowired controllers in it. Depending on the button pressed you'll get a different view, each controlled by their own (@Autowired) controller.

Using the same aproach as in this article I managed to get my Spring beans injected into my controller classes, but the @FXML UI components in the @Autowired controllers were null. This is probably caused by the fact that FX doesn't control the injection anymore and thus the whole controller hierarchy isn't loaded.

I 'solved' this by making the custom controller factory a utility class, and removed the @Autowired annotation - so I can fully load the controllers manually.

Post a Comment

Popular Posts

If you need to process large database result sets from Java you can opt for JDBC to give you the low level control required. On the other hand if you are already using an ORM in your application falling back to JDBC might imply some extra pain. You would be losing features such as optimistic locking, caching, automatic fetching when navigating the domain model and so forth. Fortunately most ORMs, like Hibernate, have some options to help you with that. While these techniques are not new, there are a couple of possibilities to choose from.
A simplified example; let's assume we have a table (mapped to class "DemoEntity") with 100.000 records. Each record consists of a single column (mapped to the property "property" in DemoEntity) holding some random alphanumerical data of about ~2KB. The JVM is ran with -Xmx250m. Let's assume that 250MB is the overall maximum memory that can be assigned to the JVM on our system. Your job is to read all records currently in …

This week it was time to upgrade our code base to the latest Hibernate 4.x.
We postponed our migration (still being on Hibernate 3.3) since the newer maintenance releases of the 3.x branch required some API changes which were apparently still in flux. An example is the UserType API which was still showing flaws and was going to be finalized in Hibernate 4.

The migration went quite smooth. Adapting the UserType's to the new interface was pretty straightforward. There were some hick ups here and there but nothing painful.

The thing to watch out for is the Spring integration. If you have been using Spring with Hibernate before, you will be using the LocalSessionFactoryBean (or AnnotationSessionFactoryBean) for creating the SessionFactory. For hibernate 4 there is a separate one in its own package: org.springframework.orm.hibernate4 instead of org.springframework.orm.hibernate3. The LocalSessionFactoryBean from the hibernate 4 package will do for both mapping files as well as annotate…