SlideShare a Scribd company logo
B U S I N E S S D ATA B I N D I N G
FOR VAADIN (8) APPLICATIONPETER LEHTO
@peter_lehto
Session’s content
• The Good Ol’ Boy - Vaadin 7
• The Brand New Field Model of Vaadin 8
• CustomField<T>
• Where are my Items & Properties?
• Being Lazy & Happy without Containers
Session’s content
• The Good Ol’ Boy - Vaadin 7
• The Brand New Field Model of Vaadin 8
• CustomField<T>
• Where are my Items & Properties?
• Being Lazy & Happy without Containers
H o w w o u l d y o u e d i t
c u s t o m e r r e c o r d s ?
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
No data binding
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
No data binding
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
firstName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setFirstName(firstName.getValue());
}
});
No data binding
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
firstName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setFirstName(firstName.getValue());
}
});
lastName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setLastName(lastName.getValue());
}
});
No data binding
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
firstName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setFirstName(firstName.getValue());
}
});
lastName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setLastName(lastName.getValue());
}
});
layout.addComponents(firstName, lastName);
setContent(layout);
}
No data binding
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
firstName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setFirstName(firstName.getValue());
}
});
lastName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
customer.setLastName(lastName.getValue());
}
});
layout.addComponents(firstName, lastName);
setContent(layout);
}
• Setters used explicitly
• Every Field has a Listener
• No way to Save / Cancel
• Lots of code
• Prone to error and change
• Invalid values not prevented
WHAT’S WRONG?
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
LET’S IMPROVE!
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
Button save = new Button("Save", new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
customer.setFirstName(firstName.getValue());
customer.setLastName(lastName.getValue());
}
});
layout.addComponents(firstName, lastName, save);
setContent(layout);
}
LET’S IMPROVE!
• Centralized value setting
• Validation could be added
BENEFITS? @Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
Button save = new Button("Save", new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
customer.setFirstName(firstName.getValue());
customer.setLastName(lastName.getValue());
}
});
layout.addComponents(firstName, lastName, save);
setContent(layout);
}
• Setters used explicitly
• Lots of code
• Prone to error and change
• Hard to Validate
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
Button save = new Button("Save", new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
customer.setFirstName(firstName.getValue());
customer.setLastName(lastName.getValue());
}
});
layout.addComponents(firstName, lastName, save);
setContent(layout);
}
WHAT’S WRONG?
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
With properties
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
FieldGroup fieldGroup = new FieldGroup();
fieldGroup.bind(firstName, "firstName");
fieldGroup.bind(lastName, "lastName");
fieldGroup.setItemDataSource(new
BeanItem<CustomerDTO>(customer));
With properties
VAADIN 7
With properties
VAADIN 7
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
FieldGroup fieldGroup = new FieldGroup();
fieldGroup.bind(firstName, "firstName");
fieldGroup.bind(lastName, "lastName");
fieldGroup.setItemDataSource(new
BeanItem<CustomerDTO>(customer));
Button save = new Button("Save", new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
try {
fieldGroup.commit();
}
catch(CommitException e) {
// show errors
}
}
});
• No more explicit setters
• Committable / Discardable
• Validation part of Commit
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
FieldGroup fieldGroup = new FieldGroup();
fieldGroup.bind(firstName, "firstName");
fieldGroup.bind(lastName, "lastName");
fieldGroup.setItemDataSource(new
BeanItem<CustomerDTO>(customer));
Button save = new Button("Save", new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
try {
fieldGroup.commit();
}
catch(CommitException e) {
// show errors
}
}
});
BENEFITS?
• Not type safe
• Prone to error and change
• BeanItem boiler plate and
Checked CommitException
@Override
protected void init(VaadinRequest vaadinRequest) {
VerticalLayout layout = new VerticalLayout();
TextField firstName = new TextField("Firstname");
TextField lastName = new TextField("Lastname");
CustomerDTO customer = new CustomerDTO();
FieldGroup fieldGroup = new FieldGroup();
fieldGroup.bind(firstName, "firstName");
fieldGroup.bind(lastName, "lastName");
fieldGroup.setItemDataSource(new
BeanItem<CustomerDTO>(customer));
Button save = new Button("Save", new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
try {
fieldGroup.commit();
}
catch(CommitException e) {
// show errors
}
}
});
WHAT’S WRONG?
# F F S
FIGHT FOR SIMPLICITY ;)
Session’s content
• The Good Ol’ Boy - Vaadin 7
• The Brand New Field Model of Vaadin 8
• CustomField<T>
• Where are my Items & Properties?
• Being Lazy & Happy without Containers
c . v. u i . A b s t r a c t F i e l d < T >
VAADIN 7
1 8 5 3 l o c 2 1 3 l o c
VAADIN 8
F i e l d G r o u p
TO
B i n d e r
H o w w o u l d y o u e d i t
c u s t o m e r r e c o r d s ?
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);With Binder
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname);
With Binder
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname);
binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname);
With Binder
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname);
binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname);
binder.readBean(customer);
With Binder
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname);
binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname);
binder.readBean(customer);
Commit / Discard?
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname);
binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname);
binder.readBean(customer);
Button save = new Button("Save" , e -> binder.writeBeanIfValid(customer));
Button discard = new Button("Discard" , e -> binder.removeBean());
Commit / Discard?
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname);
binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname);
binder.setBean(customer);
Without Buffering?
VAADIN 8
C o n v e r s i o n
TextField yearOfBirth = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
Conversion with
Binding
VAADIN 8
TextField yearOfBirth = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
Conversion with
Binding
VAADIN 8
TextField yearOfBirth = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withConverter(Integer::valueOf, String::valueOf)
Conversion with
Binding
VAADIN 8
TextField yearOfBirth = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withConverter(Integer::valueOf, String::valueOf)
.bind(CustomerDTO::getYearOfBirth, CustomerDTO::setYearOfBirth);
Conversion with
Binding
VAADIN 8
Va l i d a t i o n
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);Validation with
Binding
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(firstName)
Validation with
Binding
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(firstName)
.withValidator(Validator::notEmpty, "Mandatory field")
Validation with
Binding
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(firstName)
.withValidator(Validator::notEmpty, "Mandatory field")
.withValidator(value -> value.length() < 10, "Must be less than 10 chars")
Validation with
Binding
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(firstName)
.withValidator(Validator::notEmpty, "Mandatory field")
.withValidator(value -> value.length() < 10, "Must be less than 10 chars")
.bind(CustomerDTO::getFirstname, CustomerDTO::setFirstname);
Validation with
Binding
VAADIN 8
TextField firstName = …
TextField lastName = …
CustomerDTO customer = …
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(firstName)
.withValidator(Validator::notEmpty, "Mandatory field")
.withValidator(value -> value.length() < 10, "Must be less than 10 chars")
.bind(CustomerDTO::getFirstname, CustomerDTO::setFirstname);
Button save = new Button("Save", e -> binder.writeBeanIfValid(customer));
Validation with
Binding
VAADIN 8
Va l i d a t i o n
w i t h
C o n v e r s i o n
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);Validation with
Conversion
VAADIN 8
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
Validation with
Conversion
VAADIN 8
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withValidator(value -> value.length() == 4, "Must have 4 characters")
Validation with
Conversion
VAADIN 8
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withValidator(value -> value.length() == 4, "Must have 4 characters")
.withConverter(Integer::valueOf, String::valueOf)
Validation with
Conversion
VAADIN 8
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withValidator(value -> value.length() == 4, "Must have 4 characters")
.withConverter(Integer::valueOf, String::valueOf)
.withValidator(value -> value < 2000, "Must be before year 2000")
Validation with
Conversion
VAADIN 8
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withValidator(value -> value.length() == 4, "Must have 4 characters")
.withConverter(Integer::valueOf, String::valueOf)
.withValidator(value -> value < 2000, "Must be before year 2000")
.bind(CustomerDTO::getYearOfBirth, CustomerDTO::setYearOfBirth);
Validation with
Conversion
VAADIN 8
TextField yearOfBirth = …
Customer customer = …
customer.setYearOfBirth(1984);
BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);
binder.forField(yearOfBirth)
.withValidator(value -> value.length() == 4, "Must have 4 characters")
.withConverter(Integer::valueOf, String::valueOf)
.withValidator(value -> value < 2000, "Must be before year 2000")
.bind(CustomerDTO::getYearOfBirth, CustomerDTO::setYearOfBirth);
Button save = new Button("Save", e -> {
try {
binder.writeBean(customer);
} catch (ValidationException ve) {
ve.getFieldValidationErrors().forEach(error -> …);
}
});
Validation with
Conversion
VAADIN 8
Session’s content
• The Good Ol’ Boy - Vaadin 7
• The Brand New Field Model of Vaadin 8
• CustomField<T>
• Where are my Items & Properties?
• Being Lazy & Happy without Containers
c . v. u i . C u s t o m F i e l d < T >
c . v. u i . C u s t o m F i e l d < T >
F o r m a k i n g F i e l d s f o r y o u r
b u s i n e s s t y p e s
CUSTOMFIELD
public class MoneyField extends CustomField<Money> {
CUSTOMFIELD
public class MoneyField extends CustomField<Money> {
private TextField textField;
private Label currencyCode;
CUSTOMFIELD
public class MoneyField extends CustomField<Money> {
private TextField textField;
private Label currencyCode;
private BigDecimal parseValue() throws ParseException {
return …;
}
private String formatValue(BigDecimal parsedValue) {
return …;
}
CUSTOMFIELD
public class MoneyField extends CustomField<Money> {
private TextField textField;
private Label currencyCode;
private BigDecimal parseValue() throws ParseException {
return …;
}
private String formatValue(BigDecimal parsedValue) {
return …;
}
public Money getValue() {
if (StringUtils.isEmpty(textField.getValue())) {
return null;
}
try {
return Money.of(currencyCode.getValue(), parseValue());
} catch (ParseException e) {
textField.setComponentError(new UserError("Invalid format”));
return null;
}
}
protected void doSetValue(Money value) {
if (value == null) {
textField.clear();
currencyCode.setValue(null);
} else {
textField.setValue(formatValue(value.getAmount()));
currencyCode.setValue(value.getCurrencyCode());
}
}
Session’s content
• The Good Ol’ Boy - Vaadin 7
• The Brand New Field Model of Vaadin 8
• CustomField<T>
• Where are my Items & Properties?
• Being Lazy & Happy without Containers
c . v. d a t a . I t e m
TO
< T >
C o m b o B o x
C o m b o B o x < C o u n t r y >
TO
C o u n t r y c = ( C o u n t r y )
c o m b o B o x . g e t V a l u e ( )
TO
C o u n t r y c = c o m b o B o x . g e t V a l u e ( )
H o w w o u l d y o u m a k e
a d r o p d o w n o f c o u n t r i e s ?
VAADIN 7
BeanItemContainer<Country> container =
new BeanItemContainer<>(Country.class);
BeanItemContainer<Country> container =
new BeanItemContainer<>(Country.class);
container.addAll(getCountries());
BeanItemContainer<Country> container =
new BeanItemContainer<>(Country.class);
container.addAll(getCountries());
ComboBox countrySelector = new ComboBox();
BeanItemContainer<Country> container =
new BeanItemContainer<>(Country.class);
container.addAll(getCountries());
ComboBox countrySelector = new ComboBox();
countrySelector.setContainerDataSource(container);
BeanItemContainer<Country> container =
new BeanItemContainer<>(Country.class);
container.addAll(getCountries());
ComboBox countrySelector = new ComboBox();
countrySelector.setContainerDataSource(container);
countrySelector.setItemCaptionMode(ItemCaptionMode.PROPERTY);
BeanItemContainer<Country> container =
new BeanItemContainer<>(Country.class);
container.addAll(getCountries());
ComboBox countrySelector = new ComboBox();
countrySelector.setContainerDataSource(container);
countrySelector.setItemCaptionMode(ItemCaptionMode.PROPERTY);
countrySelector.setItemCaptionPropertyId("name");
H o w w o u l d y o u m a k e
a d r o p d o w n o f c o u n t r i e s ?
VAADIN 8
ComboBox<Country> countrySelector = new ComboBox<>();
countrySelector.setItems(getCountries());
ComboBox<Country> countrySelector = new ComboBox<>();
countrySelector.setItems(getCountries());
countrySelector.setItemCaptionGenerator(Country::getName);
H o w w o u l d y o u f i l t e r
e n t r i e s i n a d r o p d o w n ?
VAADIN 7
Vaadin 8 - Data Binding with Binder
N e t h e r l a n d s , a n y o n e ?
countrySelector.setFilteringMode(FilteringMode.CONTAINS);
countrySelector.setFilteringMode(FilteringMode.STARTSWITH);
OR
H o w w o u l d y o u f i l t e r
e n t r i e s i n a d r o p d o w n ?
VAADIN 8
D a t a P r o v i d e r < C o u n t r y, S t r i n g >
countrySelector.setDataProvider(DataProvider<Country, String> dataProvider)
countrySelector.setDataProvider(DataProvider<Country, String> dataProvider)
public interface DataProvider<Country, String> {
int size(Query<String> t);
Stream<Country> fetch(Query<String> query);
}
D a t a P r o v i d e r < C o u n t r y, S t r i n g >
D a t a P r o v i d e r < C o u n t r y, S t r i n g >
java.util.function.Predicate<T>
CriteriaQuery.where(...)
Service.findCountries(String)
P l u g i n t o a n y d a t a s o u r c e l a z i l y !
Q u e r y < F >
public class Query<F> {
int getOffset();
int getLimit();
List<SortOrder<String>> getSortOrders();
Optional<F> getFilter();
}
T h e c l a s s i c C o n t a i n e r d i s c r e p a n c y
VAADIN 7
Grid grid = new Grid();
grid.addColumn("firstName");
grid.addColumn("lastName");
grid.addColumn("yearsOld");
grid.setContainerDataSource(
new BeanItemContainer<>(CustomerDTO.class));
HTTP Status 500 - com.vaadin.server.ServiceException:
java.lang.IllegalStateException:
Found at least one column in Grid that does not exist
in the given container: yearsOld with the header “Years
Old”.
Call removeAllColumns() before setContainerDataSource()
if you want to reconfigure the columns based on the new
container.
# F F S
Grid grid = new Grid();
grid.addColumn("firstName");
grid.addColumn("lastName");
grid.addColumn("yearsOld");
Grid grid = new Grid();
grid.addColumn("firstName");
grid.addColumn("lastName");
grid.addColumn("yearsOld");
GeneratedPropertyContainer generatedProps =
new GeneratedPropertyContainer(
new BeanItemContainer<>(CustomerDTO.class));
generatedProps.addContainerProperty("yearsOld", Integer.class, null);
grid.setContainerDataSource(generatedProps);
HTTP Status 500 - com.vaadin.server.ServiceException: java.lang.UnsupportedOperationException:
GeneratedPropertyContainer does not support adding properties.
# F F S
THIS ISN’T FUN ANYMORE…
Grid grid = new Grid();
grid.addColumn("firstName");
grid.addColumn("lastName");
grid.addColumn("yearsOld");
GeneratedPropertyContainer generatedProps =
new GeneratedPropertyContainer(
new BeanItemContainer<>(CustomerDTO.class));
grid.setContainerDataSource(generatedProps);
generatedProps.addGeneratedProperty("yearsOld", new
PropertyValueGenerator<Integer>() {
@Override
public Class<Integer> getType() {
return Integer.class;
}
@Override
public Integer getValue(Item item, Object itemId,
Object propertyId) {
return LocalDate.now().getYear() -
((CustomerDTO)itemId).getYearOfBirth();
}
});
# F F S
OH REALLY!?
B y e B y e C o n t a i n e r s ;
w e ’ v e h a d e n o u g h !
VAADIN 8
Grid<CustomerDTO> grid = new Grid<>();
Grid<CustomerDTO> grid = new Grid<>();
grid.addColumn("firstName", customer -> customer.getFirstname());
Grid<CustomerDTO> grid = new Grid<>();
grid.addColumn("firstName", customer -> customer.getFirstname());
grid.addColumn("lastName", customer -> customer.getLastname());
Grid<CustomerDTO> grid = new Grid<>();
grid.addColumn("firstName", customer -> customer.getFirstname());
grid.addColumn("lastName", customer -> customer.getLastname());
grid.addColumn("yearsOld",
customer -> String.valueOf(LocalDate.now().getYear() -
customer.getYearOfBirth()));
Grid<CustomerDTO> grid = new Grid<>();
grid.addColumn("firstName", customer -> customer.getFirstname());
grid.addColumn("lastName", customer -> customer.getLastname());
grid.addColumn("yearsOld",
customer -> String.valueOf(LocalDate.now().getYear() -
customer.getYearOfBirth()));
grid.setDataProvider(DataProvider<CustomerDTO, F> customerDataProvider);
Lessons learned
• Vaadin 8 - built on Java 8
• Lambdas and Functional paradigm at large
• DataBinding completely redone
• Targets simplifications and flexibility
• Drops Containers, Items and Properties
• Gathers all DataBinding to Binder
T H A N K Y O U !
PLEASE RATE THE TALK
@
FLIP CHART BY THE DOOR!
@peter_lehto

More Related Content

PPT
Chapter 4-Naming.ppt
DOCX
data replication
PPTX
Introduction to Aneka, Aneka Model is explained
PPTX
Role of java in android app development
PPTX
Virtualization- Cloud Computing
PPTX
Distributed Computing
PDF
IPC with Qt
PDF
Hypervisors and Virtualization - VMware, Hyper-V, XenServer, and KVM
Chapter 4-Naming.ppt
data replication
Introduction to Aneka, Aneka Model is explained
Role of java in android app development
Virtualization- Cloud Computing
Distributed Computing
IPC with Qt
Hypervisors and Virtualization - VMware, Hyper-V, XenServer, and KVM

What's hot (20)

PPTX
Getting Started with Apache CloudStack
PDF
Introduction to OpenStack Storage
PDF
AI_6 Uncertainty
ODP
Distributed operating system(os)
PPTX
Virtualization & cloud computing
PDF
cloud virtualization technology
PDF
Software Reuse and Object-Oriented Programming
PDF
Network virtualization seminar report
PPTX
Virtualization
PPTX
Distributed computing
PDF
8. mutual exclusion in Distributed Operating Systems
PPTX
Virtualization
PPTX
Replication in Distributed Systems
PDF
Cloud Computing Using OpenStack
PDF
Zabbix Monitoring Platform
PPT
lecture07.ppt
PDF
Open stack
PPTX
Dynamic memory allocation
PDF
Qu'est ce que le Cloud computing ?
Getting Started with Apache CloudStack
Introduction to OpenStack Storage
AI_6 Uncertainty
Distributed operating system(os)
Virtualization & cloud computing
cloud virtualization technology
Software Reuse and Object-Oriented Programming
Network virtualization seminar report
Virtualization
Distributed computing
8. mutual exclusion in Distributed Operating Systems
Virtualization
Replication in Distributed Systems
Cloud Computing Using OpenStack
Zabbix Monitoring Platform
lecture07.ppt
Open stack
Dynamic memory allocation
Qu'est ce que le Cloud computing ?
Ad

Viewers also liked (20)

PDF
Vaadin 8 with Spring Frameworks AutoConfiguration
PDF
Vaadin 8 with Spring Framework
PDF
Building web apps with Vaadin 8
PDF
Binding business data to vaadin components
PDF
Techlunch - Dependency Injection with Vaadin
PDF
Building impressive layout systems with vaadin
PDF
GWT integration with Vaadin
PDF
Vaadin with Java EE 7
PDF
JavaEE with Vaadin - Workshop
PDF
Functional UIs with Java 8 and Vaadin JavaOne2014
PDF
Remote controlling Parrot AR drone with Vaadin & Spring Boot @ GWT.create
PDF
Remote controlling Parrot AR Drone with Spring Boot & Vaadin (JavaCro15)
PDF
Vaadin 7 - Java Enterprise Edition integration
PDF
Día internacional de la mujer. 2017. mujer y discapacidad.
PDF
Catalogo galleggianti idro stop
PPTX
Cosolvency
PPTX
Learning Hub in Ambala ! Batra Computer Centre
PPT
Modul 8
PDF
Social media is social business
PDF
Panel wim (2)
Vaadin 8 with Spring Frameworks AutoConfiguration
Vaadin 8 with Spring Framework
Building web apps with Vaadin 8
Binding business data to vaadin components
Techlunch - Dependency Injection with Vaadin
Building impressive layout systems with vaadin
GWT integration with Vaadin
Vaadin with Java EE 7
JavaEE with Vaadin - Workshop
Functional UIs with Java 8 and Vaadin JavaOne2014
Remote controlling Parrot AR drone with Vaadin & Spring Boot @ GWT.create
Remote controlling Parrot AR Drone with Spring Boot & Vaadin (JavaCro15)
Vaadin 7 - Java Enterprise Edition integration
Día internacional de la mujer. 2017. mujer y discapacidad.
Catalogo galleggianti idro stop
Cosolvency
Learning Hub in Ambala ! Batra Computer Centre
Modul 8
Social media is social business
Panel wim (2)
Ad

Similar to Vaadin 8 - Data Binding with Binder (20)

PDF
Vaadin DevDay 2017 - Data Binding in Vaadin 8
PDF
PPTX
Vaadin 7 FieldGroup & Converter
PPTX
Writing Good Tests
PDF
MaintainStaffTable
RTF
Easy Button
PPTX
重構—改善既有程式的設計(chapter 8)part 1
DOCX
VISUALIZAR REGISTROS EN UN JTABLE
PDF
Griffon @ Svwjug
PDF
Paintfree Object-Document Mapping for MongoDB by Philipp Krenn
PDF
Vaadin 7
PDF
Unit testing with zend framework tek11
PPTX
An intro to cqrs
PDF
package net.codejava.swing.mail;import java.awt.Font;import java.pdf
PDF
ES2015 New Features
PDF
Wicket KT part 2
KEY
Unit testing with zend framework PHPBenelux
PDF
PDF
2024 PHPCon - Symfony background processing
KEY
SOLID Principles
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin 7 FieldGroup & Converter
Writing Good Tests
MaintainStaffTable
Easy Button
重構—改善既有程式的設計(chapter 8)part 1
VISUALIZAR REGISTROS EN UN JTABLE
Griffon @ Svwjug
Paintfree Object-Document Mapping for MongoDB by Philipp Krenn
Vaadin 7
Unit testing with zend framework tek11
An intro to cqrs
package net.codejava.swing.mail;import java.awt.Font;import java.pdf
ES2015 New Features
Wicket KT part 2
Unit testing with zend framework PHPBenelux
2024 PHPCon - Symfony background processing
SOLID Principles

Recently uploaded (20)

PPTX
Transform Your Business with a Software ERP System
PDF
Digital Strategies for Manufacturing Companies
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
history of c programming in notes for students .pptx
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Nekopoi APK 2025 free lastest update
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PPTX
L1 - Introduction to python Backend.pptx
Transform Your Business with a Software ERP System
Digital Strategies for Manufacturing Companies
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
history of c programming in notes for students .pptx
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Adobe Illustrator 28.6 Crack My Vision of Vector Design
VVF-Customer-Presentation2025-Ver1.9.pptx
Odoo Companies in India – Driving Business Transformation.pdf
Nekopoi APK 2025 free lastest update
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Understanding Forklifts - TECH EHS Solution
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
L1 - Introduction to python Backend.pptx

Vaadin 8 - Data Binding with Binder

  • 1. B U S I N E S S D ATA B I N D I N G FOR VAADIN (8) APPLICATIONPETER LEHTO @peter_lehto
  • 2. Session’s content • The Good Ol’ Boy - Vaadin 7 • The Brand New Field Model of Vaadin 8 • CustomField<T> • Where are my Items & Properties? • Being Lazy & Happy without Containers
  • 3. Session’s content • The Good Ol’ Boy - Vaadin 7 • The Brand New Field Model of Vaadin 8 • CustomField<T> • Where are my Items & Properties? • Being Lazy & Happy without Containers
  • 4. H o w w o u l d y o u e d i t c u s t o m e r r e c o r d s ? VAADIN 7
  • 5. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); No data binding VAADIN 7
  • 6. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); No data binding VAADIN 7
  • 7. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); firstName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setFirstName(firstName.getValue()); } }); No data binding VAADIN 7
  • 8. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); firstName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setFirstName(firstName.getValue()); } }); lastName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setLastName(lastName.getValue()); } }); No data binding VAADIN 7
  • 9. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); firstName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setFirstName(firstName.getValue()); } }); lastName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setLastName(lastName.getValue()); } }); layout.addComponents(firstName, lastName); setContent(layout); } No data binding VAADIN 7
  • 10. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); firstName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setFirstName(firstName.getValue()); } }); lastName.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { customer.setLastName(lastName.getValue()); } }); layout.addComponents(firstName, lastName); setContent(layout); } • Setters used explicitly • Every Field has a Listener • No way to Save / Cancel • Lots of code • Prone to error and change • Invalid values not prevented WHAT’S WRONG?
  • 11. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); LET’S IMPROVE!
  • 12. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); Button save = new Button("Save", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { customer.setFirstName(firstName.getValue()); customer.setLastName(lastName.getValue()); } }); layout.addComponents(firstName, lastName, save); setContent(layout); } LET’S IMPROVE!
  • 13. • Centralized value setting • Validation could be added BENEFITS? @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); Button save = new Button("Save", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { customer.setFirstName(firstName.getValue()); customer.setLastName(lastName.getValue()); } }); layout.addComponents(firstName, lastName, save); setContent(layout); }
  • 14. • Setters used explicitly • Lots of code • Prone to error and change • Hard to Validate @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); Button save = new Button("Save", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { customer.setFirstName(firstName.getValue()); customer.setLastName(lastName.getValue()); } }); layout.addComponents(firstName, lastName, save); setContent(layout); } WHAT’S WRONG?
  • 15. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); With properties VAADIN 7
  • 16. @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); FieldGroup fieldGroup = new FieldGroup(); fieldGroup.bind(firstName, "firstName"); fieldGroup.bind(lastName, "lastName"); fieldGroup.setItemDataSource(new BeanItem<CustomerDTO>(customer)); With properties VAADIN 7
  • 17. With properties VAADIN 7 @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); FieldGroup fieldGroup = new FieldGroup(); fieldGroup.bind(firstName, "firstName"); fieldGroup.bind(lastName, "lastName"); fieldGroup.setItemDataSource(new BeanItem<CustomerDTO>(customer)); Button save = new Button("Save", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { try { fieldGroup.commit(); } catch(CommitException e) { // show errors } } });
  • 18. • No more explicit setters • Committable / Discardable • Validation part of Commit @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); FieldGroup fieldGroup = new FieldGroup(); fieldGroup.bind(firstName, "firstName"); fieldGroup.bind(lastName, "lastName"); fieldGroup.setItemDataSource(new BeanItem<CustomerDTO>(customer)); Button save = new Button("Save", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { try { fieldGroup.commit(); } catch(CommitException e) { // show errors } } }); BENEFITS?
  • 19. • Not type safe • Prone to error and change • BeanItem boiler plate and Checked CommitException @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); CustomerDTO customer = new CustomerDTO(); FieldGroup fieldGroup = new FieldGroup(); fieldGroup.bind(firstName, "firstName"); fieldGroup.bind(lastName, "lastName"); fieldGroup.setItemDataSource(new BeanItem<CustomerDTO>(customer)); Button save = new Button("Save", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { try { fieldGroup.commit(); } catch(CommitException e) { // show errors } } }); WHAT’S WRONG?
  • 20. # F F S FIGHT FOR SIMPLICITY ;)
  • 21. Session’s content • The Good Ol’ Boy - Vaadin 7 • The Brand New Field Model of Vaadin 8 • CustomField<T> • Where are my Items & Properties? • Being Lazy & Happy without Containers
  • 22. c . v. u i . A b s t r a c t F i e l d < T > VAADIN 7 1 8 5 3 l o c 2 1 3 l o c VAADIN 8
  • 23. F i e l d G r o u p TO B i n d e r
  • 24. H o w w o u l d y o u e d i t c u s t o m e r r e c o r d s ? VAADIN 8
  • 25. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);With Binder VAADIN 8
  • 26. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname); With Binder VAADIN 8
  • 27. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname); binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname); With Binder VAADIN 8
  • 28. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname); binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname); binder.readBean(customer); With Binder VAADIN 8
  • 29. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname); binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname); binder.readBean(customer); Commit / Discard? VAADIN 8
  • 30. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname); binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname); binder.readBean(customer); Button save = new Button("Save" , e -> binder.writeBeanIfValid(customer)); Button discard = new Button("Discard" , e -> binder.removeBean()); Commit / Discard? VAADIN 8
  • 31. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.bind(firstName, CustomerDTO::getFirstname, CustomerDTO::setFirstname); binder.bind(lastName, CustomerDTO::getLastname, CustomerDTO::setLastname); binder.setBean(customer); Without Buffering? VAADIN 8
  • 32. C o n v e r s i o n
  • 33. TextField yearOfBirth = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); Conversion with Binding VAADIN 8
  • 34. TextField yearOfBirth = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) Conversion with Binding VAADIN 8
  • 35. TextField yearOfBirth = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withConverter(Integer::valueOf, String::valueOf) Conversion with Binding VAADIN 8
  • 36. TextField yearOfBirth = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withConverter(Integer::valueOf, String::valueOf) .bind(CustomerDTO::getYearOfBirth, CustomerDTO::setYearOfBirth); Conversion with Binding VAADIN 8
  • 37. Va l i d a t i o n
  • 38. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);Validation with Binding VAADIN 8
  • 39. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(firstName) Validation with Binding VAADIN 8
  • 40. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(firstName) .withValidator(Validator::notEmpty, "Mandatory field") Validation with Binding VAADIN 8
  • 41. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(firstName) .withValidator(Validator::notEmpty, "Mandatory field") .withValidator(value -> value.length() < 10, "Must be less than 10 chars") Validation with Binding VAADIN 8
  • 42. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(firstName) .withValidator(Validator::notEmpty, "Mandatory field") .withValidator(value -> value.length() < 10, "Must be less than 10 chars") .bind(CustomerDTO::getFirstname, CustomerDTO::setFirstname); Validation with Binding VAADIN 8
  • 43. TextField firstName = … TextField lastName = … CustomerDTO customer = … BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(firstName) .withValidator(Validator::notEmpty, "Mandatory field") .withValidator(value -> value.length() < 10, "Must be less than 10 chars") .bind(CustomerDTO::getFirstname, CustomerDTO::setFirstname); Button save = new Button("Save", e -> binder.writeBeanIfValid(customer)); Validation with Binding VAADIN 8
  • 44. Va l i d a t i o n w i t h C o n v e r s i o n
  • 45. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class);Validation with Conversion VAADIN 8
  • 46. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) Validation with Conversion VAADIN 8
  • 47. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withValidator(value -> value.length() == 4, "Must have 4 characters") Validation with Conversion VAADIN 8
  • 48. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withValidator(value -> value.length() == 4, "Must have 4 characters") .withConverter(Integer::valueOf, String::valueOf) Validation with Conversion VAADIN 8
  • 49. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withValidator(value -> value.length() == 4, "Must have 4 characters") .withConverter(Integer::valueOf, String::valueOf) .withValidator(value -> value < 2000, "Must be before year 2000") Validation with Conversion VAADIN 8
  • 50. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withValidator(value -> value.length() == 4, "Must have 4 characters") .withConverter(Integer::valueOf, String::valueOf) .withValidator(value -> value < 2000, "Must be before year 2000") .bind(CustomerDTO::getYearOfBirth, CustomerDTO::setYearOfBirth); Validation with Conversion VAADIN 8
  • 51. TextField yearOfBirth = … Customer customer = … customer.setYearOfBirth(1984); BeanBinder<CustomerDTO> binder = new BeanBinder<>(CustomerDTO.class); binder.forField(yearOfBirth) .withValidator(value -> value.length() == 4, "Must have 4 characters") .withConverter(Integer::valueOf, String::valueOf) .withValidator(value -> value < 2000, "Must be before year 2000") .bind(CustomerDTO::getYearOfBirth, CustomerDTO::setYearOfBirth); Button save = new Button("Save", e -> { try { binder.writeBean(customer); } catch (ValidationException ve) { ve.getFieldValidationErrors().forEach(error -> …); } }); Validation with Conversion VAADIN 8
  • 52. Session’s content • The Good Ol’ Boy - Vaadin 7 • The Brand New Field Model of Vaadin 8 • CustomField<T> • Where are my Items & Properties? • Being Lazy & Happy without Containers
  • 53. c . v. u i . C u s t o m F i e l d < T >
  • 54. c . v. u i . C u s t o m F i e l d < T > F o r m a k i n g F i e l d s f o r y o u r b u s i n e s s t y p e s
  • 55. CUSTOMFIELD public class MoneyField extends CustomField<Money> {
  • 56. CUSTOMFIELD public class MoneyField extends CustomField<Money> { private TextField textField; private Label currencyCode;
  • 57. CUSTOMFIELD public class MoneyField extends CustomField<Money> { private TextField textField; private Label currencyCode; private BigDecimal parseValue() throws ParseException { return …; } private String formatValue(BigDecimal parsedValue) { return …; }
  • 58. CUSTOMFIELD public class MoneyField extends CustomField<Money> { private TextField textField; private Label currencyCode; private BigDecimal parseValue() throws ParseException { return …; } private String formatValue(BigDecimal parsedValue) { return …; } public Money getValue() { if (StringUtils.isEmpty(textField.getValue())) { return null; } try { return Money.of(currencyCode.getValue(), parseValue()); } catch (ParseException e) { textField.setComponentError(new UserError("Invalid format”)); return null; } }
  • 59. protected void doSetValue(Money value) { if (value == null) { textField.clear(); currencyCode.setValue(null); } else { textField.setValue(formatValue(value.getAmount())); currencyCode.setValue(value.getCurrencyCode()); } }
  • 60. Session’s content • The Good Ol’ Boy - Vaadin 7 • The Brand New Field Model of Vaadin 8 • CustomField<T> • Where are my Items & Properties? • Being Lazy & Happy without Containers
  • 61. c . v. d a t a . I t e m TO < T >
  • 62. C o m b o B o x C o m b o B o x < C o u n t r y > TO
  • 63. C o u n t r y c = ( C o u n t r y ) c o m b o B o x . g e t V a l u e ( ) TO C o u n t r y c = c o m b o B o x . g e t V a l u e ( )
  • 64. H o w w o u l d y o u m a k e a d r o p d o w n o f c o u n t r i e s ? VAADIN 7
  • 65. BeanItemContainer<Country> container = new BeanItemContainer<>(Country.class);
  • 66. BeanItemContainer<Country> container = new BeanItemContainer<>(Country.class); container.addAll(getCountries());
  • 67. BeanItemContainer<Country> container = new BeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox();
  • 68. BeanItemContainer<Country> container = new BeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox(); countrySelector.setContainerDataSource(container);
  • 69. BeanItemContainer<Country> container = new BeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox(); countrySelector.setContainerDataSource(container); countrySelector.setItemCaptionMode(ItemCaptionMode.PROPERTY);
  • 70. BeanItemContainer<Country> container = new BeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox(); countrySelector.setContainerDataSource(container); countrySelector.setItemCaptionMode(ItemCaptionMode.PROPERTY); countrySelector.setItemCaptionPropertyId("name");
  • 71. H o w w o u l d y o u m a k e a d r o p d o w n o f c o u n t r i e s ? VAADIN 8
  • 72. ComboBox<Country> countrySelector = new ComboBox<>(); countrySelector.setItems(getCountries());
  • 73. ComboBox<Country> countrySelector = new ComboBox<>(); countrySelector.setItems(getCountries()); countrySelector.setItemCaptionGenerator(Country::getName);
  • 74. H o w w o u l d y o u f i l t e r e n t r i e s i n a d r o p d o w n ? VAADIN 7
  • 76. N e t h e r l a n d s , a n y o n e ?
  • 78. H o w w o u l d y o u f i l t e r e n t r i e s i n a d r o p d o w n ? VAADIN 8
  • 79. D a t a P r o v i d e r < C o u n t r y, S t r i n g >
  • 81. countrySelector.setDataProvider(DataProvider<Country, String> dataProvider) public interface DataProvider<Country, String> { int size(Query<String> t); Stream<Country> fetch(Query<String> query); }
  • 82. D a t a P r o v i d e r < C o u n t r y, S t r i n g >
  • 83. D a t a P r o v i d e r < C o u n t r y, S t r i n g > java.util.function.Predicate<T> CriteriaQuery.where(...) Service.findCountries(String)
  • 84. P l u g i n t o a n y d a t a s o u r c e l a z i l y !
  • 85. Q u e r y < F >
  • 86. public class Query<F> { int getOffset(); int getLimit(); List<SortOrder<String>> getSortOrders(); Optional<F> getFilter(); }
  • 87. T h e c l a s s i c C o n t a i n e r d i s c r e p a n c y VAADIN 7
  • 88. Grid grid = new Grid(); grid.addColumn("firstName"); grid.addColumn("lastName"); grid.addColumn("yearsOld"); grid.setContainerDataSource( new BeanItemContainer<>(CustomerDTO.class));
  • 89. HTTP Status 500 - com.vaadin.server.ServiceException: java.lang.IllegalStateException: Found at least one column in Grid that does not exist in the given container: yearsOld with the header “Years Old”. Call removeAllColumns() before setContainerDataSource() if you want to reconfigure the columns based on the new container.
  • 90. # F F S
  • 91. Grid grid = new Grid(); grid.addColumn("firstName"); grid.addColumn("lastName"); grid.addColumn("yearsOld");
  • 92. Grid grid = new Grid(); grid.addColumn("firstName"); grid.addColumn("lastName"); grid.addColumn("yearsOld"); GeneratedPropertyContainer generatedProps = new GeneratedPropertyContainer( new BeanItemContainer<>(CustomerDTO.class)); generatedProps.addContainerProperty("yearsOld", Integer.class, null); grid.setContainerDataSource(generatedProps);
  • 93. HTTP Status 500 - com.vaadin.server.ServiceException: java.lang.UnsupportedOperationException: GeneratedPropertyContainer does not support adding properties.
  • 94. # F F S THIS ISN’T FUN ANYMORE…
  • 95. Grid grid = new Grid(); grid.addColumn("firstName"); grid.addColumn("lastName"); grid.addColumn("yearsOld"); GeneratedPropertyContainer generatedProps = new GeneratedPropertyContainer( new BeanItemContainer<>(CustomerDTO.class)); grid.setContainerDataSource(generatedProps);
  • 96. generatedProps.addGeneratedProperty("yearsOld", new PropertyValueGenerator<Integer>() { @Override public Class<Integer> getType() { return Integer.class; } @Override public Integer getValue(Item item, Object itemId, Object propertyId) { return LocalDate.now().getYear() - ((CustomerDTO)itemId).getYearOfBirth(); } });
  • 97. # F F S OH REALLY!?
  • 98. B y e B y e C o n t a i n e r s ; w e ’ v e h a d e n o u g h ! VAADIN 8
  • 99. Grid<CustomerDTO> grid = new Grid<>();
  • 100. Grid<CustomerDTO> grid = new Grid<>(); grid.addColumn("firstName", customer -> customer.getFirstname());
  • 101. Grid<CustomerDTO> grid = new Grid<>(); grid.addColumn("firstName", customer -> customer.getFirstname()); grid.addColumn("lastName", customer -> customer.getLastname());
  • 102. Grid<CustomerDTO> grid = new Grid<>(); grid.addColumn("firstName", customer -> customer.getFirstname()); grid.addColumn("lastName", customer -> customer.getLastname()); grid.addColumn("yearsOld", customer -> String.valueOf(LocalDate.now().getYear() - customer.getYearOfBirth()));
  • 103. Grid<CustomerDTO> grid = new Grid<>(); grid.addColumn("firstName", customer -> customer.getFirstname()); grid.addColumn("lastName", customer -> customer.getLastname()); grid.addColumn("yearsOld", customer -> String.valueOf(LocalDate.now().getYear() - customer.getYearOfBirth())); grid.setDataProvider(DataProvider<CustomerDTO, F> customerDataProvider);
  • 104. Lessons learned • Vaadin 8 - built on Java 8 • Lambdas and Functional paradigm at large • DataBinding completely redone • Targets simplifications and flexibility • Drops Containers, Items and Properties • Gathers all DataBinding to Binder
  • 105. T H A N K Y O U ! PLEASE RATE THE TALK @ FLIP CHART BY THE DOOR! @peter_lehto