Binding and Validation JSR295

    Preamble

    At leisure, I decided to parse the binding and validation in Java Beans Binding (JSR 295). The implementation offered by JSR 295 seemed to me simpler and more convenient than the similar functionality provided by JGoodies.

    Below I will consider two small examples of control bindings and an example of creating and using a validator.

    Binding a text field (JTextField)

    We define a simple class with the properties of which the elements of the form will be associated.

    class MyBean extends AbstractBean {
        private String strProperty = "";
        //
        // Конструкторы, геттеры и сеттеры здесь.
        //
    }


    The process of binding text fields is quite simple and practically does not need comments. The binding of two properties of different elements is carried out by creating an object of the AutoBinding class. This class synchronizes the properties of objects, guided by one of three strategies:

    1. READ_ONCE - synchronization is carried out only once, during the binding of the fields of objects.

    2. READ - the target is synchronized with the source.

    3. READ_WRITE - synchronization of objects with each other.

    The process of creating AutoBinding class objects can be simplified by using the Bindings class factory

    // ...где-то в глубинах кода...
    MyBean modelBean = new MyBean();
    // ...
    JTextField textField = new JTextField();
    // ...
    Bindings.createAutoBinding(READ_WRITE,
        modelBean, BeanProperty.create("strProperty"),
        textField, BeanProperty.create("text")).bind();
    


    . Everything is clear.
    Combining boxing (JComboBox)

    Combining boxing is carried out in two stages. First, the combo box is associated with a list of possible values, after which the selectedItem property is associated with the corresponding property of the target class.

    Define a simple class representing an element of the combobox list of values

    class ComboBoxVal {
        private int id = 0;
        private String text = "";
        //
        // Конструкторы, геттеры и сеттеры здесь.
        //   
    }


    Add a field to the MyBean class with which the selectedItem property of the combobox

    class MyBean extends AbstractBean {
        private String stringProperty = "Hello!";
        private ComboBoxVal comboProperty = 
            new ComboBoxVal(0, "Item0");
    // ...


    will be associated. Create a list of combobox values.

    // ...где-то в глубинах кода... 
    private List comboBoxData = new ArrayList(); 
    // ... 
    for (int i = 0; i < 10; i++) 
        comboBoxData.add(
            new ComboBoxVal(i, "Item" + i));
    


    Binding of complex Swing components is supported by the factory of SwingBindings classes. We will connect the combobox with the list of values. It

    JComboBox comboBox = new JComboBox();
    // ...
    SwingBindings.createJComboBoxBinding(
        READ, comboBoxData, comboBox).bind();
    


    remains to associate the selectedItem property of the combobox with the corresponding property of the target class.

    Bindings.createAutoBinding(READ_WRITE,
        comboBox, 
        BeanProperty.create("selectedItem"),
        modelBean, 
        BeanProperty.create("comboProperty")).bind();
    


    Validator creation

    As an example, we will implement a simple validator for the textField element considered above. Our validator will perform two checks - for nonemptiness and for the maximum number of characters.

    All validators must inherit from the parameterized Validator class, where T is the data type with which the work will be performed.

    class StringValidator extends Validator {
        private int maxStrLength = 10;
        // ...
        // Конструкторы, геттеры и сеттеры здесь.
        // ...
        public Result validate(String value) {
            if (value == null || value.length() == 0)
                return new StringEmptyResult();
            if (value.length() > maxStrLength)
                return new StringTooLong();
            return null;
        }
        public static class StringEmptyResult 
        extends Result {
            public StringEmptyResult() {
                super(0, "Str empty msg");
            }
        }
        public static class StringTooLong 
        extends Result {
            public StringTooLong() {
                super(1, "Str too long msg");
            }
        }
    }


    Validation is done by the validate function. In case the value has passed validation, null should be returned. Otherwise, you should return an object of the Result class containing a description of the problem and an error code.

    Using the validator

    In order to use the validator, you need to slightly modify the code that performs the binding. It

    //...где-то в глубинах кода...
    private Binding textBinding;
    // ...
    textBinding = Bindings.createAutoBinding(
        READ_WRITE,
        modelBean, BeanProperty.create("strProperty"),
        textField, BeanProperty.create("text"));
    textBinding.setValidator(validator);
    textBinding.bind();
    


    remains only to respond to the validation events

    textBinding.addBindingListener(
        new BindingListener(){
            public void syncFailed(Binding binding, 
            Binding.SyncFailure failure) {
                // Реакция на ошибку валидации.
            }
            public void synced(Binding binding) {
                // Реакция на успешную валидацию. 
            }
    // ...


    End.

    Also popular now: