KEMBAR78
Functional UIs with Java 8 and Vaadin JavaOne2014 | PDF
Functional 
Vaadin 
7 
Henri Muurimaa, SVP of Engineering 
henri@vaadin.com 
@henrimuurimaa
Mission 
Why do we exist 
Make building amazing 
web applications easy
Vaadin X 
Build UIs with components
Developer 
Productivity 
Rich 
UX
Web application layers 
Backend Web server Communication JavaScript 
JS 
required required required required 
Vaadin 
required required optional optional
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
But can it 
scale?
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
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
Demo time
github.com/hezamu/WorkoutTracker
What is 
Functional 
Programming?
A style of programming that 
expresses computation as the 
evaluation of mathematical 
functions
Recursion 
Lazy evaluation 
Lambda expressions 
Pattern matching 
Type theory 
Monads 
Referential 
transparency 
Currying 
Entscheidungsproblem 
Tuples
Something practical? 
Side effects? 
State? 
Denied 
Denied
Okay…
What’s in it for me? 
A new way of thinking 
A new way of programming 
Write tight, robust and scalable code
What’s hot 
in Java 8
Improved 
Date API
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(); 
}
Lambda 
expressions
Anonymous functions 
Runnable r = () -> System.out.println("hello lambda!”); 
Comparator<Integer> cmp1 = (x, y) -> (x < y) ? -1 : ((x > y) ? 1 : 0); 
Comparator<Integer> cmp2 = (x, y) -> { 
return (x < y) ? -1 : ((x > y) ? 1 : 0); // Need return if not one liner 
}; 
// Anonymous onsite functions 
button.addClickListener(event -> System.out.println("Button clicked!"));
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(); 
});
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);
Workout Tracker example 
!editor.activity.addValueChangeListener(new Property.ValueChangeListener() { 
@Override 
public void valueChange(ValueChangeEvent event) { 
updateRating(); 
} 
}); 
editor.date.addValueChangeListener(this::updateRating);
Streams
Stream != Collection 
Create from a Collection or an Iterable 
Composable to new Streams with higher 
order functions 
As lazy as possible
Input validation 
private boolean areInputsValid() { 
Component component = null; 
for (Iterator<Component> iter = editor.iterator(); iter.hasNext(); iter.next()) { 
if (fieldNotValidating(component)) 
return false; 
} 
return true; 
} 
// Java 8 version with anyMatch and a method reference 
private boolean areInputsValid() { 
return !StreamSupport.stream(editor.spliterator(), true) 
.anyMatch(this::fieldNotValidating); 
}
From rating to stars 
StringBuilder stars = new StringBuilder("New Workout: "); 
for (int i = 0; i < rating; ++i) { 
stars.append(FontAwesome.STAR.getHtml()); 
} 
editor.title.setValue("New Workout: “ + stars); 
String stars = IntStream.range(0, rating) 
.mapToObj(r -> FontAwesome.STAR.getHtml()) 
.collect(Collectors.joining("")); 
editor.title.setValue("New Workout: " + stars);
Higher order 
functions
A function that 
takes one or more 
functions as input
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
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()); 
}
What is 
Functional 
Reactive 
Programming?
Observable
Consider a 
spreadsheet
RxJava
Quick peek at RxJava 
Observable<String> letters = Observable.from(new String[] { "a", "b", "c" }); 
letters.subscribe(letter -> System.out.println("Got letter: " + letter));
Power of Observables - composition 
Observable<String> letters = Observable.from(new String[] { "a", “b", "c" }); 
Observable<Integer> numbers = Observable.from(new Integer[] { 1, 2, 3 }); 
Observable<String> pairs = Observable.combineLatest(letters, numbers, (l, n) -> { 
return "" + l + " -> " + n; 
}); 
! 
pairs.subscribe(pair -> System.out.println("Got pair: " + pair));
RxVaadin www.vaadin.com/blog/-/blogs/reactive-functional-ui-development-with-vaadin
Rating to stars, reactive style! 
Observable<String> activities = RxVaadin.valuesWithDefault(editor.activity, null); 
Observable<String> durations = RxVaadin.valuesWithDefault(editor.duration, ""); 
Observable<Date> dates = RxVaadin.valuesWithDefault(editor.date, 
editor.date.getValue()); 
Observable<String> calories = RxVaadin.valuesWithDefault(editor.calories, ""); 
Observable<String> avgHRs = RxVaadin.valuesWithDefault(editor.avgHR, ""); 
Observable<String> maxHRs = RxVaadin.valuesWithDefault(editor.maxHR, ""); 
Observable<String> comments = RxVaadin.valuesWithDefault(editor.comment, "");
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: ", "")); 
} 
});
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));
Summary
The functional additions in Java 8 rock 
Observables allow us avoid the 
“callback hell” with events 
Vaadin works brilliantly with both
Thank You! 
! 
github.com/hezamu 
@henrimuurimaa 
henri@vaadin.com
! 
Join us for a chat 
and drinks at the 
Vaadin Meetup 
! 
Hotel Serrano 
Right now!

