Question

I am attempting to use JGoodies Binding 2.9.1 to bind the enabled property of a JTextField to an enum property. I want this to be a one-way operation: when the property changes, I want the JTextField to become enabled or disabled, but I never want to go the other way and set the enum property based on the enabled value.

Although I think I set up everything properly, I am getting a PropertyAccessException: Failed to set an adapted Java Bean property.

My model is a standard Java Bean with property change events:

public static String MY_PROPERTY = "myProperty";
private MyEnum myProperty;

public MyEnum getMyProperty() { return myProperty; }

public void setMyProperty(final MyEnum newValue) {
    final MyEnum oldValue = myProperty;
    if (newValue == oldValue) { return; }
    myProperty = newValue;
    changeSupport.firePropertyChange(MY_PROPERTY, oldValue, newValue);
}

In my view I have a one-way converter that will return true when the bound value matches the provided value:

private final class EnumMatchToEnabledConverter implements BindingConverter<MyEnum, Boolean> {
    private MyEnum match;

    public EnumMatchToEnabledConverter (MyEnum match) {
        this.match = match;
    }

    @Override
    public Boolean targetValue(MyEnum source) {
        return (source == match);
    }

    @Override
    public MyEnum sourceValue(Boolean target) {
        // this wouldn't make sense
        throw new UnsupportedOperationException();
    }
}

Then I set up the binding:

PresentationModel<MyModel> pm = new PresentationModel<MyModel>(model);
Bindings.bind(
    myTextField, "enabled", new ConverterValueModel(
        pm.getModel(MyModel.MY_PROPERTY),
        new EnumMatchToEnabledConverter(MyEnum.MyValue)));

To my surprise, EnumMatchToEnabledConverter's sourceValue() method gets called, and because it raises an UnsupportedOperationException I get a PropertyAccessException from the binding.

I also tried explicitly telling the binding not to use the setter, but I still got the same behavior:

Bindings.bind(
    myTextField, "enabled", new ConverterValueModel(
        pm.getModel(MyModel.MY_PROPERTY, "getMyProperty", null), // null setter!
        new EnumMatchToEnabledConverter(MyEnum.MyValue)));

Where am I going wrong?

Was it helpful?

Solution

I found a workaround. It's ugly, but it works.

I wrap my ConverterValueModel with a BufferedValueModel whose ValueModel trigger never triggers.

Bindings.bind(
    myTextField,
    "enabled",
    new BufferedValueModel(
        new ConverterValueModel(
            pm.getModel(MyModel.MY_PROPERTY),
            new EnumMatchToEnabledConverter(MyEnum.MyValue)),
        new AbstractValueModel() {
            @Override public Object getValue() { return null; }
            @Override public void setValue(Object o) {}
        }));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top