Home » Eclipse Projects » JFace » [Databinding] MultiValidator in RAP Application
| |
Re: [Databinding] MultiValidator in RAP Application [message #489912 is a reply to message #489767] |
Tue, 06 October 2009 13:22 |
habakuk Messages: 32 Registered: October 2009 |
Member |
|
|
Thanks for your help Matthew. Well I'm already using a 2 stage binding. Because I use RAP with Eclipselink I have to rebind everything after saving data. (This is necessary because after doing a merge JPA returns a new instance of my data object). I think I'm creating the MultiValidator as late as possible. Is there a better way to create the MultiValidator, so that the data that get loaded from the database are not validated? (because I expect them to be valid anyway, it should be sufficient to validate only user entries). I attached my code, maybe there is room for improvement
Thank you
private void bindValues() {
if (bindingContext != null) {
bindingContext.dispose();
bindingContext = new DataBindingContext();
}
bindingContext.bindValue(new RadioGroupObservableValue(radioGroup),
BeansObservables.observeValue(dv, "typ_id"),
new UpdateValueStrategy().setConverter(new DVConverter()),
new UpdateValueStrategy().setConverter(new DVModel2TargetConverter()));
IObservableValue guiBeginnObservableValue = SWTObservables.observeSelection(beginn);
IObservableValue guiEndeObservableValue = SWTObservables.observeSelection(ende);
final IObservableValue middleStartObservableValue = new WritableValue(null, Date.class);
final IObservableValue middleEndObservableValue = new WritableValue(null, Date.class);
bindingContext.bindValue(guiBeginnObservableValue, middleStartObservableValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT), null);
bindingContext.bindValue(guiEndeObservableValue, middleEndObservableValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT), null);
IObservableValue modelBeginnObservableValue = BeansObservables.observeValue(dv, "beginn");
IObservableValue modelEndeObservableValue = BeansObservables.observeValue(dv, "ende");
PeriodValidator periodValidator = new PeriodValidator(middleStartObservableValue, middleEndObservableValue);
bindingContext.addValidationStatusProvider(periodValidator);
bindingContext.bindValue(periodValidator.observeValidatedValue(middleStartObservableValue), modelBeginnObservableValue, null, null);
bindingContext.bindValue(periodValidator.observeValidatedValue(middleEndObservableValue), modelEndeObservableValue, null, null);
}
class PeriodValidator extends MultiValidator {
IObservableValue beginn;
IObservableValue ende;
public PeriodValidator(IObservableValue beginn, IObservableValue ende) {
super();
this.beginn = beginn;
this.ende = ende;
}
@Override
protected IStatus validate() {
Date startDate = (Date) this.beginn.getValue();
Date endDate = (Date) this.ende.getValue();
System.out.println("PeriodValidator.validate(" + startDate + ", " + endDate + ")");
if (!startDate.before(endDate)) {
return ValidationStatus.error("Startdatum muss vor Endedatum sein");
}
return ValidationStatus.ok();
}
}
Matthew Hall wrote on Mon, 05 October 2009 15:54 | habakuk wrote:
> I'm writing a RAP based application that uses Eclipselink for
> persistence. I have lot of standard "web forms" that consists of some
> fields that are filled from the database. After pressing the obligatory
> save button, the data should be validated and sent to the database. I
> use the ON_REQUEST policy for the targetToModel UpdateStrategy, so that
> data only get written to the model when save is pressed. Because I have
> to validate a time periode (2 date values) I use pretty much the same
> code as proposed in the Javadoc of MultiValidator. It seems to work, but
> I noticed that the validator gets called too often. It gets called 3
> times when the data is loaded, and 2 times when the data is saved. No
> idea why.
Are you creating your MultiValidator before or after all its
dependencies are bound? It is better to create it afterward to minimize
the number of times it has to validate on startup.
> Is there a strategy to make MultValidator called only once
> when loading/saving. The problem is that my validation might take too
> much time, because it has to query the database. I cannot validate after
> every field is updated, I need to validate only after all values are
> loaded.
In this case I would suggest binding in two stages:
target <=> staging <=> model
The staging observables are basically just Writable<Value|List|Set|Map>
instances. Put the simple validators (the ones that don't have to talk
to the database) on the target <=> staging bindings (which should have a
POLICY_CONVERT update policy). The more involved validators should be
attached to the staging <=> model bindings.
The staging <=> model bindings can use the default POLICY_UPDATE update
policy. Now modify your MultiValidator to validate against the staging
observables instead of the target.
You will still have multiple database trips when the MultiValidator's
dependencies are each updated in turn however now you will only incur
those trips once when Ok/Save is clicked instead of on every change.
There was some work going on a while ago to implement asynchronous
validation with MultiValidator [1] and with bindings [2] but for some
reason the work stalled and we never finished it. Something to do with
IProgressMonitor integration I think. If you'd like to take a look into
those bugs and leave your comments maybe we can get those features
moving forward again.
Hope this helps,
Matthew
[1] https://bugs.eclipse.org/bugs/show_bug.cgi?id=237857
[2] https://bugs.eclipse.org/bugs/show_bug.cgi?id=233191
|
|
|
|
Goto Forum:
Current Time: Fri Apr 19 19:28:50 GMT 2024
Powered by FUDForum. Page generated in 0.03502 seconds
|