Data Binding
Introduction
The term data binding refers to the concept of process the entries of data from the user interface to the domain model in a dynamic form and more less automatic. Before we have seen how to use the system of data binding via AbstractView. In this chapter we can see this implemented.
Control Accessor
Writing a generic code for the Swing components is a complex task because it is necessary to know the type specific control for simple operations. For example to obtain the value contained in a control Swing different methods must be used if it is a JTexField or a JCheckBox. We found the same problem if we want to be notified of the changes in the values of the component. We add different a Listener depending on the type.
The interface ControlAccessor solves this problem, allowing you to write code that is independent to the type of the Swing. Component. Básically the idea is the same that is behind the interface PropertyEditor of the specification JavaBeans or in formidable BeanWrapper of Spring Framework.
ControlAccessor defines six methods to allow a basic access to any type of Swing component:
- setControlValue(Object value) actualize the value contained in the control.
- getControlValue() obtain the value contained in the control.
- addControlChangeListener(ControlChangeListener l) add a ControlChangeListener that is notified in the changes of the value of control.
- removeControlChangeListener(ControlChangeListener l) remove a ControlChangeListener added previously.
- setEnabled(boolean enabled) activate/desactivate the control.
- isEnabled() devuelve true return true if the control is active.
Control Accessor Factory
Because we want to operate on Swing components, which in principal, we do not know the type, we need a way to associate the component with it's specific ControlAccessor. This is the factory of ControlAcessors. The implementation by defect provides JDAL, ConfigurableControlAccessorFactory use a map to associate the ControlAccessor to the class of the component..
... ControlAccessor controlAccesor = controlAccessorFactory.getControlAccessor(control); if (controlAccessor != null) { controlAccessor.addControlChangeListener(this); controlAccessor.setControlValue(someValue); } ...
Binder
The Binder interface adds methods to ModelHolder which allows the data to be moves between the control of the user interface and the domain model:
- update(): Actualize the model with control data.
- refresh(): Actualize the control with model datal.
- getBindingResult() Return the result of the update() operation.
JDAL delegates the obtaining of the Binder appropriate to the factory BinderFactory which contains a FactoryMethod that asociates a Binder with the class of the Java component.
The interface PropertyBinder is a specialization of binder that permits associates control to a property of a model.
Finally the class CompositeBinder represents an aggregate of PropertyBinders that shares the same model.
Composite Binder
All the work of data binding is done by the CompositeBinder. Consists in an aggregate of Binders that, generally operates about the same model.
CompositeBinder provides the following methods related with the data binding:
- bind(String propertyPath, Object component, T model, boolean readOnly) Creates a binding between a property referenced by propertyPath in the model and the component.
- getBinder(StringPropertyPath Obtain the binder associated to a propertyPath
- getBindingResult() Obtain the result of the operation of binding (update()), a BindingResult of Spring Framework.
- getPropertyBinders() Obtain a collectión with all the binders that are contained.
- autobind() Perform automatic binding between the model and the view, following the convention of the same name.
- update() Actualize the model data.
- refresh() Actualize the view from model data.
Note: Here by view, we refer to the class that contains the Swing components. It is not necessary to implement the interface Viewi. Nor is it necessary to create getters and setters for the components.
You can use CompositeBinder independtly with your own components and without the necesity to use the Spring IoC container:
CompositeBinder<Object> binder = new CompositeBinder<Object>(model); binder.setBinderFactory(new ControlAccessorBinderFactory( ConfigurableControlAccessorFactory.getDefaultFactory()))); binder.autobind(view); binder.update(); BindingResult result = binder.getBindingResult();