Workshop on how to build Vaadin Add-ons. We introduce two styles of building Vaadin add-on components for Vaadin: integrating an existing GWT widget (DatePicker), and integrating an existing JavaScript library (three.js).
8. What we do here
Eclipse Kepler - eclipse.org
Vaadin plugin for Eclipse - vaadin.com/eclipse
Jetty Server - run-Jetty-run plugin
New Vaadin project - testing and development
DatePicker - simple GWT or JavaScript add-on
... or something else.
13. Client-server UI components
“UI Component”
• Button, Table, Tree, ...
• Server-side data
• Full Java API
HTTP(S)
“Widget”
• Client-side peer for the
component
• Runs on JavaScript
Java
Java
• Compiled with JDK
• Google Web Toolkit
14. This is add-on
HTTP(S)
“UI Component”
• Button, Table, Tree, ...
• Server-side data
• Full Java API
Java
• Compiled with JDK
“Widget”
• Client-side peer for the
component
• Runs on JavaScript
Java
Add-on JAR file
• Google Web Toolkit
19. Webcam
Webcam allows you to capture
images from the web camera.
webcam.addCaptureSucceededListener(new CaptureSucceededListener() {
@Override
public void captureSucceeded(CaptureSucceededEvent event) {
Image img = new Image("Captured image", new FileResource(
targetFile));
img.setWidth("200px");
layout.addComponent(img);
}
});
20. ReCaptcha
A wrapper component for ReCaptcha.
Recaptcha4j used for the server side
validation of the captcha.
ReCaptcha captcha = new ReCaptcha(
MY_PRIVATE_KEY,
MY_PUBLIC_KEY,
new ReCaptchaOptions() {{
theme = "white";
}}
);
layout.addComponent(captcha);
21. GoogleMaps
Enables Google Maps support in Vaadin
7 projects.
GoogleMap googleMap = new GoogleMap(new LatLon(60.440963, 22.25122),
10.0, apiKey);
googleMap.setSizeFull();
googleMap.addMarker("DRAGGABLE: Paavo Nurmi Stadion", new LatLon(
60.442423, 22.26044), true, "VAADIN/1377279006_stadium.png");
kakolaMarker = googleMap.addMarker("DRAGGABLE: Kakolan vankila",
new LatLon(60.44291, 22.242415), true, null);
googleMap.addMarker("NOT DRAGGABLE: Iso-Heikkilä", new LatLon(
60.450403, 22.230399), false, null);
googleMap.setMinZoom(4.0);
googleMap.setMaxZoom(16.0);
22. Spring stuff
This add-on contains classes
that add some missing "glue"
between Vaadin and Spring.
<!-- Activate Spring annotation support -->
<context:annotation-config/>
<!-- Example of an application-specific bean which gets
created and autowired when the
application starts and destroyed when the application stops -->
<bean class="com.example.MyApplicationBean"/>
<!-- This makse the Vaadin application instance itself available in,
and autowired by, this context -->
<bean class="org.dellroad.stuff.vaadin.ContextApplicationFactoryBean"
p:autowire="true"/>
23. OAuth Popup
Authorize the Vaadin application to do things on the
users' behalf on various services such as Facebook,
Twitter, etc.
OAuthPopupButton ob = new TwitterButton(TW_KEY, TW_SECRET);
ob.addOAuthListener(new OAuthListener() {
@Override
public void authSuccessful(String accessToken,
String accessTokenSecret) {
Notification.show("Authorized");
// TODO: do something with the access token
}
@Override
public void authDenied(String reason) {
Notification.show("Authorization denied");
}
});
24. Scaladin
Scaladin makes easier to use Vaadin Framework with
Scala programming language.
class ScaladinExampleApplication extends
Application("Scaladin Example") {
override val main = new VerticalLayout {
add(new Button {
caption = "Click me!"
icon = new ThemeResource("../runo/icons/16/globe.png")
clickListeners += { mainWindow.showNotification("Hello World!")
})
}
}
25. LeapGestures
Basic Leapmotion gestures API for Vaadin.
LeapGestures g = LeapGestures.extend(this);
g.addSwipeDownListener(new SwipeDownListener() {
@Override
public void onSwipeDown(SwipeDownArgs args) {
layout.addComponent(new Label("swipe down"));
}
});
26. Widgets - the most common add-ons
Extensions - invisible functionality
Data - integration to the backend
Tools - additional tools and components
Misc - something else
39. Tools for add-on development
Browser
developer
tools
Java
IDE
Java EE
Server
Google Chrome
Firefox
Safari
NetBeans 7.4 (+ Vaadin plugin)
Eclipse Kepler (+Vaadin and Jetty plugin)
Tomcat 7
Jetty 8
43. DatePicker component
“The goal of this exercise is to practice the usage of
RPC and shared state. In this exercise, we will take
an existing GWT widget and make it compatible
with server-side Vaadin applications.”
com.google.gwt.user.datepicker.client. DatePicker
45. 1. Create a new Vaadin7 project called DatePicker
2. Create a new Vaadin 7 widget using the ”fullfledged”
template, call your widget DatePickerComponent
3. In the server-side component, override getState to
return a DatePickerState
4. Remove the client RPC interface
5. In the server RPC interface, define one method,
dateChanged(Date date)
49. SuperDevMode runtime
SuperDevMode code server for MyAddonProject.launch
Visit http://localhost:9876/
Start
code server
Debug as » Debug on server
Visit http://localhost:8080/MyAddOnProject?debug
Run
application in
SuperDevMode
50. 6. The state object should have a field for the selected date
7. Set a default value for the date
8. Implement the server RPC in the server-side component.The
dateChanged method should update the selected date in state
9. The connector should create a DatePicker widget
10. The connector should register itself as a
ValueChangeHandler<Date> to the widget, in order to listen to
the selected date
11. State changes should be passed to the widget
53. GWT widget theme
to use the
default
GWT theme
Include the following to the .gwt.xml
<inherits name="com.google.gwt.user.theme.standard.Standard" />
54. JSNI classes
Java to JavaScript:
public static native void alert(String msg) /*-{
$wnd.alert(msg);
}-*/;
JavaScript to Java:
// Call instance method instanceFoo() on x
x.@org.vaadin.se.myaddon.MyJSNI::myMethod(Ljava/lang/String;)(s);
61. Server code
@JavaScript({"three.min.js",
"cube_integration.js"})
public class Cube
extends AbstractJavaScriptComponent {
!
!
!
!
!
!
!
!
public Cube() {
! setWidth("200px");
! setHeight("200px");
}
!
!
!
!
!
!
!
!
!
!
!
!
!
!
public CubeState getState() {
! return (CubeState) super.getState();
}
public boolean isAnimating() {
! return getState().animate;
}
! ! public void stop() {
! ! ! getState().animate = false;
! ! }
!
!
!
!
! public void start() {
! ! getState().animate = true;!! !
! }
!
public class CubeState
extends JavaScriptComponentState {
! public boolean animate = false;
}
62. Client integration JavaScript
window.com_example_threejs_Cube = function() {
var element = this.getElement();
// This is Vaadin callback on state changes
this.onStateChange = function() {
! if (this.getState().animate) {
! this.start();
!
! else {
}
! this.stop();
!
!
}
}
// React to resize events
this.addResizeListener(this.getElement(), this.onResize);
// ...
}
63. JavaScript not found
Could not initialize JavaScriptConnector because no
JavaScript init function was found. Make sure one of
these functions are defined:
• com_example_threejsaddon_Cube
• com_vaadin_ui_AbstractJavaScriptComponent
• com_vaadin_ui_AbstractComponent
• com_vaadin_server_AbstractClientConnector
66. Add-on versions follow semver.org
New add-on version (start with 1.0.0)
Major
when you make incompatible API changes
when you add functionality
Minor
Patch
Do not break backward compatibility
when you make backwards-compatible bug fixes
No new features
74. Publish add-ons in Directory
Good
description
Links and
documentation
Demo is
worth
a thousand
words
Be descriptive and think of SEO.
Make screenshots and screencasts.
Example code, issue tracking, discussion
Publish sources (GitHub is good)
Show how it works. Remember code samples.
Works as test and validation for your add-on
76. Add-on ideas
Start from
yourself
There is aready one user for something that you need.
Common patterns and needs.
Combine client and server
Generalize
Reuse existing JavaScript and GWT widgets.
Abstract functionality: Java API is your product
Fix bugs
Maintain
Follow discussion