Client and server-side in harmony

Modern Web with Vaadin 7 and JavaScript

TapioAali
vaadin

Vaadin’s Tapio Aali shows us how to get the most out of the Java-friendly web framework, with a bit of jQuery and JavaScript thrown in.

In an article orginally published in the August edition of
JAX Magazine, Vaadin’s Tapio Aali shows us how to get the most out
of the Java-friendly web framework, with a bit of jQuery and
JavaScript thrown in.

Vaadin is an open source Java-based framework for building
modern web applications. The core idea of the framework is that all
application logic is run in the server-side, while the client-side
is only responsible for sending the user actions to the server and
reacting to the responses it receives. Being based on GWT, both the
client and the server code can be written in pure Java.

The latest major version, Vaadin 7, was released in February.
The most prominent change from Vaadin 6 was the integration of GWT
to Vaadin, which meant better support for client-side widget
development and even gave the ability to create offline Vaadin
applications.

While the server-side programming model was kept solid in Vaadin
7, it was made much more extensible. Other changes included the
introduction of the new RPC and shared state system, redesigned
form-to-data binding and the support for Sass (Syntactically
Awesome Style Sheets). Another interesting new feature was the
ability to use any kind of JavaScript widgets directly with Vaadin
applications.

Vaadin 7.1 was released in June. It contained a bunch of new
features including support for Atmosphere-based asynchronous server
push and an integrated calendar component.  

Add-ons,
components, widgets and extensions 

Before diving more deeply into the extension model of Vaadin, a
few terms should probably be made clear. First, in the Vaadin
world, an add-on can be about anything that helps in the
development of Vaadin applications: UI components, toolkits,
plugins that integrate Vaadin with different development tools, or
application bases. Normally, these can be found from Vaadin
Directory [1].

Since Vaadin is a UI library, a component either refers
to something which display things to the user or something which
handles his/her input. In order to create a component, at least a
server-side class is required. If the component requires UI
functionality that cannot be created using other existing
components, a client-side widget is also needed. While the
server-side part is written in Java—or any language that is
supported by JVM—the client-side can be implemented using
JavaScript, too.

Finally, there are the extensions. It’s a new concept
introduced in Vaadin 7 that gives you the possibility to directly
modify both the server and client-side functionality, allowing the
alteration of the look and the behaviour of the existing
components.

From the
server to the client and back: component development in Vaadin
7

While the usage of pure Java and GWT has remained as the
foundation of the widget development in Vaadin 7, there has been
massive evolution under the hood. The basic idea has been to
separate the code of the widgets into three parts: the server-side
component, the client-side widget and the connector.

In Vaadin 6, the widget and the connector were the same thing.
Therefore there were normally only two classes: the client-side
widget and the server-side API for it. In addition to those, Vaadin
7 adds one extra required class: the connector that defines how the
sides are connected to each other.

Naturally, in most cases, some kind of communication is required
between the sides. Here is the biggest change: instead of the old
way of sending attributes, variables and events between a paint
target and an application connection, the communication is now done
by using a state object and remote procedure calls.

The state is a class that defines the variables that the
framework keeps in sync between the sides automatically, notifying
the client if the state is modified in the server-side. When
compared to the model used in Vaadin 6, this is a far more explicit
way of data sharing, which is archived by adding one extra
class.

While the state is always supposed to be in sync, remote
procedure calls can be used to communicate stateless events, such
as button clicks or other user interaction. Naturally, the RPCs can
be initiated from the either side.

Probably the easiest way to explore how you can create a
fully-fledged GWT-based Vaadin widget that uses both state and
RPCs, is to create a project using the Maven archetype
com.vaadin.vaadin-archetype-widget or with the Vaadin
Plug-in for Eclipse by adding a new Vaadin Widget to an existing
Vaadin 7 project.

Using a
JavaScript-based widget with Vaadin 7

In Vaadin 6, the only way to use a JavaScript-based component
was by creating a GWT wrapper for it and compiling it to the
widgetset. This isn’t required anymore—with Vaadin 7, you can use
any JavaScript component with little extra code.

As an example, I will create a component called
LinkWithQTip that displays a thumbnail of a link when
hovering over its text. It is based on a minimalistic jQuery plugin
called LinkQTip [2].

It is often easiest to start the development of a new component
by creating a state object which, as mentioned before, holds the
variables that are shared and kept in sync between the server and
the client.

In this example, I’ve reduced the variables to two that are most
certainly required for a link: the URL that it points to and the
link text. Because we’re creating a JavaScript-based component, the
state object is based on special class:
JavaScriptComponentState.

public class LinkWithQTipState extends JavaScriptComponentState {

public String url;

public String text;

}

The server-side component extends a class called
AbstractJavaScriptComponent. First it loads the
required JavaScript files: the jQuery library, the LinkQTip plugin
and the connector that joins it to the server-side. The loading is
done using
@JavaScript class
annotation.

The other parts of the server-side component don’t differ in any
way from a Vaadin component whose client code is written in GWT.
The server-side component provides an API that in this example
consists of one function that allows the user to change the text of
the link. See Listing 1.

Listing 1

@JavaScript({ "client/jquery-1.10.1.min.js",

"client/jquery.linkqtip.js",

"client/linkwithqtip_connector.js" })

