> What if I like my core business logic classes that do not support just GUI's but also processes to not have Observable properties?
Might be a good use-case for the
javafx.beans.property.adapter classes.
Or perhaps try an
MVVM model (yeah, I know that link is WPF not JavaFX, but hopefully you can get the gist of it - and you probably already know MVVM anyway...).
Some of the utilities in
DataFX may help you.
> I can certainly work around this and try to create observable wrappers around my non-observable classes, but it just feels awful messy. If I have a singleton list of immutable Airport objects that I want to project into a TableView, I have to first make all the properties of Airport Observable, and then I have to wrap the Airport objects into an ObservableList. Or in the TableView, I have to create a ReadOnly wrapper.
From a naive point of view, it doesn't seem too tricky to me. Maybe post an example (in a new
thread here or on StackOverflow under the JavaFX tag) with the code which does this and it will be easier to see just how messy it is or what compromises are made or to suggest potential optimizations which might make it less messy.
> It almost feels like you are forced to make things mutable via Properties.
I don't think you are forced to. Certain things (such as setting up UI bindings) are definitely simpler if you have observable properties.
> but Swing just feels so much easier especially with JTable.
Sometimes what is familiar seems easier. (I have never written much Swing code, so it could indeed be easier with Swing...).
It is also possible that additional API could be added to the JavaFX core or a third party library which emulates or surpasses the ease-of-use provided by Swing in this regard.
There may also be tradeoffs between ease of use and flexible functionality which might not be readily apparent at first glance.
> what if I am fond of using Immutable Collections?
The standard collection type used throughout JavaFX is the mutable ObservableList - I don't think you have any option other than to use it.
I like immutable stuff too - it makes programs easier to reason about. It is especially useful when dealing with concurrency - though that is less of an issue in a system which is single threaded from an application developer standpoint (such as JavaFX). Still, even in single-threaded environments, having stuff immutable by default can make your life easier.
> if I don't drink the Observable/Binding framework KoolAid, am I not going to enjoy JavaFX until I adapt to them?
Perhaps not. Use of properties is pervasive to the core JavaFX API. Even if you don't use properties and bindings directly in your app code, you still need to code against the core API which does use such things all of the time. You can probably get away within your app code with plain
java objects and immutable ones at that, but you may need to use beans adapters on your app objects and listeners on the JavaFX API properties to allow reasonable interaction between your app code and the JavaFX API.
----
In the end, the observable/binding framework of JavaFX is programming by
side-effect, which has inherent risks in difficulty of understanding and reasoning about program state and the potential scope and impact of changes to property values - especially in larger programs. Because there is high potential for side-effects, it is important for the app developer to understand the impact of a change. For example, if you change a
string property in a concurrent task and that string property is bound to label's text, that change to the string property can trigger a change to the label text which violates a JavaFX threading rule of not updating properties of the active scene graph off the JavaFX application thread. In practice, I have found that the observable/binding model seems to work well and appreciate its implementation in JavaFX, but opinions on that may vary. For small programs the side-effect based model works fine...
Even though it seems simple, be careful with things like laying out controls based upon binding calculations beyond very simple layout rules. The preferred method for layout in applications is to use built-in layout managers and set layout constraints on the layout managers and their child nodes. If this preferred method does not get you the customization you need, instead of using lots of bindings, subclass region and override layoutChildren() and perform layout there (that technique is used extensively in the internal JavaFX implementation - though it is not documented in tutorials for developers that I know of).
Use of immutable data is quite prevalent in functional programming techniques. Functions work best and are easier to reason about without side-effects. One of the things which can make functional programming great is it's prevalent lack of mutable state, for example using a map function from one immutable list to another rather than a for loop with a mutable counter that modifies values inside a list. On the other hand, GUIs are often built on changing data - so there is a bit of an impedance mismatch, as typified in this question:
Clojure: how to architect desktop UI in which the question author posits creating an application which uses JavaFX for the UI technology (wrapped in Clojure) but relies as much as possible on immutable state within the application object model (and there are no good answers to that question).
----
One issue with JavaFX, is that it may not provide out-of-the-box the optimal level of functionality for its binding/observable setup. Perhaps take a look at
ReactFX, to see how the in-built setup can potentially be enhanced. Though if you don't like bindings/observables, you may not like ReactFX either...