JavaBeanPropertyAdapter

Michael Heinrichs michael.heinrichs at oracle.com
Mon Dec 19 01:15:50 PST 2011


Hi Tom,

this works only for bidirectional bindings. If you do a unidirectional bind between a Property p and an ObservableValue v, then v may very well be read only.

I was thinking about such a sync-back functionality for bidirectional bindings. But actually I am not sure, what we want to do in such cases. Do we want to set a default value, throw an exception, try to sync back or maybe do something else? Is there a one-size-fits-all solution possible? Maybe best would be a solution, that allows all kinds of behaviors easily, but I have no idea how to achieve that.

One possible solution would be to add a type-parameter that can be passed to the createProperty() method. This would allow to configure the behavior in case of an error. But I do not like this solution. While maybe technically viable, it does not feel right. So far the class is very easy to use:  "Just pass in a bean and the name of a property and the runtime will do its best to make it behave like a JavaFX property". But if we add a type parameter, a developer suddenly has to consider something which is actually just a rare corner case that only pops up, if the application logic is flawed anyway.

Another idea just came to my mind. What if the class we return, let's call it JavaBeanProperty, is an extension of Property, which adds functionality to deal with such cases? That way createProperty() would not be spoiled and only expect the obvious parameters. But if you need to change the default behavior, you can take a look at the documentation of JavaBeanProperty. The downside would be, that is probably not obvious to find the functionality the first time you look for it. JavaBeanPropertyAdapter.createProperty() would return a JavaBeanProperty, if you do not know that JavaBeanProperty is a Property, this can easily be overlooked.

- Michael



On 17.12.2011, at 10:42, Tom Eugelink wrote:

> 
>>> Bindings for Java Bean properties will be slightly different than our usual bindings: they will be eager and they may become out-of-sync. Let's say we have a Java Bean Property p, that is bound to an ObservableValue v. Internally we hook a listener to v and propagate all changes to p by calling its setter (that is why it will be eager). If now p does not accept the value from v, p and v will be out-of-sync. Especially the last point bothers my, but I guess there is no way to ensure synchronization.
>> Right, we're just sort of hosed there.
> 
> How about the if-set-then-sync-back approach? Which basically means that every time after calling the setter, you'll do an equals on the result and if it it is not equal a sync-back is started.
> 
> sync A->B:
>    try
>    {
>        A.setter(value)
>    }
>    finally
>    {
>        if (A.getter.equals( value ) == false) // TODO: also take nulls in comparison
>        {
>            sync B->A
>        }
>    }
> 
> If this starts to loop then something is wrong in the user's code, because it has attempted to reach a state that should (can) not exist. N.B. this approach is different from the current binding logic of JavaFX, where the JavaFX side always accepts the value (if I remember correctly Richard?)
> 
> 
> 
> 
>> 
>> Very few Java classes use VetoableChangeListeners. However, I think that is OK since the common usage here will be to either do a unidirectional binding from a JavaFX property to a POJO (for example, Label.text is bound to Customer.name), or a bidirectional binding between the two. So this seems fine.
> 
> The approach above also takes care of this scenario, via the finally construct.
> 
> Tom
> 



More information about the openjfx-dev mailing list