KEMBAR78
Vaadin 8 - Data Binding with Binder | PDF
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
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

Vaadin 8 - Data Binding with Binder

  • 1.
    B U SI N E S S D ATA B I N D I N G FOR VAADIN (8) APPLICATIONPETER LEHTO @peter_lehto
  • 2.
    Session’s content • TheGood 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 • TheGood 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 ww 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(VaadinRequestvaadinRequest) { VerticalLayout layout = new VerticalLayout(); TextField firstName = new TextField("Firstname"); TextField lastName = new TextField("Lastname"); No data binding VAADIN 7
  • 6.
    @Override protected void init(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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 valuesetting • 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 usedexplicitly • 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(VaadinRequestvaadinRequest) { 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(VaadinRequestvaadinRequest) { 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 protectedvoid 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 moreexplicit 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 typesafe • 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 FS FIGHT FOR SIMPLICITY ;)
  • 21.
    Session’s content • TheGood 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 el d G r o u p TO B i n d e r
  • 24.
    H o ww 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 nv 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 id 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 id 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 • TheGood 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 MoneyFieldextends CustomField<Money> {
  • 56.
    CUSTOMFIELD public class MoneyFieldextends CustomField<Money> { private TextField textField; private Label currencyCode;
  • 57.
    CUSTOMFIELD public class MoneyFieldextends CustomField<Money> { private TextField textField; private Label currencyCode; private BigDecimal parseValue() throws ParseException { return …; } private String formatValue(BigDecimal parsedValue) { return …; }
  • 58.
    CUSTOMFIELD public class MoneyFieldextends 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(Moneyvalue) { if (value == null) { textField.clear(); currencyCode.setValue(null); } else { textField.setValue(formatValue(value.getAmount())); currencyCode.setValue(value.getCurrencyCode()); } }
  • 60.
    Session’s content • TheGood 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 mb o B o x C o m b o B o x < C o u n t r y > TO
  • 63.
    C o un 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 ww 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 = newBeanItemContainer<>(Country.class);
  • 66.
    BeanItemContainer<Country> container = newBeanItemContainer<>(Country.class); container.addAll(getCountries());
  • 67.
    BeanItemContainer<Country> container = newBeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox();
  • 68.
    BeanItemContainer<Country> container = newBeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox(); countrySelector.setContainerDataSource(container);
  • 69.
    BeanItemContainer<Country> container = newBeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox(); countrySelector.setContainerDataSource(container); countrySelector.setItemCaptionMode(ItemCaptionMode.PROPERTY);
  • 70.
    BeanItemContainer<Country> container = newBeanItemContainer<>(Country.class); container.addAll(getCountries()); ComboBox countrySelector = new ComboBox(); countrySelector.setContainerDataSource(container); countrySelector.setItemCaptionMode(ItemCaptionMode.PROPERTY); countrySelector.setItemCaptionPropertyId("name");
  • 71.
    H o ww 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 ww 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 th e r l a n d s , a n y o n e ?
  • 77.
  • 78.
    H o ww 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 ta P r o v i d e r < C o u n t r y, S t r i n g >
  • 80.
  • 81.
    countrySelector.setDataProvider(DataProvider<Country, String> dataProvider) publicinterface DataProvider<Country, String> { int size(Query<String> t); Stream<Country> fetch(Query<String> query); }
  • 82.
    D a ta P r o v i d e r < C o u n t r y, S t r i n g >
  • 83.
    D a ta 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 ug 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 er y < F >
  • 86.
    public class Query<F>{ int getOffset(); int getLimit(); List<SortOrder<String>> getSortOrders(); Optional<F> getFilter(); }
  • 87.
    T h ec 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.
  • 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 FS 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 publicClass<Integer> getType() { return Integer.class; } @Override public Integer getValue(Item item, Object itemId, Object propertyId) { return LocalDate.now().getYear() - ((CustomerDTO)itemId).getYearOfBirth(); } });
  • 97.
    # F FS OH REALLY!?
  • 98.
    B y eB 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.
  • 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 • Vaadin8 - 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 AN K Y O U ! PLEASE RATE THE TALK @ FLIP CHART BY THE DOOR! @peter_lehto