Getting started with Griffon and JavaFX part II - No Fluff Just Stuff

Getting started with Griffon and JavaFX part II

Posted by: Andres Almiray on July 4, 2014

The first part of these series presented how Griffon 2.0.0.BETA3 can be used to create a JavaFX application with Java as the main language. In this post I'm going to show the same application but using Groovy instead of Java.

Why Groovy? I can think of many reasons to go with this option, chiefly

  • reduced verbosity
  • the compiler understands Java conventions (properties for example)
  • the compiler is extemsible via AST transformations
  • dynamic and static mode
  • runtime additions (GDK)
  • closures!

The last two points can be contended at some point given that JDK8 brings extension methods and lambda expressions, however I beg to differ and pick Groovy's side as its additions are still relevant, even on top of JDK8.

Getting started with JavaFx, Groovy and Griffon requires the same steps as in the first post: having JDK8, Lazybones and Gradle installed. You can use GVM to keep those tools up to date. Open a terminal prompt and issue the following commands

$ curl -s get.gvmtool.net | bash
$ gvm install lazybones
$ gvm install gradle

Don't forget to edit ~/.lazybones/config.groovy file in order for Lazybones to find the Griffon project templates

Issue the create command with the following options; you'll be prompted to pick some values, let all defaults except for the final question: className

Now change into the generated directory (sample-javafx-groovy). The directory structure should look very similar to this one

Notice that the structure is exactly the same as in the Java version of the same application, only this time the source files are Groovy based. The build file is slightly modified too

We appear to be missing the core dependencies again, however we know the answer to this mystery: the griffon-gradle-plugin takes care of adding the default core dependencies for you. Take note that the griffon configuration now marks includeGroovyDependencies with true. This allows the build to resolve additional core dependencies that should be included when dealing with Groovy, as witnessed by the following dependency graphs

We have griffon-groovy, griffon-javafx-groovy added to the mix. There are updated dependencies for compileOnly and testCompileOnly too

Here we can see that both jipsy and gipsy are included. They are required by the compile-time metadata generation process to be successfully executed. Alright, lets' get started with the code, shall we? We'll follow the same order as in the previous entry, this means we'll cover griffon-app/conf/Config.groovy first

Of the many features you find in Groovy perhaps the one that results in a head-scratching moment followed by "Eureka!" is Groovy's DSL capabilities. Here we can appreciate something that looks like a JSON payload but in reality is plan Groovy code. This is a Groovy script that can be internally converted to a set of properties. The Griffon runtime supports this format besides the plain Java and properties files; more options for you to pick the one that suits you best. We'll look at src/main/java/org/example/Launcher.groovy next

Looks like the only benefit we get here is the absence of semicolons and the omission of the public keyword, as everything in Groovy is public by default if no visibility modifier is defined. Moving on to griffon-app/models/org/example/SampleModel.groovy we see the following

As you can appreciate there are 2 JavaFX properties and nothing more. Wait a second, in the Java version we had to define properties in a verbose manner, what's going on here? Remember I said the the Groovy compiler is aware of well-known Java conventions? It typically generates getters/setters for properties. But the Groovy compiler is not aware of JavaFX conventions. This is where the AST transformations kick in. The @FXObservable annotation functions as a marker for the compiler to find a suitable component that can generate the required code. Have a look at the compiled code of this class

Ah, the secret has been deveiled. We can verify that the SampleModel class has the right information. More over, notice that it's super class has been changed too. That's right, even if you do not specify a super class Griffon artifacts will get the base one. This saves you typing but still lets artifacts be feature complete. IDEs should be able to give you code completion hints because the additions are made at the byte code level.

The next artifact we'll look at is the Controller, located at griffon-app/controllers/org/example/SampleController.groovy

A simplified version of the previous controller for sure. Here we can appreciate the essence of the sayHello action as there's little to no cruft at all. This action will still be automatically executed off the UI thread, like in the Java version, this is why updating the model has to happen inside the UI thread. Notice that the Groovy closure is very similar to the lambda expression we saw before, however property access makes it even terser. That's right, what appears to be a field access is in fact a method invocation under the covers, so that the JavaFX binding will be updated as we expect.

Next in line is the SampleService class located at griffon-app/services/org/example/SampleService.groovy

Less verbosity than before, wouldn't you agree? The code is 100% equivalent to the Java version but results in a much easier read. Both message files we saw before stay the same, here reproduced for completeness sake. The files are located at griffon-app/i18n/messages.properties and griffon-app/i18n/messages_es.properties.

The View is perhaps the place where we'll see most of the change. There are a few options for writing a JavaFX view in Griffon when Groovy is involved

  • the Java way. Build up using the JavaFX API.
  • the FXML way. Same as the last example.
  • the GroovyFX way. You may use a DSL for writing the view instead of FXML.
  • the hybrid way. Combine both FXML and GroovyFX for the ultimate experience.

In this example I've chosen to go with option #3 as it keeps the code neatly packed in a single file: griffon-app/views/org/example/SampleView.groovy

The GroovyFX DSL closely resembles the structure found in the FXML, but notice that the input and output components have their text property bound to their respective model properties. The button also uses a convention to configure itself via the controller action. Once you know the conventions writing code in this way is a snap.

You can run the application now. Execute the following command in a command prompt (or click the run action on your IDE)

$ gradle run

A familiar window will pop up after a few seconds. Great! From the previous example we know that changing the locale using a program argument will result in no change in the UI. We must inform the application that the locale must change. In the previous example we accomplished this task by leveraging an event handler. We'll use the same feature here. The first class we'll visit is src/main/java/org/example/ApplicationEventHandler.groovy

Now we configure the event handler using a Module, in src/main/java/org/example/ApplicationModule.groovy

Now that we have all things wired up we can again invoke the run command with the ES locale as argument

$ gradle -Plocale=es run

The window pops up again. And now the Spanish locale is in effect as expected. You may run this application using Maven too

$ mvn compile exec:java
$ mvn compile jfx:run

And there you have it. Overall the code between the Java and Groovy versions looks very similar. We expect to see a reduction of lines when using Groovy because the language is more concise and less verbose than Java. The additions of DSL capabilities, compiler extensions via AST transformations and the GDK makes it for a more pleasant development experience if you ask me.

Allow me to remind you that the Griffon team welcomes any feedback you may have regarding the state of the latest 2.0.0.BETA3 release. We're now in bugfix mode only, getting ready for 2.0.0.Final to come out very soon. So let us know what you think, drop us a line at the mailing lists, report a bug in our tracker, send us a pull request, tweet us at @theaviary.

Keep on Groovying!

PS: all code shown in this post can be found at https://gist.github.com/aalmiray/007c32f01e3b17230278

Andres Almiray

About Andres Almiray

Andres is a Java/Groovy developer and a Java Champion with more than 20 years of experience in software design and development. He has been involved in web and desktop application development since the early days of Java. Andres is a true believer in open source and has participated on popular projects like Groovy, Griffon, and DbUnit, as well as starting his own projects (Json-lib, EZMorph, GraphicsBuilder, JideBuilder). Founding member of the Griffon framework and Hackergarten community event. https://ch.linkedin.com/in/aalmiray

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »