On Mon, 12 Jul 2021 22:27:12 GMT, Kevin Rushforth <[email protected]> wrote:
>> The following unit test demonstrated the *current* behavior, though maybe
>> it's not the desired one:
>>
>>
>> import static org.junit.Assert.*;
>>
>> import javafx.beans.property.IntegerProperty;
>> import javafx.beans.property.SimpleIntegerProperty;
>>
>> import org.junit.Before;
>> import org.junit.Test;
>>
>> public class BindingsTest {
>>
>> private IntegerProperty property1, property2, property3;
>>
>> @Before
>> public void setup() {
>> property1 = new SimpleIntegerProperty(1);
>> property2 = new SimpleIntegerProperty(2);
>> property3 = new SimpleIntegerProperty(3);
>> }
>>
>> @Test
>> public void testBidiAndThenUni() {
>> property1.bindBidirectional(property2);
>> assertEquals(2, property1.get());
>> assertEquals(2, property2.get());
>> property1.bind(property3);
>> assertEquals(3, property1.get());
>> assertEquals(3, property2.get());
>> assertEquals(3, property3.get());
>> }
>>
>> @Test(expected = RuntimeException.class)
>> public void setProperty1() {
>> property1.bindBidirectional(property2);
>> property1.bind(property3);
>>
>> property1.set(4);
>> }
>>
>> @Test
>> public void setProperty2() {
>> property1.bindBidirectional(property2);
>> property1.bind(property3);
>>
>> // ignores exception (but still prints stack trace) at
>> //
>> com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:181)
>> property2.set(5);
>> assertEquals(3, property1.get());
>> assertEquals(3, property2.get()); // "Bidirectional binding
>> failed, setting to the previous value"
>> assertEquals(3, property3.get());
>> }
>>
>> @Test
>> public void setProperty3() {
>> property1.bindBidirectional(property2);
>> property1.bind(property3);
>>
>> property3.set(6);
>> assertEquals(6, property1.get());
>> assertEquals(6, property2.get());
>> assertEquals(6, property3.get());
>> }
>>
>> @Test(expected = RuntimeException.class)
>> public void testUniAndThenBidiOnBound() {
>> property1.bind(property3);
>> property1.bindBidirectional(property2);
>> }
>>
>> @Test
>> public void testUniAndThenBidiOnUnbound() {
>> property1.bind(property3);
>> property2.bindBidirectional(property1);
>>
>> assertEquals(3, property1.get());
>> assertEquals(3, property2.get());
>> assertEquals(3, property3.get());
>> }
>> }
>>
>>
>> My observations:
>>
>> * `setProperty2()` is weird in that it throws an exception internally which
>> is ignored by the JVM, and then reverts the change to the unidirectionally
>> unbound property when it finds out that its counterpart can't be changed. It
>> makes sense logically, but I don't see a valid use case for this.
>> * `setProperty3()` behaves as I expect it to, but this is effectively 2
>> chained unidirectional binds: `property3` changes `property1` which changes
>> `property2`. This is the same as `testUniAndThenBidiOnUnbound()`.
>>
>> It would make sense to disallow this mixing of bindings on grounds that this
>> is probably not what the developer wants to do. If we opt to let them do it
>> but write that it should not be done, we could emit a warning. I'm leaning
>> towards to fail-fast approach.
>
> I also like documenting it as illegal, but am hesitant to make any
> implementation change in this area for JavaFX 17 during rampdown. So I would
> recommend documenting as illegal, but not adding the `@throws` to the docs.
> We could still say that an exception might be thrown or could say something
> like "results are undefined". Then in JavaFX 18, we can add the `@throws` and
> change the implementation to fail fast.
Fine with me.
I didn't look at the current tests, but if it helps, we can add the one I wrote.
-------------
PR: https://git.openjdk.java.net/jfx/pull/533