public class LinkWithQTip extends AbstractJavaScriptComponent {

public LinkWithQTip(String url, String text) {

getState().url = url;

getState().text = text;

}

protected LinkWithQTipState getState() {

return (LinkWithQTipState) super.getState();

}

public void setText(String text) {

getState().text = text;

}

}

End

The
client-side: connecting jQuery widget to Vaadin

When a JavaScript-based
component is created, Vaadin searches for a JavaScript function
whose name comes from the package and the server-side class of the
component, replacing dots with underlines. This function is the
connector that receives the parameters from the state object and
applies them to the actual JavaScript widget. The initialization of
the connector can be compared to the
$(document).ready() function of jQuery since it is called when
the required surroundings of the component are ready to be
used.

The connector of LinkQTip is therefore a function called
com_vaadin_linkwithqtip_LinkWithQTip. It creates an
<a> element with the text and the url from the state object
and applies the linkQTip plugin to it before appending the element
to the DOM. It also applies a state change listener that changes
the link text if it is modified on the server-side. See
Listing 2
.

Listing 2

com_vaadin_linkwithqtip_LinkWithQTip = function() {

var aElement = $('<a/>', {

href: this.getState().url

});

var linkQTip = aElement.linkQTip();

$(this.getElement()).append(aElement);

this.onStateChange = function () {

aElement.html(this.getState().text);

};

};

End

Stateless
actions: Adding RPCs

Like all other components, JavaScript-based widgets can
also perform RPC in both directions. Naturally the ‘classical’
solution based on defining interfaces can also be used, but with JS
connectors, there is also a simplified mechanism
available.

Let’s say we want to be able to toggle the link preview from the
server-side. This is clearly a stateless action since the server
doesn’t know if the preview is visible or not; it just tells the
client-side to show the preview if it is hidden and vice versa.

The first thing we need to do is add a function called
toggle() to the connector. It redirects the call to the
actual plugin.

this.toggle = function() {

aElement.data('LinkQTip').toggle();

};

In order to do an RPC call from the server-side,
AbstractJavaScriptComponent.callFunction() is used.
Therefore we add a new API method that uses it to call the

toggle() function of the connector.

public void toggleQTip() {

callFunction("toggle");

}

Another nice feature we could have is the ability to know on the
server-side when a link preview is actually opened. The jQuery
plugin has a function called onLinkQTipShow that is set in
the initialization phase. Let’s make it call a new function
onLinkQTipOpened() of the connector.

var self = this;

var linkQTip = aElement.linkQTip({

onLinkQTipShow: self.onLinkQTipOpened

});

The actual implementation for the function is given on the
server-side, in the constructor of LinkWithQTip, as shown in

Listing 3.

Listing 3

addFunction("onLinkQTipOpened", new JavaScriptFunction() {

@Override

public void call(JSONArray arguments) throws JSONException {

for (LinkQTipOpenedListener listener : listeners) {

listener.qTipOpened();

}

}

});

In order to notify the users of the component, a listener
interface is used.

public interface LinkQTipOpenedListener extends Serializable {

public void qTipOpened();

}

Naturally also an API function for adding new listeners is
required.

public void addQTipOpenedListener(LinkQTipOpenedListener listener) {

listeners.add(listener);

}

That’s really all the code that is required to use a
JavaScript plugin with two-way RPC with Vaadin. All that is left to
do is apply the relevant styles so that the hovering thumbnail is
displayed correctly. Vaadin 7 introduced a new annotation,

@StyleSheet, that can be used to load CSS (or SCSS)
files from the WebContent/VAADIN folder. Therefore if the

jquery.linkqtip-styles.css file is copied there, it
can be loaded by adding one line to the LinkWithQTip
class.

@StyleSheet("vaadin://jquery.linkqtip-styles.css")

Now the add-on is ready to be added to the Vaadin
Directory. Since anyone is allowed to upload new add-ons, all you
need to do is to export the jar using either Maven or Vaadin
Plug-in for Eclipse. Then you can browse to the Authoring page,
fill in the required details and finally release your add-on for
everyone [3].

Some
final words

With this approach, the huge amount of already existing
jQuery-based plugins or any other JavaScript libraries can be used
with Vaadin applications really easily. Also, since no conversion
from Java to JavaScript is needed, the code can be modified and
deployed live without need for widgetset compilation.

Naturally, this has also some drawbacks. Trying to refer to any
GWT code from JavaScript is practically impossible. Also, since GWT
is no longer taking care of browser differences, it’s up to the
user or the used library to handle them.

Both the jQuery plugin and the Vaadin project are Apache
licensed and available in GitHub [2] [4]. You can find demos of
these projects via at my personal blog [5] [6].

Example
projects

  • https://vaadin.com/addon/webcam

  • https://vaadin.com/addon/dcharts-widget

  • https://vaadin.com/addon/ckeditor-wrapper-for-vaadin

  • https://vaadin.com/addon/aceeditor

  • https://vaadin.com/addon/googleanalyticstracker

References

[1]

https://vaadin.com/directory

[2]

https://github.com/tjkaal/LinkQTip

[3]

https://vaadin.com/directory#authoring

[4]

https://github.com/tjkaal/LinkWithQtip).

[5]

http://tapio.virtuallypreinstalled.com/jquery.linkqtip/jquery.linkqtip-example.html

[6]

http://tapio.virtuallypreinstalled.com/LinkQTip/.

 

 


Author
Comments
comments powered by Disqus