<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p><br>
</p>
<div class="moz-cite-prefix">On 26/10/2025 13:56, Nir Lisker wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CA+0ynh9NHeF=-7tLyGjtj6BbK-VVe8UtoR3deKGkxjTf29d=XQ@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr"><br>
<div style="padding:0px 2px">Some observations:</div>
<div style="padding:0px 2px">Bindings returns a Binding rather
than an ObservableValue and also has primitive specialization
versions that have their unique methods (add, subtract...).
These methods, however, can be replicated with fluent bindings
and they also have the "known" subtle GC issue for the
intermediary values.</div>
</div>
</blockquote>
<p>The subtle GC is rather easy to hit I saw.</p>
<p>I often write code that has very little assignments, and operates
by using listeners/subscriptions, and this code is already
incorrect:</p>
<div style="background-color:#ffffff;padding:0px 0px 0px 2px;">
<div
style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p
style="margin:0;"><span style="color:#000000;"> // All local variables:
ObjectProperty<LocalDate> departureDate = </span><span
style="color:#0000a0;font-weight:bold;">new</span><span
style="color:#000000;"> SimpleObjectProperty<>();</span></p><p
style="margin:0;"><span style="color:#000000;"> ObjectProperty<LocalDate> returnDate = </span><span
style="color:#0000a0;font-weight:bold;">new</span><span
style="color:#000000;"> SimpleObjectProperty<>();</span></p><p
style="margin:0;"><span style="color:#000000;"> ObservableValue<Boolean> returnTrip = tripType.map(v -> v.equals(</span><span
style="color:#2a00ff;">"Return"</span><span style="color:#000000;">));</span></p><p
style="margin:0;"><span style="color:#000000;"> BooleanBinding datesValid = Bindings.</span><span
style="color:#000000;font-style:italic;">createBooleanBinding</span><span
style="color:#000000;">(() -> {</span></p><p style="margin:0;"><span
style="color:#000000;"> </span><span
style="color:#7f0055;font-weight:bold;">return</span><span
style="color:#000000;"> returnTrip.getValue() && departureDate.get() != </span><span
style="color:#0000a0;font-weight:bold;">null</span><span
style="color:#000000;"> && returnDate.get() != </span><span
style="color:#0000a0;font-weight:bold;">null</span><span
style="color:#000000;"> ? departureDate.get().compareTo(returnDate.get()) < 0 : </span><span
style="color:#0000a0;font-weight:bold;">false</span><span
style="color:#000000;">;</span></p><p style="margin:0;"><span
style="color:#000000;"> }, departureDate, returnDate, returnTrip);</span></p><p
style="margin:0;">
... create some UI where dp is a DatePicker ...
</p><div style="background-color:#ffffff;padding:0px 0px 0px 2px;"><div
style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p
style="margin:0;"><span style="color:#000000;"> datesValid.subscribe(valid -> {</span></p><span
style="color:#000000;"> </span><span
style="color:#0000a0;font-weight:bold;">if</span><span
style="color:#000000;"> (valid) {</span><p style="margin:0;"><span
style="color:#000000;"> dp.getStyleClass().remove(</span><span
style="color:#2a00ff;">"invalid"</span><span
style="color:#000000;">);</span></p><p style="margin:0;"><span
style="color:#000000;"> }</span></p><p style="margin:0;"><span
style="color:#000000;"> </span><span
style="color:#0000a0;font-weight:bold;">else</span><span
style="color:#000000;"> {</span></p><p style="margin:0;"><span
style="color:#000000;"> dp.getStyleClass().add(</span><span
style="color:#2a00ff;">"invalid"</span><span
style="color:#000000;">);</span></p><p style="margin:0;"><span
style="color:#000000;"> }</span></p><p style="margin:0;"><span
style="color:#000000;"> });</span></p></div></div></div>
</div>
<p></p>
<p>It works perfectly, even for a longer period, until I added a few
`System.gc()` calls, and the binding just poofs despite having a
subscription on it.</p>
<p>It's really disingenious, nothing is mentioned in the docs that
the above is incorrect usage:</p>
<p>- Not in Bingdings#createBooleanBinding<br>
- Not in BooleanBinding<br>
- Not in Binding</p>
<p>The only thing mentioned is that you can use `unbind` to stop
observing (or just wait for a random GC to occur obviously...)<br>
<br>
--John<br>
</p>
<p><br>
</p>
<blockquote type="cite"
cite="mid:CA+0ynh9NHeF=-7tLyGjtj6BbK-VVe8UtoR3deKGkxjTf29d=XQ@mail.gmail.com">
<div dir="ltr">
<div style="padding:0px 2px"><br>
</div>
<div style="padding:0px 2px">The proposal is more ergonomic
with its fluency for a couple of values, but I'm not sure it
solves enough problems that the current mechanism can't.</div>
</div>
<br>
<div class="gmail_quote gmail_quote_container">
<div dir="ltr" class="gmail_attr">On Sun, Oct 26, 2025 at
11:59 AM John Hendrikx <<a
href="mailto:john.hendrikx@gmail.com" moz-do-not-send="true"
class="moz-txt-link-freetext">john.hendrikx@gmail.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote"
style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">JEP:
<a
href="https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a"
rel="noreferrer" target="_blank" moz-do-not-send="true"
class="moz-txt-link-freetext">https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a</a><br>
<br>
Hi everyone,<br>
<br>
I'd like to propose an extension to the fluent bindings API on<br>
ObservableValue (map, flatMap, orElse) which were introduced
in JavaFX<br>
19 over 3 years ago.<br>
<br>
The API currently is very powerful when dealing with a single<br>
observable, but lacks support when dealing with multiple
observables. <br>
For example, let's say you want to compute a width/height
ratio. You<br>
could write this:<br>
<br>
ObservableValue<Double> ratio = width.map(w -> w
/ height.get());<br>
<br>
... but you'll quickly find that such an observable will not
update<br>
itself when height changes, only when width changes.<br>
<br>
The go-to solution for this is currently:<br>
<br>
DoubleBinding ratio = new DoubleBinding() {<br>
{ bind(width, height); }<br>
<br>
protected double computeValue() { return width.get() /<br>
height.get(); }<br>
}<br>
<br>
My proposal would extend ObservableValue with a new `with`
method that<br>
returns an intermediate stage that can be easily converted
back to an<br>
ObservableValue:<br>
<br>
ObservableValue<Double> ratio =
width.with(height).map((w, h) -> w /<br>
h); // yields a ratio that updates whenever w or h changes<br>
<br>
Or for example:<br>
<br>
ObservableValue<Point> point =
x.with(y).map(Point::new); //<br>
yields a Point that updates whenever x or y changes<br>
<br>
The intermediate stage would not be an observable value
itself. This<br>
limits the API surface, and makes this proposal fairly
lightweight and<br>
much easier to implement.<br>
<br>
Please see the JEP for the full proposal. I look forward to
your feedback!<br>
<br>
--John<br>
<br>
<br>
</blockquote>
</div>
</blockquote>
</body>
</html>