Building a better world one commit at a time

Creating aggregate JavaFX bindings

The standard JavaFX API provides a class named Bindings that can be used to create all kinds of bindings your application may need. Methods in this class can be used to translate any Observable, ObservableValue, Binding, Expression, and/or Property into another Binding, regardless of their original type. Here’s for example how you could translate a StringProperty into an IntegerBinding, by exposing the length of the contained String:

While quick and to the point we’re forced to read the value directly from the inputs (in this case sourceProperty) instead of receiving the value as is. Here’s another typical scenario: calculate an aggregate binding based on a list of observable values. Say you have an observable class that exposes a BooleaProperty to indicate its valid state; perhaps this class looks like the following one

There are a couple of issues with this code. First we’re forced to extract the values again; second we’ve got lucky as the resulting type is a boolean, this means we don’t have to worry about the case when the list is empty as the resulting BooleanBinding will contain a false value. But what if we’re aggregating over type that’s not a boolean and we need a non-null value? How do we specify such default value? This is where Griffon’s JavaFX Binding support comes in.

We can rewrite the first sample code in a more concise way using Griffon’s MappingBindings utility class:

We can now make use of the actual value, which in this case is supplied to a Function, masked as a method reference. You'll find other variants of this mapping method supporting all basic binding types. What's even better if that there are overloaded versions that take an observable Function, thus you can update the calculating function at any time you so desire, for example

Moving on to the aggregate binding, there's another utility class named ReducingBindings that offers map/reduce capabilities on an observable collection of values (yes, this includes observable variants of List, Set, and Map).

However if you recall the first version of the code relied on the stream capabilities added in Java 8. Wouldn't it be great to use those same capabilities in an observable manner? If you think that's a good thing to have then I have news for you: Griffon exposes an ObservableStream class that offers the same contract as a Stream, this being said it is not a subtype of Stream.

One more thing, all these aggregate bindings will trigger an update whenever an element is added or removed from the collection but not when the internal state of an element is updated, that is, if an ObservableBean changes valid state from false to true the aggregate will fail to see the update. This is clearly not what we want. We need a way to listen to internal changes within elements, with this use case in mind Griffon's JavaFX support exposes ElementObservableList, an implementation of ObservableList that's aware of internal element updates. You simply must implement a marker interface, ElementObservableList.ObservableValueContainer, or provide a custom strategy that implements ElementObservableList.ObservableValueExtractor, for example

You may use these classes with any JavaFX application, you're not required to use the full features of the Griffon framework to do so, you only have to configure the griffon-javafx artifact in your build, for example

2 comments

Hi Andres. I’m doing my thesis and I needed some advice. I want to develop a desktop application and my fist choice was Griffon. But in a thesis from last year the following was said:

“One of the biggest flaws of Griffon, is, that it is primarily targeted at the Swing UI toolkit. It can however be used with JavaFX, considering that features are not as integrated as with swing. It is a problem for the controls community, as they want to use JavaFX as the main UI toolkit. Besides this flaw, Griffon enforces the use of the model, view, controller pattern. It follows the Swing application framework, which also defines the application’s life cycle.”

My question is, this is a quote from 2017, can you tell me if this “problem” still persists?

Do you have a link to the full thesis from where the comment was lifted? Would like to read it in context.

Setting the record straight: Griffon 1.x was created with Swing support in mind, JavaFX support was added later as a bolt-on. Griffon 2.x was redesigned from scratch to better accommodate the differences between different UI toolkits, there’re no Swing abstractions leaking into JavaFX and viceversa, also you may use Java, Groovy, Kotlin, either in isolation or in conjuction. My personal preference when writing Griffon applications is to follow the PMVC design pattern however Griffon does not enforce a explicit pattern, you can combine artifacts in any way you deem fit, as shown at http://griffon-framework.org/tutorials/5_mvc_patterns.html; you can even pick a totally different pattern, bearing in mind that additional configuration may be required.