Just bind it

The javafx binding concept is nice and powerful. But sometimes it might be a bit difficult to figure out how to use it.

Let's assume you have the following bean
and you need a variable bound to the sum of x*y for a sequence of those beans. Actually this problem can be expressed more generally: how to bind a variable to the result of a function applied to a sequence of elements (i.e. have it updated each time the sequence is modified or a field of a bean is modified). In java you would required tons of PropertyChangeListener registered correctly. With javafx you can write it in a more concise way using the bind keyword and bounded functions. But the first time I wanted to write it, I had to fight a little bit with the syntax. So I wanted to share this small unit test demonstrating a way to achieve this:

MediaPlayer keeping quiet

According to the javafx media tutorial, playing a sound is simple. JavaFX provides a MediaPlayer to easily play any media source. You just need to define your Media by it's URI, so this should looks like:
This seems very easy, but if you tries this, you might here nothing!
Then you are certainly in one of the two following cases:
  • Your sound resource is packaged within your jar. This is not supported for the moment, see javafx faq
  • You are trying to play a short sound sample. The first time I tried to play a 2s sound sample, my speakers kept desperately quiet. So what happened? A look at the Improve Media Performance tutorial put me on the way to the solution: according to this article, "for faster playback of a streaming media that is progressively downloaded, it helps to initialize the engine first by using the same media behind the scenes". So, when you call the play function of the MediaPlayer, that playback engines "crunches" the first seconds of the sound sample during it's initialization. For a long sound, you just almost don't notice it, but a short sound sample might totally vanish. Unfortunately the MediaPlayer does not provides an init method, and the only way you can do it for the moment is to set your player to mute, play your media once and then rewind and unmute. It's quiet ugly, but it's the "official" solution proposed in the previous article. If you have a better solution, I'd be happy to hear it. Or just hope that javafx 1.3 will add an init method to the MediaPlayer.

Unit testing your javafx application

In my last post I described how to set up a maven-javafx project using the jfrog-javafx plugin. One essential point was still missing in the configuration: the execution of javafx unit tests. By default, the jfrog-javafx plugin is not configured to handle a test folder. So let's see how to do that:
  • Create a src/test/javafx folder in your project
  • Put a unit test in this folder. Note that javafx does not support annotations, so the test must be written according to junit 3 rules. (however, you can use junit 4 in your dependencies, since it's backward compatible)
  • Update the configuration of the jfrog-javafx plugin to compile both the main and the test javafx folders. We define two executions for this plugin. The main execution will process the javafx resources and compile the javafx code in src/main/javafx during the compile phase. The test will compile the javafx code in src/test/javafx during the test-compile phase. You might also notice that junit is declared as a dependency of the plugin to fix a classpath issue since the jfrog-javafx plugin does not include the dependencies with test scope during compilation
  • Now your javafx test should be executed during the test phase of the maven lifecycle like a regular java unit test. You can now let hudson run your javafx unit tests at each build!

Spice up your JavaFX project with maven

Click here to download:
MavenFX.zip (7 KB)

JavaFX is a promising technology for nice Rich Internet Applications (RIA). However this is a quiet recent product (it was introduced by Sun at JavaOne, May 2007) and still lacks at integration with continuous development environments like hudson. Continuous integration is great because it reduces the gap between the development process and the release phase. With continuous integration, the work made by the developers is continuously compiled and tested against unit tests. This helps detecting many problems very early and simplifies the whole development process.

Hudson is an integration server that works very nicely with maven projects. So the first step to integrate a JavaFX project into our continuous integration environment was to "mavenize" the project. Jfrog has developed a javafx plugin for maven that integrates the compilation of the javafx sources into the maven lifecycle. Moreover it can generate a jnlp to launch the project. 

However, this plugin is by default configured to work with artifactory. For some reasons you might want to use it without artifactory, and that's possible. Just checkout the attached project to see how to configure it. Since artifactory takes care of some jnlp deployment issues, some additionnal plugins are required in this case: the dependency-plugin will copy the dependencies at the codebase directory of the jnlp and the jar-signer plugin will sign these jars.

At this step your project is fully integrated in the maven world. The last step is to deploy automatically the jnlp and required jars on a server to test your project. This can be achieved with the wagon plugin and its ftp extension (see attached project for an example of configuration). Then hudson can automatically deploy your application after each build by calling the mvn:deploy target. Enjoy!

Note: in the attached project, we use profiles (see profiles.xml) to configure the project dynamically whether this is intended to be run locally or deployed on a remote server. The "dev" profile allow you to run the project locally (using mvn clean package jfrog-javafx:excute) and the "prod" profile if for deployment (mvn -P-dev,prod deploy)