Comprehensive Java web application development framework that enables server-side Java development with modern web UI components and automatic client-server communication.
Vaadin's data binding system provides two-way synchronization between UI components and Java objects (beans). It includes validation, conversion, and automatic form handling with comprehensive error management.
// Data binding core classes
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.BeanBinder;
import com.vaadin.flow.data.binder.Binding;
import com.vaadin.flow.data.binder.BindingBuilder;
import com.vaadin.flow.data.binder.BindingValidationStatus;
import com.vaadin.flow.data.binder.BinderValidationStatus;
// Validation
import com.vaadin.flow.data.validator.Validator;
import com.vaadin.flow.data.validator.ValidationResult;
import com.vaadin.flow.data.validator.StringLengthValidator;
import com.vaadin.flow.data.validator.EmailValidator;
import com.vaadin.flow.data.validator.RegexpValidator;
import com.vaadin.flow.data.validator.RangeValidator;
import com.vaadin.flow.data.validator.DateRangeValidator;
import com.vaadin.flow.data.validator.BeanValidator;
// Conversion
import com.vaadin.flow.data.converter.Converter;
import com.vaadin.flow.data.converter.StringToIntegerConverter;
import com.vaadin.flow.data.converter.StringToDoubleConverter;
import com.vaadin.flow.data.converter.StringToBigDecimalConverter;
import com.vaadin.flow.data.converter.StringToDateConverter;
import com.vaadin.flow.data.converter.StringToBooleanConverter;
import com.vaadin.flow.data.converter.LocalDateToDateConverter;
import com.vaadin.flow.data.converter.DateToLocalDateConverter;
// Value providers and property access
import com.vaadin.flow.function.ValueProvider;
import com.vaadin.flow.function.SerializableFunction;
import com.vaadin.flow.function.SerializablePredicate;
import com.vaadin.flow.function.SerializableBiConsumer;
import com.vaadin.flow.data.binder.Setter;
import com.vaadin.flow.data.binder.PropertyDefinition;
// Result and context
import com.vaadin.flow.data.converter.Result;
import com.vaadin.flow.data.binder.ValueContext;
// Error handling
import com.vaadin.flow.data.binder.ErrorMessageProvider;
import com.vaadin.flow.data.binder.BindingValidationErrorHandler;
import com.vaadin.flow.data.binder.DefaultBindingValidationErrorHandler;
import com.vaadin.flow.data.binder.StatusChangeListener;
import com.vaadin.flow.data.binder.StatusChangeEvent;
// Required field configuration
import com.vaadin.flow.data.binder.RequiredFieldConfigurator;
import com.vaadin.flow.data.binder.DefaultRequiredFieldConfigurator;
// Component interfaces
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.HasValidation;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.shared.Registration;
// Standard Java types
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.Optional;
import java.util.List;
import java.util.Locale;
import java.text.DateFormat;Main class for binding form fields to bean properties with validation support.
public class Binder<BEAN> {
public Binder();
public Binder(Class<BEAN> beanType);
// Field binding
public <FIELDVALUE> Binder.Binding<BEAN, FIELDVALUE> forField(HasValue<?, FIELDVALUE> field);
public <FIELDVALUE> Binder.BindingBuilder<BEAN, FIELDVALUE> forField(HasValue<?, FIELDVALUE> field);
// Bean operations
public void setBean(BEAN bean);
public BEAN getBean();
public void removeBean();
public void readBean(BEAN bean);
public boolean writeBeanIfValid(BEAN bean);
public BinderValidationStatus<BEAN> writeBeanAsDraft(BEAN bean);
// Validation
public boolean validate();
public BinderValidationStatus<BEAN> validate(boolean fireStatusChange);
public boolean isValid();
// Status change handling
public Registration addStatusChangeListener(StatusChangeListener listener);
public Registration addValueChangeListener(ValueChangeListener<HasValue.ValueChangeEvent<Object>> listener);
// Bean validation
public Binder<BEAN> withValidator(Validator<? super BEAN> validator);
public void setValidatorsDisabled(boolean validatorsDisabled);
public boolean isValidatorsDisabled();
// Required field handling
public void setRequiredConfigurator(RequiredFieldConfigurator requiredConfigurator);
// Conversion and validation error handling
public void setValidationErrorHandler(BindingValidationErrorHandler handler);
public void setStatusLabel(Label statusLabel);
}Individual field binding with conversion and validation.
public static class Binding<BEAN, FIELDVALUE> {
// Validation
public Binding<BEAN, FIELDVALUE> withValidator(Validator<? super FIELDVALUE> validator);
public Binding<BEAN, FIELDVALUE> withValidator(SerializablePredicate<? super FIELDVALUE> predicate, String message);
public Binding<BEAN, FIELDVALUE> withValidator(SerializablePredicate<? super FIELDVALUE> predicate, ErrorMessageProvider errorMessageProvider);
// Null handling
public Binding<BEAN, FIELDVALUE> withNullRepresentation(FIELDVALUE nullRepresentation);
// Conversion
public <TARGET> Binder.BindingBuilder<BEAN, TARGET> withConverter(Converter<FIELDVALUE, TARGET> converter);
public <TARGET> Binder.BindingBuilder<BEAN, TARGET> withConverter(SerializableFunction<FIELDVALUE, TARGET> toModel,
SerializableFunction<TARGET, FIELDVALUE> toPresentation);
// Bean property binding
public Binding<BEAN, FIELDVALUE> bind(ValueProvider<BEAN, FIELDVALUE> getter, Setter<BEAN, FIELDVALUE> setter);
public Binding<BEAN, FIELDVALUE> bind(String propertyName);
// Status
public BindingValidationStatus<FIELDVALUE> validate();
public BindingValidationStatus<FIELDVALUE> validate(boolean fireStatusChange);
// Control
public void unbind();
public HasValue<?, FIELDVALUE> getField();
}Extended binder with automatic bean property binding and JSR-303 validation support.
public class BeanBinder<BEAN> extends Binder<BEAN> {
public BeanBinder(Class<BEAN> beanType);
// Automatic binding
public BeanBinder<BEAN> bindInstanceFields(Object objectWithMemberFields);
public BindingBuilder<BEAN, ?> forMemberField(HasValue<?, ?> field);
// Bean validation
public BeanBinder<BEAN> withValidator(Validator<? super BEAN> validator);
public void setBean(BEAN bean);
}Core validation interface for field and bean validation.
public interface Validator<T> extends SerializableFunction<T, ValidationResult> {
ValidationResult apply(T value, ValueContext context);
// Static factory methods
static <T> Validator<T> from(SerializablePredicate<T> predicate, String errorMessage);
static <T> Validator<T> from(SerializablePredicate<T> predicate, ErrorMessageProvider errorMessageProvider);
}Result of validation containing success/failure status and error messages.
public class ValidationResult {
// Factory methods
public static ValidationResult ok();
public static ValidationResult error(String errorMessage);
public static ValidationResult create(String errorMessage, boolean isError);
// Status checking
public boolean isError();
public Optional<String> getErrorMessage();
// Combining results
public ValidationResult combine(ValidationResult other);
}Common validation implementations.
public class StringLengthValidator implements Validator<String> {
public StringLengthValidator(String errorMessage, int minLength, int maxLength);
public StringLengthValidator(String errorMessage, Integer minLength, Integer maxLength);
}
public class EmailValidator implements Validator<String> {
public EmailValidator(String errorMessage);
}
public class RegexpValidator implements Validator<String> {
public RegexpValidator(String errorMessage, String regexp);
public RegexpValidator(String errorMessage, String regexp, boolean completeMatch);
}
public class RangeValidator<T extends Comparable<? super T>> implements Validator<T> {
public RangeValidator(String errorMessage, T minValue, T maxValue);
}
public class DateRangeValidator extends RangeValidator<LocalDate> {
public DateRangeValidator(String errorMessage, LocalDate minValue, LocalDate maxValue);
}
public class BeanValidator implements Validator<Object> {
public BeanValidator(Class<?> beanClass, String propertyName);
}Status information about validation results.
public class BinderValidationStatus<BEAN> {
public List<BindingValidationStatus<?>> getFieldValidationStatuses();
public List<ValidationResult> getBeanValidationResults();
public boolean isOk();
public boolean hasErrors();
public List<BindingValidationStatus<?>> getFieldValidationErrors();
public List<ValidationResult> getBeanValidationErrors();
}
public class BindingValidationStatus<TARGET> {
public ValidationResult getResult();
public HasValue<?, ?> getField();
public boolean isError();
public Optional<String> getMessage();
}Interface for converting between field values and bean property values.
public interface Converter<PRESENTATION, MODEL> extends Serializable {
Result<MODEL> convertToModel(PRESENTATION value, ValueContext context);
PRESENTATION convertToPresentation(MODEL value, ValueContext context);
// Default methods
default <TARGET> Converter<PRESENTATION, TARGET> chain(Converter<MODEL, TARGET> other);
}Container for conversion results with success/failure handling.
public class Result<R> {
// Factory methods
public static <R> Result<R> ok(R value);
public static <R> Result<R> error(String message);
// Status checking
public boolean isError();
public R getOrThrow(SerializableFunction<String, RuntimeException> exceptionSupplier);
// Value handling
public <S> Result<S> map(SerializableFunction<R, S> mapper);
public <S> Result<S> flatMap(SerializableFunction<R, Result<S>> mapper);
public Optional<R> asOptional();
public Optional<String> getMessage();
}Common conversion implementations.
public class StringToIntegerConverter implements Converter<String, Integer> {
public StringToIntegerConverter(String errorMessage);
public StringToIntegerConverter(Integer emptyValue, String errorMessage);
}
public class StringToDoubleConverter implements Converter<String, Double> {
public StringToDoubleConverter(String errorMessage);
public StringToDoubleConverter(Double emptyValue, String errorMessage);
}
public class StringToBigDecimalConverter implements Converter<String, BigDecimal> {
public StringToBigDecimalConverter(String errorMessage);
public StringToBigDecimalConverter(BigDecimal emptyValue, String errorMessage);
}
public class StringToDateConverter implements Converter<String, Date> {
public StringToDateConverter(String errorMessage);
public StringToDateConverter(DateFormat dateFormat, String errorMessage);
}
public class LocalDateToDateConverter implements Converter<LocalDate, Date> {
public LocalDateToDateConverter();
}
public class DateToLocalDateConverter implements Converter<Date, LocalDate> {
public DateToLocalDateConverter();
}
public class StringToBooleanConverter implements Converter<String, Boolean> {
public StringToBooleanConverter(String trueString, String falseString, String errorMessage);
}Context information for validation and conversion operations.
public class ValueContext {
public ValueContext();
public ValueContext(Component component);
public ValueContext(Component component, HasValue<?, ?> hasValue);
public Optional<Component> getComponent();
public Optional<HasValue<?, ?>> getHasValue();
public Optional<Locale> getLocale();
// Builder methods
public ValueContext withLocale(Locale locale);
public ValueContext withComponent(Component component);
public ValueContext withHasValue(HasValue<?, ?> hasValue);
}Interfaces for providing localized error messages.
public interface ErrorMessageProvider extends SerializableFunction<ValueContext, String> {
String apply(ValueContext context);
}
public interface BindingValidationErrorHandler extends Serializable {
void handleError(HasValue<?, ?> field, ValidationResult result);
}
public class DefaultBindingValidationErrorHandler implements BindingValidationErrorHandler {
public void handleError(HasValue<?, ?> field, ValidationResult result);
}Events for monitoring binding status changes.
public interface StatusChangeListener extends SerializableEventListener {
void statusChange(StatusChangeEvent statusChangeEvent);
}
public class StatusChangeEvent extends EventObject {
public Binder<?> getBinder();
public boolean hasValidationErrors();
}Utilities for accessing bean properties in a type-safe manner.
public interface ValueProvider<SOURCE, TARGET> extends SerializableFunction<SOURCE, TARGET> {
TARGET apply(SOURCE source);
// Default methods for nested properties
default <V> ValueProvider<SOURCE, V> andThen(ValueProvider<TARGET, V> after);
}
public interface Setter<BEAN, FIELDVALUE> extends SerializableBiConsumer<BEAN, FIELDVALUE> {
void accept(BEAN bean, FIELDVALUE fieldvalue);
}
// Property definition utilities
public class PropertyDefinition<T, V> {
public static <T, V> PropertyDefinition<T, V> create(ValueProvider<T, V> getter, Setter<T, V> setter);
public static <T, V> PropertyDefinition<T, V> create(ValueProvider<T, V> getter, Setter<T, V> setter, Class<V> type);
public ValueProvider<T, V> getGetter();
public Optional<Setter<T, V>> getSetter();
public Class<V> getType();
public String getName();
}Configuration for marking fields as required.
public interface RequiredFieldConfigurator extends Serializable {
void configure(HasValue<?, ?> field, boolean required, String caption);
}
public class DefaultRequiredFieldConfigurator implements RequiredFieldConfigurator {
public void configure(HasValue<?, ?> field, boolean required, String caption);
}Control over when changes are applied to the bean.
public class Binder<BEAN> {
// Buffered mode (default)
public boolean writeBeanIfValid(BEAN bean);
public BinderValidationStatus<BEAN> writeBeanAsDraft(BEAN bean);
// Non-buffered mode
public void setBean(BEAN bean); // Immediate binding
public void readBean(BEAN bean); // Read-only binding
}Validation that depends on multiple field values.
// Bean-level validator that can access all fields
binder.withValidator(bean -> {
if (bean.getEndDate().isBefore(bean.getStartDate())) {
return ValidationResult.error("End date must be after start date");
}
return ValidationResult.ok();
});public class PersonForm extends FormLayout {
private TextField firstName = new TextField("First Name");
private TextField lastName = new TextField("Last Name");
private EmailField email = new EmailField("Email");
private DatePicker birthDate = new DatePicker("Birth Date");
private Binder<Person> binder = new Binder<>(Person.class);
public PersonForm() {
// Simple property binding
binder.forField(firstName)
.asRequired("First name is required")
.withValidator(new StringLengthValidator("Name must be 2-50 characters", 2, 50))
.bind(Person::getFirstName, Person::setFirstName);
binder.forField(lastName)
.asRequired("Last name is required")
.bind(Person::getLastName, Person::setLastName);
binder.forField(email)
.withValidator(new EmailValidator("Invalid email address"))
.bind(Person::getEmail, Person::setEmail);
binder.forField(birthDate)
.withValidator(date -> date.isBefore(LocalDate.now()), "Birth date must be in the past")
.bind(Person::getBirthDate, Person::setBirthDate);
add(firstName, lastName, email, birthDate);
}
public void setPerson(Person person) {
binder.setBean(person);
}
public boolean save() {
return binder.writeBeanIfValid(binder.getBean());
}
}TextField ageField = new TextField("Age");
binder.forField(ageField)
.withConverter(new StringToIntegerConverter("Age must be a number"))
.withValidator(age -> age >= 0 && age <= 150, "Age must be between 0 and 150")
.bind(Person::getAge, Person::setAge);BeanBinder<Person> binder = new BeanBinder<>(Person.class);
// Automatic JSR-303 validation
binder.bindInstanceFields(this);
binder.setBean(new Person());
// The Person class should have JSR-303 annotations:
// @NotNull
// @Email
// @Size(min = 2, max = 50)binder.setValidationErrorHandler(new BindingValidationErrorHandler() {
@Override
public void handleError(HasValue<?, ?> field, ValidationResult result) {
if (field instanceof HasValidation) {
((HasValidation) field).setErrorMessage(result.getErrorMessage().orElse(""));
((HasValidation) field).setInvalid(result.isError());
}
}
});The data binding system provides robust form handling with automatic validation, conversion, and error management, significantly reducing boilerplate code for form development.
Install with Tessl CLI
npx tessl i tessl/maven-com-vaadin--vaadin