Fixes #8253tags/8.0.0.beta2
@@ -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<T> implements BinderPropertySet<T> { | |||
.convertPrimitiveType(descriptor.getPropertyType()); | |||
} | |||
@Override | |||
public BindingBuilder<T, V> beforeBind( | |||
BindingBuilder<T, V> originalBuilder) { | |||
if (BeanUtil.checkBeanValidationAvailable()) { | |||
return originalBuilder.withValidator(new BeanValidator( | |||
getPropertySet().beanType, descriptor.getName())); | |||
} else { | |||
return originalBuilder; | |||
} | |||
} | |||
@Override | |||
public String getName() { | |||
return descriptor.getName(); |
@@ -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<BEAN> extends Binder<BEAN> { | |||
private final Class<BEAN> 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 <code>null</code> | |||
*/ | |||
public BeanValidationBinder(Class<BEAN> 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<BEAN, ?> configureBinding( | |||
BindingBuilder<BEAN, ?> binding, | |||
BinderPropertyDefinition<BEAN, ?> definition) { | |||
return binding.withValidator( | |||
new BeanValidator(beanType, definition.getName())); | |||
} | |||
} |
@@ -619,13 +619,14 @@ public class Binder<BEAN> implements Serializable { | |||
// Setter ignores value | |||
}); | |||
BindingBuilder finalBinding = withConverter( | |||
BindingBuilder<BEAN, ?> 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<BEAN> 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 <code>null</code> | |||
@@ -1937,6 +1936,22 @@ public class Binder<BEAN> 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<BEAN, ?> configureBinding( | |||
BindingBuilder<BEAN, ?> binding, | |||
BinderPropertyDefinition<BEAN, ?> definition) { | |||
return binding; | |||
} | |||
private void doRemoveBean(boolean fireStatusEvent) { | |||
setHasChanges(false); | |||
if (bean != null) { |
@@ -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<T, V> extends Serializable { | |||
*/ | |||
public Class<V> 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 | |||
* <code>null</code> | |||
* @return the binding builder to use for creating the binding, not | |||
* <code>null</code> | |||
*/ | |||
public BindingBuilder<T, V> beforeBind( | |||
BindingBuilder<T, V> originalBuilder); | |||
/** | |||
* Gets the name of this property. | |||
* |
@@ -91,7 +91,7 @@ public class BeanValidator implements Validator<Object> { | |||
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"); |
@@ -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); |
@@ -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<Map<String, String>, String> beforeBind( | |||
BindingBuilder<Map<String, String>, String> originalBuilder) { | |||
return originalBuilder; | |||
} | |||
@Override | |||
public String getName() { | |||
return name; |
@@ -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<BeanToValidate> beanValidationBinder = new BeanValidationBinder<>( | |||
BeanToValidate.class); | |||
Assert.fail(); | |||
} catch (IllegalStateException ignore) { | |||
// an exception has to be thrown | |||
} | |||
} | |||
} |