Functional UIs with Java 8 and Vaadin JavaOne2014

  • 1.
    Functional Vaadin 7 Henri Muurimaa, SVP of Engineering henri@vaadin.com @henrimuurimaa
  • 3.
    Mission Why dowe exist Make building amazing web applications easy
  • 4.
    Vaadin X BuildUIs with components
  • 5.
  • 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
  • 8.
    But can it scale?
  • 9.
    Test results 20,622AJAX 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
  • 11.
  • 12.
  • 13.
    What is Functional Programming?
  • 14.
    A style ofprogramming that expresses computation as the evaluation of mathematical functions
  • 15.
    Recursion Lazy evaluation Lambda expressions Pattern matching Type theory Monads Referential transparency Currying Entscheidungsproblem Tuples
  • 16.
    Something practical? Sideeffects? State? Denied Denied
  • 17.
  • 19.
    What’s in itfor me? A new way of thinking A new way of programming Write tight, robust and scalable code
  • 20.
  • 21.
  • 22.
    New Java 8Date 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(); }
  • 23.
  • 24.
    Anonymous functions Runnabler = () -> System.out.println("hello lambda!”); Comparator<Integer> cmp1 = (x, y) -> (x < y) ? -1 : ((x > y) ? 1 : 0); Comparator<Integer> cmp2 = (x, y) -> { return (x < y) ? -1 : ((x > y) ? 1 : 0); // Need return if not one liner }; // Anonymous onsite functions button.addClickListener(event -> System.out.println("Button clicked!"));
  • 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 withthe :: 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);
  • 28.
  • 29.
    Stream != Collection Create from a Collection or an Iterable Composable to new Streams with higher order functions As lazy as possible
  • 30.
    Input validation privateboolean areInputsValid() { Component component = null; for (Iterator<Component> iter = editor.iterator(); iter.hasNext(); iter.next()) { if (fieldNotValidating(component)) return false; } return true; } // Java 8 version with anyMatch and a method reference private boolean areInputsValid() { return !StreamSupport.stream(editor.spliterator(), true) .anyMatch(this::fieldNotValidating); }
  • 31.
    From rating tostars StringBuilder stars = new StringBuilder("New Workout: "); for (int i = 0; i < rating; ++i) { stars.append(FontAwesome.STAR.getHtml()); } editor.title.setValue("New Workout: “ + stars); String stars = IntStream.range(0, rating) .mapToObj(r -> FontAwesome.STAR.getHtml()) .collect(Collectors.joining("")); editor.title.setValue("New Workout: " + stars);
  • 32.
  • 33.
    A function that takes one or more functions as input
  • 34.
    Map Returns anew 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()); }
  • 36.
    What is Functional Reactive Programming?
  • 37.
  • 38.
  • 39.
  • 40.
    Quick peek atRxJava Observable<String> letters = Observable.from(new String[] { "a", "b", "c" }); letters.subscribe(letter -> System.out.println("Got letter: " + letter));
  • 41.
    Power of Observables- composition Observable<String> letters = Observable.from(new String[] { "a", “b", "c" }); Observable<Integer> numbers = Observable.from(new Integer[] { 1, 2, 3 }); Observable<String> pairs = Observable.combineLatest(letters, numbers, (l, n) -> { return "" + l + " -> " + n; }); ! pairs.subscribe(pair -> System.out.println("Got pair: " + pair));
  • 42.
  • 43.
    Rating to stars,reactive style! Observable<String> activities = RxVaadin.valuesWithDefault(editor.activity, null); Observable<String> durations = RxVaadin.valuesWithDefault(editor.duration, ""); Observable<Date> dates = RxVaadin.valuesWithDefault(editor.date, editor.date.getValue()); Observable<String> calories = RxVaadin.valuesWithDefault(editor.calories, ""); Observable<String> avgHRs = RxVaadin.valuesWithDefault(editor.avgHR, ""); Observable<String> maxHRs = RxVaadin.valuesWithDefault(editor.maxHR, ""); Observable<String> comments = RxVaadin.valuesWithDefault(editor.comment, "");
  • 44.
    Composing the ratingObservable 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: updatethe 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));
  • 46.
  • 47.
    The functional additionsin Java 8 rock Observables allow us avoid the “callback hell” with events Vaadin works brilliantly with both
  • 48.
    Thank You! ! github.com/hezamu @henrimuurimaa henri@vaadin.com
  • 49.
    ! Join usfor a chat and drinks at the Vaadin Meetup ! Hotel Serrano Right now!