introduction to vaadin
DESCRIPTION
An introduction to Vaadin, with a demo application showing how to integrate Spring 3, JPA and Vaadin to quickly build interactive web applications.TRANSCRIPT
Introduction to VaadinBuilding server-side RIA applications
Thomas Neidhart
https://github.com/netomihttp://people.apache.org/~tn
March 29, 2012
T. Neidhart Introduction to Vaadin March 29, 2012 1 / 46
Overview of the talk
Motivation
Comparison to GWT
Why Vaadin?
How does it work?
What does Vaadin offer me?
How can I use it?
An integrated example: Satellite Tracker
T. Neidhart Introduction to Vaadin March 29, 2012 2 / 46
What is the problem?
We want to build web-applications◮ fast development◮ interactive UI (using AJAX)◮ strongly-typed (maintainability)◮ lots of widgets
T. Neidhart Introduction to Vaadin March 29, 2012 3 / 46
Solution: GWT
Coded in Java (subset of J2SE supported)
Compiled to Javascript
Uses (asynchronous) RPC mechanism for client-server communication
T. Neidhart Introduction to Vaadin March 29, 2012 4 / 46
Solution: GWT
Coded in Java (subset of J2SE supported)
Compiled to Javascript
Uses (asynchronous) RPC mechanism for client-server communication
It is great!
T. Neidhart Introduction to Vaadin March 29, 2012 4 / 46
Solution: GWT
Coded in Java (subset of J2SE supported)
Compiled to Javascript
Uses (asynchronous) RPC mechanism for client-server communication
It is great!
But also painful if you happen to work on large projects!◮ slow compilation◮ difficult to debug
T. Neidhart Introduction to Vaadin March 29, 2012 4 / 46
What about Vaadin?1
1taken from Book of VaadinT. Neidhart Introduction to Vaadin March 29, 2012 5 / 46
Pros
100% Java
Strong typing
Object-oriented
Browser independent
Secure◮ business logic on server-side◮ no UI services required
Fast development
T. Neidhart Introduction to Vaadin March 29, 2012 6 / 46
Cons
No offline mode (network connection required)
Scalability concerns◮ Client-side UI state stored on server
Most UI interactions are executed on the server-side (latency!)
Are there more?
T. Neidhart Introduction to Vaadin March 29, 2012 7 / 46
Cons
No offline mode (network connection required)
Scalability concerns◮ Client-side UI state stored on server
Most UI interactions are executed on the server-side (latency!)
Are there more?
Same cons as for other RIA frameworks◮ limited support for browser history◮ state-ful vs. state-less application◮ limited bookmark support
T. Neidhart Introduction to Vaadin March 29, 2012 7 / 46
Used Technologies
Java: server-side API
AJAX: async communication
GWT: client-side widgets
JSON: data exchange
Servlet API: serve HTTP content
T. Neidhart Introduction to Vaadin March 29, 2012 8 / 46
Toolchain
Java SDK
Eclipse IDE
Browser of choice (Firefox, Chrome)
Firebug (optional)
Vaadin Eclipse plugin
GWT Eclipse plugin
Maven
T. Neidhart Introduction to Vaadin March 29, 2012 9 / 46
Helpful Resources
Book of Vaadin http://vaadin.com/book
Vaadin Sampler http://demo.vaadin.com/sampler
Addon Directory https://vaadin.com/directory
Vaadin Forum https://vaadin.com/forum
Sat-Tracker Demo Application https://github.com/netomi/sat-tracker
T. Neidhart Introduction to Vaadin March 29, 2012 10 / 46
How does Vaadin actually work?
Do not worry, it’s not magic
Uses GWT for client-side widgets
Communication between client / server using UIDL◮ User Interface Definition Language◮ json-like format◮ describes the user interface
Only changes are transmitted (ideally - not completely true)
Server-side components acting as stub
T. Neidhart Introduction to Vaadin March 29, 2012 11 / 46
Client-side Engine2
2taken from Book of VaadinT. Neidhart Introduction to Vaadin March 29, 2012 12 / 46
Application Architecture3
3taken from Book of VaadinT. Neidhart Introduction to Vaadin March 29, 2012 13 / 46
Application
Entry point of the web-application
Similar to a session object
One instance per session / user
Initializes the user interface components for the client
T. Neidhart Introduction to Vaadin March 29, 2012 14 / 46
Application - Code
1 @Component(value = "trackerApplication")
2 @Scope(value = "prototype")
3 public class TrackerApplication extends BaseApplication {
4
5 public void init() {
6 setTheme(Runo.THEME_NAME);
7
8 final MainLayout layout = new MainLayout();
9 final Window main = new Window(app.getMessage("application.name"),
10 layout);
11 main.setSizeFull();
12 setMainWindow(main);
13 }
14 }
T. Neidhart Introduction to Vaadin March 29, 2012 15 / 46
Application - Code
1 public abstract class BaseApplication extends Application
2 implements HttpServletRequestListener {
3
4 public final void onRequestStart(HttpServletRequest request,
5 HttpServletResponse response) {
6 ApplicationHolder.setApplication(this);
7 requestStart(request, response);
8 }
9
10 public final void onRequestEnd(HttpServletRequest request,
11 HttpServletResponse response) {
12 try {
13 requestEnd(request, response);
14 } finally {
15 ApplicationHolder.resetApplication();
16 }
17 }
18
19 ..
20 }
T. Neidhart Introduction to Vaadin March 29, 2012 16 / 46
Web.xml1 <context-param>
2 <description>Vaadin production mode</description>
3 <param-name>productionMode</param-name>
4 <param-value>false</param-value>
5 </context-param>
6
7 <servlet>
8 <servlet-name>Myproject Application</servlet-name>
9 <servlet-class>
10 com.vaadin.terminal.gwt.server.ApplicationServlet
11 </servlet-class>
12 <init-param>
13 <description>Vaadin application class to start</description>
14 <param-name>application</param-name>
15 <param-value>
16 com.example.myproject.MyprojectApplication
17 </param-value>
18 </init-param>
19 </servlet>
20
21 <servlet-mapping>
22 <servlet-name>Myproject Application</servlet-name>
23 <url-pattern>/*</url-pattern>
24 </servlet-mapping>
T. Neidhart Introduction to Vaadin March 29, 2012 17 / 46
Web.xml - Spring version
1 <servlet>
2 <servlet-name>SatTracker</servlet-name>
3 <servlet-class>
4 org.netomi.tracker.util.SpringApplicationServlet
5 </servlet-class>
6 <init-param>
7 <description>Vaadin application bean to start</description>
8 <param-name>applicationBean</param-name>
9 <param-value>trackerApplication</param-value>
10 </init-param>
11 <init-param>
12 <description>Application widgetset</description>
13 <param-name>widgetset</param-name>
14 <param-value>org.netomi.tracker.ui.widgetset.TrackerWidgetset</param-value>
15 </init-param>
16 </servlet>
T. Neidhart Introduction to Vaadin March 29, 2012 18 / 46
Widgetset
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.3.0//EN"
3 "http://google-web-toolkit.googlecode.com/svn/tags/2.3.0/distro-source/core/src/gwt-m
4 <module>
5 <inherits name="com.vaadin.terminal.gwt.DefaultWidgetSet" />
6
7 <!-- Use a custom widget map generator to reduce resulting js size, optional-->
8 <generate-with>
9 <class ="org.netomi.tracker.ui.widgetset.CustomWidgetMapGenerator" >
10 <when-type-is class="com.vaadin.terminal.gwt.client.WidgetMap" />
11 </generate-with>
12
13 <!-- The supported user agents at the moment of writing were:
14 ie6,ie8,gecko,gecko1_8,safari,opera
15 The value gecko1_8 is used for Firefox 3 and later and safari is used
16 for webkit based browsers including Google Chrome. -->
17 <!-- <set-property name="user.agent" value="gecko1_8" /> -->
18
19 <!-- any addons that are used and define a widget -->
20 <inherits name="org.vaadin.vol.VolWidgetsetWithHostedScript" />
21 <inherits name="com.github.wolfie.refresher.RefresherApplicationWidgetset"
22 /> </module>
T. Neidhart Introduction to Vaadin March 29, 2012 19 / 46
Widgetset Compilation - maven1 <plugin>
2 <!-- Compile the vaadin widgetset using the GWT compiler -->
3 <groupId>org.codehaus.mojo</groupId>
4 <artifactId>gwt-maven-plugin</artifactId>
5 <version>2.3.0</version>
6 <configuration>
7 <modules>
8 <module>org.netomi.tracker.ui.widgetset.TrackerWidgetset</module>
9 </modules>
10 <webappDirectory>${project.build.directory}/${project.build.finalName}/VAAD
11 <extraJvmArgs>-Xmx512M -Xss1024k</extraJvmArgs>
12 <runTarget>clean</runTarget>
13 <noServer>true</noServer>
14 <port>8080</port>
15 <soyc>false</soyc>
16 </configuration>
17 <executions>
18 <execution>
19 <goals>
20 <goal>resources</goal>
21 <goal>compile</goal>
22 </goals>
23 </execution>
24 </executions>
25 </plugin>
T. Neidhart Introduction to Vaadin March 29, 2012 20 / 46
Widgetset Update - maven - optional
1 <plugin>
2 <!-- Used to automatically update the widgetset, can be omitted -->
3 <groupId>com.vaadin</groupId>
4 <artifactId>vaadin-maven-plugin</artifactId>
5 <version>1.0.2</version>
6 <executions>
7 <execution>
8 <configuration />
9 <goals>
10 <goal>update-widgetset</goal>
11 </goals>
12 </execution>
13 </executions>
14 </plugin>
T. Neidhart Introduction to Vaadin March 29, 2012 21 / 46
How do I find the available widgetsets myself?
1 Manifest-Version: 1.0
2 Vaadin-License-Title: Apache License 2.0
3 Implementation-Vendor: Henrik Paul
4 Implementation-Title: Refresher
5 Implementation-Version: 1.1.1
6 Vaadin-License-File: http://www.apache.org/licenses/LICENSE-2.0.html
7 Vaadin-Package-Version: 1
8 Vaadin-Widgetsets: com.github.wolfie.refresher.RefresherApplicationWid
9 getset
10 Class-Path:
T. Neidhart Introduction to Vaadin March 29, 2012 22 / 46
Back to our application
T. Neidhart Introduction to Vaadin March 29, 2012 23 / 46
UI Components
1 public class MainLayout extends VerticalLayout {
2
3 private TabSheet tabSheet;
4
5 public MainLayout() {
6 setMargin(true);
7 setSizeFull();
8
9 Label title = new Label("Satellite Tracker"));
10 title.addStyleName(Runo.LABEL_H1);
11 title.setSizeUndefined();
12 addComponent(title);
13 setComponentAlignment(title, Alignment.TOP_CENTER);
14
15 ..
16 }
17 }
T. Neidhart Introduction to Vaadin March 29, 2012 24 / 46
UI Components
Coding the UI feels very much like Swing
Use Layouts for composition of UI components◮ (Vertical|Horizontal)Layout◮ GridLayout◮ FormLayout◮ CssLayout◮ AbsoluteLayout◮ TabSheet◮ Accordion◮ Panel◮ (Vertical|Horizontal)SplitPanel
Event listener support
(modal) Sub-window support
T. Neidhart Introduction to Vaadin March 29, 2012 25 / 46
Event Listener
1 public class TrackingScreen extends HorizontalLayout {
2
3 public TrackingScreen() {
4 setMargin(true);
5 setSpacing(true);
6 setSizeFull();
7
8 Button compute = new Button("Track", new Button.ClickListener() {
9
10 public void buttonClick(ClickEvent event) {
11 getApplication().getMainWindow()
12 .showNotification("Button_clicked");
13 }
14 });
15
16 addComponent(compute);
17 ..
18 }
19 }
T. Neidhart Introduction to Vaadin March 29, 2012 26 / 46
Notification Example
T. Neidhart Introduction to Vaadin March 29, 2012 27 / 46
Sub-Windows
1 public class TrackingScreen extends HorizontalLayout {
2
3 public TrackingScreen() {
4 setMargin(true);
5 setSpacing(true);
6 setSizeFull();
7
8 Button compute = new Button("Track", new Button.ClickListener() {
9
10 public void buttonClick(ClickEvent event) {
11 Window w = new Window("My_window");
12 w.setContent(new MySubWindowContent());
13 w.setModal(true);
14 getApplication().getMainWindow()
15 .addWindow(w);
16 }
17 });
18
19 addComponent(compute);
20 ..
21 }
22 }
T. Neidhart Introduction to Vaadin March 29, 2012 28 / 46
Sub-Window example
T. Neidhart Introduction to Vaadin March 29, 2012 29 / 46
More UI Components
T. Neidhart Introduction to Vaadin March 29, 2012 30 / 46
Data Binding
Allows a view to access a model
View = any UI component
Model = can be anything
3 Level of Aggregation◮ Property◮ Item◮ Container
corresponding DataSources for each component◮ PropertyDataSource: TextField◮ ItemDataSource: Form◮ ContainerDataSource: Table
T. Neidhart Introduction to Vaadin March 29, 2012 31 / 46
Data Model4
4taken from Book of VaadinT. Neidhart Introduction to Vaadin March 29, 2012 32 / 46
Property
1 // Have a data model
2 ObjectProperty property = new ObjectProperty("Hello", String.class);
3
4 // Have a component that implements Viewer
5 Label viewer = new Label();
6
7 // Bind it to the data
8 viewer.setPropertyDataSource(property);
9
10 final TextField tf = new TextField("Name");
11
12 // Set the value
13 tf.setValue("The text field value");
14
15 // When the field value is edited by the user
16 tf.addListener(new Property.ValueChangeListener() {
17 public void valueChange(ValueChangeEvent event) {
18 // Get the value and cast it to proper type
19 String value = (String) tf.getValue();
20 getApplication().getMainWindow().showNotification("Value_changed");
21 }
22 });
T. Neidhart Introduction to Vaadin March 29, 2012 33 / 46
BeanItemContainer
1 // Create a container for such beans with
2 // strings as item IDs.
3 BeanContainer<String, Bean> beans =
4 new BeanContainer<String, Bean>(Bean.class);
5
6 // Use the name property as the item ID of the bean
7 beans.setBeanIdProperty("name");
8
9 // Add some beans to it
10 beans.addBean(new Bean("Mung bean", 1452.0));
11 beans.addBean(new Bean("Chickpea", 686.0));
12 beans.addBean(new Bean("Lentil", 1477.0));
13 beans.addBean(new Bean("Common bean", 129.0));
14 beans.addBean(new Bean("Soybean", 1866.0));
15
16 // Bind a table to it
17 Table table = new Table("Beans of All Sorts");
18 table.setContainerDataSource(beans);
T. Neidhart Introduction to Vaadin March 29, 2012 34 / 46
Containers
BeanItemContainer: for POJOs
IndexedContainer: for indexed data
LazyQueryContainer (addon): lazy loading from various data sources
HbnContainer (addon): for hibernate
Vaadin SQLContainer (addon): for SQL tables
Vaadin JPAContainer (commercial addon): for JPA entities
MockupContainer (addon): for mocking containers
CollectionContainer (addon): for Java Collections
T. Neidhart Introduction to Vaadin March 29, 2012 35 / 46
LazyQueryContainer example
1 entityContainer = new EntityContainer<Satellite>
2 (satService.getEntityManager(), true, false, false,
3 Satellite.class, 100, new Object[] {
4 "catalogNumber", "commonName"
5 }, new boolean[] {
6 true, true
7 });
8
9 entityContainer.addContainerProperty("catalogNumber", Long.class, 0, true, true);
10 entityContainer.addContainerProperty("type", String.class, "", true, true);
11 entityContainer.addContainerProperty("country", String.class, "", true, true);
12 entityContainer.addContainerProperty("launchDate", Date.class, null, true, true);
13 entityContainer.addContainerProperty("perigee", Double.class, 0.0d, true, true);
14 ..
15
16 // add a custom date formatter for the launch date
17 table.addGeneratedColumn("launchDate", new DateColumnGenerator());
18 table.setContainerDataSource(entityContainer);
T. Neidhart Introduction to Vaadin March 29, 2012 36 / 46
Themes
Based on CSS (Cascading Style Sheets)
Pre-defined themes◮ Reindeer◮ Runo◮ More theme addons
Custom themes
T. Neidhart Introduction to Vaadin March 29, 2012 37 / 46
Theme structure5
5taken from Book of VaadinT. Neidhart Introduction to Vaadin March 29, 2012 38 / 46
How does a theme css look like?
1 @import "../reindeer/styles.css";
2
3 .v-panel .v-panel-caption {
4 background: #80ff80; /* pale green */
5 }
6
7 .v-panel .v-panel-content {
8 background: yellow;
9 }
10
11 .v-panel .v-textfield {
12 background: #e0e0ff; /* pale blue */
13 }
14
15 .v-panel .v-button {
16 background: pink;
17 }
T. Neidhart Introduction to Vaadin March 29, 2012 39 / 46
Setting the theme to be used
1 public class MyApplication extends com.vaadin.Application {
2
3 public void init() {
4 // use the Runo theme
5 setTheme(Runo.THEME_NAME);
6 // or my own theme
7 setTheme("mytheme")
8 }
9 }
T. Neidhart Introduction to Vaadin March 29, 2012 40 / 46
Client-side widgets
To extend the existing widget collection
Requires a server-side component and a client-side widget (in GWT)
Allows custom css styles and other resources (e.g. images)
Warning: It can be tedious
Let’s see an example: a updating Time Label synchronized with the server
T. Neidhart Introduction to Vaadin March 29, 2012 41 / 46
Server-side component
1 /**
2 * The server-side part of the time label.
3 */
4 @ClientWidget(VTimeLabel.class)
5 public class TimeLabel extends Label {
6 private static final long serialVersionUID = 1L;
7
8 public TimeLabel(String text) {
9 super(text, Label.CONTENT_TEXT);
10 }
11
12 @Override
13 public void paintContent(PaintTarget target) throws PaintException {
14 target.addText(toString());
15 }
16 }
T. Neidhart Introduction to Vaadin March 29, 2012 42 / 46
Client-side widget
1 public class VTimeLabel extends VLabel {
2 private long date;
3
4 public VTimeLabel() {
5 date = -1;
6
7 ..
8 }
9
10 @Override
11 public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
12 if (client.updateComponent(this, uidl, true)) { return; }
13
14 final String mode = uidl.getStringAttribute("mode");
15 if (mode == null || "text".equals(mode)) {
16 String dateString = uidl.getChildString(0);
17 try {
18 date = Long.parseLong(dateString);
19 } catch (Exception e) {
20 }
21 }
22 }
23 }
T. Neidhart Introduction to Vaadin March 29, 2012 43 / 46
Advanced Topics
Multiple Windows (see Navigator addon)
URI Fragment and History (see Navigator addon)
Portlets
Debugging Vaadin Application
T. Neidhart Introduction to Vaadin March 29, 2012 44 / 46
Common Pitfalls
UI components / layouts have different defaults wrt sizes
Do not forget to setSizeUndefined for a component to be able to expand
Try to keep your layouts slim / use CssLayout if possible
Keep an eye on re-usable components - no real MVC architecture
Multi-window support is not enabled by default
Immediate / Non-immediate components
T. Neidhart Introduction to Vaadin March 29, 2012 45 / 46
Outlook - Vaadin 7
Drop support for IE 6 and 7◮ Great news!◮ Reduces DOM tree size/depth◮ Makes layouts faster
Simplify addon development
Core support for server-push (was an addon before)
Improve and add core navigation support (was an addon before)◮ View concept◮ Browser History◮ Multi-window support
T. Neidhart Introduction to Vaadin March 29, 2012 46 / 46