From fb2ceee075473e10eb94f0c49bc5f4b36836174d Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 25 Jan 2017 16:34:02 +0200 Subject: Extract Bean validation logic from Binder to BeanValidationBinder Fixes #8253 --- .../com/vaadin/data/BeanBinderPropertySet.java | 13 ----- .../java/com/vaadin/data/BeanValidationBinder.java | 63 ++++++++++++++++++++++ server/src/main/java/com/vaadin/data/Binder.java | 27 +++++++--- .../com/vaadin/data/BinderPropertyDefinition.java | 15 ------ .../com/vaadin/data/validator/BeanValidator.java | 2 +- .../test/java/com/vaadin/data/BeanBinderTest.java | 2 +- .../vaadin/data/BinderCustomPropertySetTest.java | 7 --- .../src/test/java/com/vaadin/data/Jsr303Test.java | 8 +++ 8 files changed, 94 insertions(+), 43 deletions(-) create mode 100644 server/src/main/java/com/vaadin/data/BeanValidationBinder.java (limited to 'server') diff --git a/server/src/main/java/com/vaadin/data/BeanBinderPropertySet.java b/server/src/main/java/com/vaadin/data/BeanBinderPropertySet.java index f28873438e..d5fb2b4f5d 100644 --- a/server/src/main/java/com/vaadin/data/BeanBinderPropertySet.java +++ b/server/src/main/java/com/vaadin/data/BeanBinderPropertySet.java @@ -30,9 +30,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.vaadin.data.Binder.BindingBuilder; import com.vaadin.data.util.BeanUtil; -import com.vaadin.data.validator.BeanValidator; import com.vaadin.server.Setter; import com.vaadin.util.ReflectTools; @@ -152,17 +150,6 @@ public class BeanBinderPropertySet implements BinderPropertySet { .convertPrimitiveType(descriptor.getPropertyType()); } - @Override - public BindingBuilder beforeBind( - BindingBuilder originalBuilder) { - if (BeanUtil.checkBeanValidationAvailable()) { - return originalBuilder.withValidator(new BeanValidator( - getPropertySet().beanType, descriptor.getName())); - } else { - return originalBuilder; - } - } - @Override public String getName() { return descriptor.getName(); diff --git a/server/src/main/java/com/vaadin/data/BeanValidationBinder.java b/server/src/main/java/com/vaadin/data/BeanValidationBinder.java new file mode 100644 index 0000000000..5e3b220ffd --- /dev/null +++ b/server/src/main/java/com/vaadin/data/BeanValidationBinder.java @@ -0,0 +1,63 @@ +/* + * 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 com.vaadin.data.util.BeanUtil; +import com.vaadin.data.validator.BeanValidator; + +/** + * @author Vaadin Ltd + * @see Binder + * @see HasValue + * + * @since 8.0 + */ +public class BeanValidationBinder extends Binder { + + private final Class beanType; + + /** + * Creates a new binder that uses reflection based on the provided bean type + * to resolve bean properties. It assumes that JSR-303 bean validation + * implementation is present on the classpath. If there is no such + * implementation available then {@link Binder} class should be used instead + * (this constructor will throw an exception). Otherwise + * {@link BeanValidator} is added to each binding that is defined using a + * property name. + * + * @param beanType + * the bean type to use, not null + */ + public BeanValidationBinder(Class beanType) { + super(beanType); + if (!BeanUtil.checkBeanValidationAvailable()) { + throw new IllegalStateException( + BeanValidationBinder.class.getSimpleName() + + " cannot be used because a JSR-303 Bean Validation " + + "implementation not found on the classpath. Use " + + Binder.class.getSimpleName() + " instead"); + } + this.beanType = beanType; + } + + @Override + protected BindingBuilder configureBinding( + BindingBuilder binding, + BinderPropertyDefinition definition) { + return binding.withValidator( + new BeanValidator(beanType, definition.getName())); + } +} diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 7451c004ed..4cbcd18eb1 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -619,13 +619,14 @@ public class Binder implements Serializable { // Setter ignores value }); - BindingBuilder finalBinding = withConverter( + BindingBuilder finalBinding = withConverter( createConverter(definition.getType()), false); - finalBinding = definition.beforeBind(finalBinding); + finalBinding = getBinder().configureBinding(finalBinding, + definition); try { - return finalBinding.bind(getter, setter); + return ((BindingBuilder) finalBinding).bind(getter, setter); } finally { getBinder().boundProperties.add(propertyName); getBinder().incompleteMemberFieldBindings.remove(getField()); @@ -1085,9 +1086,7 @@ public class Binder implements Serializable { /** * Creates a new binder that uses reflection based on the provided bean type - * to resolve bean properties. If a JSR-303 bean validation implementation - * is present on the classpath, a {@link BeanValidator} is added to each - * binding that is defined using a property name. + * to resolve bean properties. * * @param beanType * the bean type to use, not null @@ -1937,6 +1936,22 @@ public class Binder implements Serializable { return eventRouter; } + /** + * Configures the {@code binding} with the property definition + * {@code definition} before it's being bound. + * + * @param binding + * a binding to configure + * @param definition + * a property definition information + * @return the new configured binding + */ + protected BindingBuilder configureBinding( + BindingBuilder binding, + BinderPropertyDefinition definition) { + return binding; + } + private void doRemoveBean(boolean fireStatusEvent) { setHasChanges(false); if (bean != null) { diff --git a/server/src/main/java/com/vaadin/data/BinderPropertyDefinition.java b/server/src/main/java/com/vaadin/data/BinderPropertyDefinition.java index 7ab7e1ccec..b4145a8c4f 100644 --- a/server/src/main/java/com/vaadin/data/BinderPropertyDefinition.java +++ b/server/src/main/java/com/vaadin/data/BinderPropertyDefinition.java @@ -18,7 +18,6 @@ package com.vaadin.data; import java.io.Serializable; import java.util.Optional; -import com.vaadin.data.Binder.BindingBuilder; import com.vaadin.server.Setter; /** @@ -55,20 +54,6 @@ public interface BinderPropertyDefinition extends Serializable { */ public Class getType(); - /** - * Hook for modifying a binding before it is being bound to this property. - * This method can return the provided {@link BindingBuilder} as-is if no - * modifications are necessary. - * - * @param originalBuilder - * the original binding builder that is being bound, not - * null - * @return the binding builder to use for creating the binding, not - * null - */ - public BindingBuilder beforeBind( - BindingBuilder originalBuilder); - /** * Gets the name of this property. * diff --git a/server/src/main/java/com/vaadin/data/validator/BeanValidator.java b/server/src/main/java/com/vaadin/data/validator/BeanValidator.java index 3d7baa05a0..097b47cb0f 100644 --- a/server/src/main/java/com/vaadin/data/validator/BeanValidator.java +++ b/server/src/main/java/com/vaadin/data/validator/BeanValidator.java @@ -91,7 +91,7 @@ public class BeanValidator implements Validator { if (!BeanUtil.checkBeanValidationAvailable()) { throw new IllegalStateException("Cannot create a " + BeanValidator.class.getSimpleName() - + ": a JSR-303 Bean Validation implementation not found on theclasspath"); + + ": a JSR-303 Bean Validation implementation not found on the classpath"); } Objects.requireNonNull(beanType, "bean class cannot be null"); Objects.requireNonNull(propertyName, "property name cannot be null"); diff --git a/server/src/test/java/com/vaadin/data/BeanBinderTest.java b/server/src/test/java/com/vaadin/data/BeanBinderTest.java index 6bd53044b7..2103c2b132 100644 --- a/server/src/test/java/com/vaadin/data/BeanBinderTest.java +++ b/server/src/test/java/com/vaadin/data/BeanBinderTest.java @@ -48,7 +48,7 @@ public class BeanBinderTest @Before public void setUp() { - binder = new Binder<>(BeanToValidate.class); + binder = new BeanValidationBinder<>(BeanToValidate.class); item = new BeanToValidate(); item.setFirstname("Johannes"); item.setAge(32); diff --git a/server/src/test/java/com/vaadin/data/BinderCustomPropertySetTest.java b/server/src/test/java/com/vaadin/data/BinderCustomPropertySetTest.java index 3d85084bc6..d8ebf4da10 100644 --- a/server/src/test/java/com/vaadin/data/BinderCustomPropertySetTest.java +++ b/server/src/test/java/com/vaadin/data/BinderCustomPropertySetTest.java @@ -23,7 +23,6 @@ import java.util.stream.Stream; import org.junit.Assert; import org.junit.Test; -import com.vaadin.data.Binder.BindingBuilder; import com.vaadin.server.Setter; import com.vaadin.ui.TextField; @@ -60,12 +59,6 @@ public class BinderCustomPropertySetTest { return String.class; } - @Override - public BindingBuilder, String> beforeBind( - BindingBuilder, String> originalBuilder) { - return originalBuilder; - } - @Override public String getName() { return name; diff --git a/server/src/test/java/com/vaadin/data/Jsr303Test.java b/server/src/test/java/com/vaadin/data/Jsr303Test.java index 43b03feb97..c907bd2af0 100644 --- a/server/src/test/java/com/vaadin/data/Jsr303Test.java +++ b/server/src/test/java/com/vaadin/data/Jsr303Test.java @@ -98,6 +98,14 @@ public class Jsr303Test { // BeanToValidate : @Size(min = 3, max = 16) for the firstName nameField.setValue("a"); assertEquals(nameField.getValue(), item.getFirstname()); + + try { + BeanValidationBinder beanValidationBinder = new BeanValidationBinder<>( + BeanToValidate.class); + Assert.fail(); + } catch (IllegalStateException ignore) { + // an exception has to be thrown + } } } -- cgit v1.2.3