summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2016-08-31 16:17:50 +0300
committerArtur Signell <artur@vaadin.com>2016-08-31 17:11:44 +0300
commit814c29c1521a42f355cfc254fb8b00ae436b4956 (patch)
treeb934305f718059ae6b55addae755c0fd54b5c098 /server
parent82806ef9b7f12c66e620a813c7987c0fbea723dc (diff)
downloadvaadin-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.java59
-rw-r--r--server/src/main/java/com/vaadin/data/ValidationException.java53
-rw-r--r--server/src/test/java/com/vaadin/data/BinderTest.java54
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<>();