6. Web application layers
Backend Web server Communication JavaScript
JS
required required required required
Vaadin
required required optional optional
7. Web application layers
Backend Web server Communication JavaScript
JS
required required required required
Vaadin
required required optional optional
1 layer
vs
3 layers
Less code
Less bugs
Faster time-to-market
9. Test results
20,622 AJAX requests / minute before exceeding
1% rejected connections
MPAA reports 1,4 billion
movie tickets sold in 2009.
!
~2,700 tickets / minute.
5,496 tickets / minute
~11,000 concurrent users
On a single Amazon EC2
Large instance
www.vaadin.com/blog/-/blogs/vaadin-scalability-study-quicktickets
10. very active there
> 100.000 developers from
> 10.000 cities
> 450 add-ons in the
marketplace
Other
Asia 4 %
20 %
Americas
22 %
Europe
54 %
Open Source community
Apache-licensed
22. New Java 8 Date API in action
public int monthAge() {
return (new Date().getYear() - date.getYear()) * 12
+ (new Date().getMonth() - date.getMonth());
}
// Java 8 version with the new Date API
public int monthAge() {
return (int) Period.between(date, LocalDate.now()).toTotalMonths();
}
25. Workout Tracker example
editor.clear.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
editor.clearValues();
updateRating();
}
});
// Java 8 version with a lambda
editor.clear.addClickListener(event -> {
editor.clearValues();
updateRating();
});
26. Method references with the :: notation
! private void eventHandler(Button.ClickEvent event) {
// do something about the button click
}
button.addClickListener(this::eventHandler);
// If the handler method is static
button.addClickListener(MyClass::eventHandler);
27. Workout Tracker example
!editor.activity.addValueChangeListener(new Property.ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
updateRating();
}
});
editor.date.addValueChangeListener(this::updateRating);
34. Map
Returns a new stream by
applying the given function to
all elements of this stream.
!
Filter
Returns a new stream
consisting of the elements of
this stream that match the
given predicate.
SQL analogue: SELECT SQL analogue: WHERE
35. Workout Tracker Example
private List<Workout> findByAge(int maxMonths) {
List<Workout> result = new ArrayList<>();
for (Workout w : workouts) {
!
!
!
if (w.monthAge() < maxMonths) {
result.add(w);
}
}
Collections.sort(result, new Comparator<Workout>() {
@Override
public int compare(Workout o1, Workout o2) {
return o2.monthAge() - o1.monthAge();
}
});
!
return result;
}
private Stream<Workout> findByAge(int maxMonths) {
return workouts.stream()
!
!
!
.filter(w -> w.monthAge() < maxMonths)
.sorted(Comparator.comparing(Workout::monthAge)
.reversed());
}
44. Composing the rating Observable
Observable<Integer> ratings = WorkoutRatingLogic.ratings(activities,
durations, dates, calories, avgHRs, maxHRs, comments);
Observable<String> ratingStrings = ratings.map(rating -> {
if (rating == null) {
return "New Workout”; // No stars if required fields not ok
} else {
return IntStream.range(0, rating)
.mapToObj(i -> FontAwesome.STAR.getHtml())
.collect(Collectors.joining("", "New Workout: ", ""));
}
});
45. Last step: update the UI
// Have the label update its value whenever the Observable
// emits a value
RxVaadin.follow(editor.title, ratingStrings);
// Disable or enable the add button based on if the rating
// calculation was successful or not
ratings.subscribe(rating -> editor.add.setEnabled(rating != null));