Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Platform » Eclipse DataBinding: updateTargetToModel() triggers validator twice.
Eclipse DataBinding: updateTargetToModel() triggers validator twice. [message #1772640] Wed, 13 September 2017 13:13
Ralf Grossklaus is currently offline Ralf GrossklausFriend
Messages: 3
Registered: October 2015
Junior Member
Hi,

i discovered a strange behaviour within the Eclipse Data Binding component and would like to ask, if this is how it is meant to be.

In my application, there are some circumstances, where I have to trigger the update of observables manually by calling "updateTargetToModel()" on the Binding object, since the content of a text field may have changed but the corresponding SWT observable have not triggered the update at that point (update is done at the Focus-Out event). There is also an after-get validator, that checks if the value of the text filed is already contained in a set of strings at the data model level. Entering a new value in the text field will update that set of strings, so that value can only be entered once. The Status of the validator will not only prevent the update of the data model (on errors), it's message will also be display in the UI in order to give the user a hint that he entered an invalid value.

The problem is, that the call of "updateTargetToModel()" triggers the validator twice. The first time in ValueBinding at line 165, when the binding calls "getValue()" on the outdated observable (during an update of this observable). At this time, the validator returns OK (since the new value is not yet written to the data model). The second time, the validator is called is at ValueBinding line 169. This time, the validator will fail (as the model does already contain the new value) and the ValidationStatus of the ValueBinding will contain the error.

Does anyone have an idea, if this is really the desired behaviour of "updateTargetToModel()"?

Regards, Ralf

PS: The following code snippet demonstrates what i mean..

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.junit.Test;

public class Main {

	private static class TestRealm extends Realm {
		@Override
		public boolean isCurrent() {
			return true;
		}
	}
	
	private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
	
	private String model = "";
	
	private String target = "";

	public String getModel() {
		return model;
	}

	public void setModel(String model) {
		changeSupport.firePropertyChange("model", this.model, this.model = model);
	}

	public String getTarget() {
		return target;
	}

	public void setTarget(String target) {
		changeSupport.firePropertyChange("target", this.target, this.target = target);
	}
	
	public void setTargetSilent(String target) {
		this.target = target;
	}
	
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.addPropertyChangeListener(listener);
		
	}
	
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.removePropertyChangeListener(listener);
	}
	
	@Test
	@SuppressWarnings("unchecked")
	public void test() {
		final Realm realm = new TestRealm();
		final Main bean = new Main();
		final IObservableValue<String> modelValue = BeanProperties.value("model").observe(realm, bean);
		final IObservableValue<String> targetValue = BeanProperties.value("target").observe(realm, bean);
		final UpdateValueStrategy targetToModel = new UpdateValueStrategy();
		final DataBindingContext context = new DataBindingContext(realm);
		final Binding binding = context.bindValue(targetValue, modelValue, targetToModel, null);
		// Now register validator
		targetToModel.setAfterGetValidator(new IValidator() {
			@Override
			public IStatus validate(Object value) {
				String existingName = bean.getModel();
				if (existingName.equals(value)) {
					System.out.println("Validate Error: " + value);
					return new Status(IStatus.ERROR, "com.vector.databindingtest", "Invalid Value");
				}
				System.out.println("Validate Ok: " + value);
				return Status.OK_STATUS;
			}
		});
		assertEquals("", targetValue.getValue());
		assertEquals("", modelValue.getValue());

		// Everything is fine here
		bean.setTarget("Test");
		assertEquals("Test", bean.getModel());
		
		// Here, the target is changed without the observable beeing updated  
		bean.setTargetSilent("Anything");
		assertEquals("Test", bean.getModel());

		// calling "updateTargetToModel()" triggers the validator twice. 
		// This is a problem, when the binding contains a validator, whose state depends on the model value 
		// This is because the model value has changed with the first update.
		binding.updateTargetToModel();
		assertEquals("Anything", bean.getModel()); // model was updated successfully
		assertTrue(((IStatus)binding.getValidationStatus().getValue()).isOK()); // However, this will fail
	}
}

Previous Topic:Xbootclasspath is no longer a supported option on JRE 9
Next Topic:Eclipse Win/Mac Play Video
Goto Forum:
  


Current Time: Tue Apr 16 18:40:48 GMT 2024

Powered by FUDForum. Page generated in 0.40826 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top