diff options
author | Artur Signell <artur@vaadin.com> | 2016-08-31 16:17:50 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2016-08-31 17:11:44 +0300 |
commit | 814c29c1521a42f355cfc254fb8b00ae436b4956 (patch) | |
tree | b934305f718059ae6b55addae755c0fd54b5c098 /server | |
parent | 82806ef9b7f12c66e620a813c7987c0fbea723dc (diff) | |
download | vaadin-framework-814c29c1521a42f355cfc254fb8b00ae436b4956.tar.gz vaadin-framework-814c29c1521a42f355cfc254fb8b00ae436b4956.zip |
Implement Binder.saveIfValid and fix Binder.save to throw exception
Change-Id: I44498b4b34b2e9732b50abb14e8eb7be01314158
Diffstat (limited to 'server')
-rw-r--r-- | server/src/main/java/com/vaadin/data/Binder.java | 59 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/ValidationException.java | 53 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/BinderTest.java | 54 |
3 files changed, 157 insertions, 9 deletions
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 34027c1f77..094afd2bd8 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -738,18 +738,65 @@ public class Binder<BEAN> implements Serializable { } /** - * Saves changes from the bound fields to the edited bean. If any value - * fails validation, no values are saved and an {@code BindingException} is - * thrown. + * Saves changes from the bound fields to the given bean if all validators + * pass. + * <p> + * If any field binding validator fails, no values are saved and an + * exception is thrown. + * + * @see #saveIfValid(Object) + * @see #load(Object) + * @see #bind(Object) * * @param bean * the object to which to save the field values, not null - * @throws BindingException + * @throws ValidationException * if some of the bound field values fail to validate */ - public void save(BEAN bean) { + public void save(BEAN bean) throws ValidationException { + List<ValidationError<?>> errors = doSaveIfValid(bean); + if (!errors.isEmpty()) { + throw new ValidationException(errors); + } + } + + /** + * Saves changes from the bound fields to the given bean if all validators + * pass. + * <p> + * If any field binding validator fails, no values are saved and + * <code>false</code> is returned. + * + * @see #saveIfValid(Object) + * @see #load(Object) + * @see #bind(Object) + * + * @param bean + * the object to which to save the field values, not null + * @return {@code true} if there was no validation errors and the bean was + * updated, {@code false} otherwise + */ + public boolean saveIfValid(BEAN bean) { + return doSaveIfValid(bean).isEmpty(); + } + + /** + * Saves the field values into the given bean if all field level validators + * pass. + * + * @param bean + * the bean to save field values into + * @return a list of field validation errors + */ + private List<ValidationError<?>> doSaveIfValid(BEAN bean) { Objects.requireNonNull(bean, "bean cannot be null"); - bindings.forEach(binding -> binding.storeFieldValue(bean)); + // First run fields level validation + List<ValidationError<?>> errors = validate(); + // If no validation errors then update bean + if (errors.isEmpty()) { + bindings.forEach(binding -> binding.storeFieldValue(bean)); + } + return errors; } /** diff --git a/server/src/main/java/com/vaadin/data/ValidationException.java b/server/src/main/java/com/vaadin/data/ValidationException.java new file mode 100644 index 0000000000..41017a8393 --- /dev/null +++ b/server/src/main/java/com/vaadin/data/ValidationException.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.data; + +import java.util.Collections; +import java.util.List; + +/** + * Indicates validation errors in a {@link Binder} when save is requested. + * + * @see Binder#save(Object) + * + * @author Vaadin Ltd + * @since 8.0 + * + */ +public class ValidationException extends Exception { + + private final List<ValidationError<?>> errors; + + /** + * Constructs a new exception with validation {@code errors} list. + * + * @param errors + * validation errors list + */ + public ValidationException(List<ValidationError<?>> errors) { + super("Validation has failed for some fields"); + this.errors = Collections.unmodifiableList(errors); + } + + /** + * Returns the validation errors list which caused the exception. + * + * @return validation errors list + */ + public List<ValidationError<?>> getValidationError() { + return errors; + } +} diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index 331d4d30de..be408d6142 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -15,6 +15,7 @@ import org.junit.Test; import com.vaadin.data.Binder.Binding; import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.validator.NotEmptyValidator; import com.vaadin.server.AbstractErrorMessage; import com.vaadin.server.ErrorMessage; import com.vaadin.server.UserError; @@ -150,7 +151,7 @@ public class BinderTest { } @Test - public void save_unbound_noChanges() { + public void save_unbound_noChanges() throws ValidationException { Binder<Person> binder = new Binder<>(); Person person = new Person(); @@ -163,7 +164,7 @@ public class BinderTest { } @Test - public void save_bound_beanIsUpdated() { + public void save_bound_beanIsUpdated() throws ValidationException { Binder<Person> binder = new Binder<>(); binder.bind(nameField, Person::getFirstName, Person::setFirstName); @@ -180,7 +181,7 @@ public class BinderTest { } @Test - public void save_null_beanIsUpdated() { + public void save_null_beanIsUpdated() throws ValidationException { Binder<Person> binder = new Binder<>(); binder.forField(nameField).withConverter(fieldValue -> { if ("null".equals(fieldValue)) { @@ -202,6 +203,53 @@ public class BinderTest { Assert.assertNull(person.getFirstName()); } + @Test(expected = ValidationException.class) + public void save_fieldValidationErrors() throws ValidationException { + Binder<Person> binder = new Binder<>(); + String msg = "foo"; + binder.forField(nameField).withValidator(new NotEmptyValidator<>(msg)) + .bind(Person::getFirstName, Person::setFirstName); + + Person person = new Person(); + String firstName = "foo"; + person.setFirstName(firstName); + nameField.setValue(""); + try { + binder.save(person); + } finally { + Assert.assertEquals(firstName, person.getFirstName()); + } + } + + @Test + public void saveIfValid_fieldValidationErrors() { + Binder<Person> binder = new Binder<>(); + String msg = "foo"; + binder.forField(nameField).withValidator(new NotEmptyValidator<>(msg)) + .bind(Person::getFirstName, Person::setFirstName); + + Person person = new Person(); + person.setFirstName("foo"); + nameField.setValue(""); + Assert.assertFalse(binder.saveIfValid(person)); + Assert.assertEquals("foo", person.getFirstName()); + } + + @Test + public void saveIfValid_noValidationErrors() { + Binder<Person> binder = new Binder<>(); + String msg = "foo"; + binder.forField(nameField).withValidator(new NotEmptyValidator<>(msg)) + .bind(Person::getFirstName, Person::setFirstName); + + Person person = new Person(); + person.setFirstName("foo"); + nameField.setValue("bar"); + + Assert.assertTrue(binder.saveIfValid(person)); + Assert.assertEquals("bar", person.getFirstName()); + } + @Test public void load_bound_fieldValueIsUpdated() { Binder<Person> binder = new Binder<>(); |