Supporting IE10 on a Rich Internet Application with Vaadin – the Vaadin 7 migration

Amidst the popularity of JavaScript-CSS frameworks like Bootstrap and Angular.js, Java developers like myself are still most comfortable with what we know – Java code. Vaadin provides a framework for Java developers to write rich internet applications that are highly interactive while usually not having to write a line of Javascript code. It builds on top of GWT, taking care of synchronizing server state with client state, which means that most of the time all you have to deal with is Java code — not Java code that’s compiled to JavaScript; real, server-side Java code.
At Trifork we especially like Vaadin because it integrates very nicely into the Liferay portal. This means you can write highly interactive portlets using Vaadin and deploy them to Liferay. My colleague David described this in detail last year in a different blog post.
The great migration
So we had two Vaadin 6-based portlets running for a client in a Liferay 6 portal. However, browsers change and with the release of Internet Explorer 10 we started to get complaints that using the portlets on this browser led to JavaScript errors. It was time to support IE10. Which meant a major upgrade from Vaadin 6 to Vaadin 7.1.
What changed?
Vaadin 7 brought a major rewrite of the Vaadin API: interfaces were changed, classes were moved, a new Connector class was introduced for custom widgets, client polling was changed and server push was introduced, and many other things. In general, the API feels more solid and mature now. Vaadin 7 makes more use of Java 5 features like enums and generics. In addition, widgetset compilation is now easier as under Maven everything is handled by the Vaadin plugin, including GWT compilation.
The migration is described briefly on the Vaadin website, but especially the details of upgrading a Vaadin portlet in Liferay are difficult find. I hope to provide in this blog post a comprehensive guide to upgrading a Vaadin portlet in Liferay from Vaadin 6 to Vaadin 7. This will be a very technical hands-on one, so hold on…!
The Vaadin application
In our case we had to make the following changes to the Vaadin applications:
- Change dependencies – Vaadin went from a single
vaadin.jarto separate JARs for the client side, the server side, and shared classes. So instead of a single dependencyvaadin-6.7.1.jar, we now have three dependencies:vaadin-server-7.1.6.jar,vaadin-shared-7.1.6.jar, andvaadin-shared-deps-1.0.2.jar. Additionally, Vaadin now includes the GWT classes in its own JARs, so we had to remove dependencies ongwt-useras well.
- Change
ApplicationtoUI– In Vaadin 6, theApplicationwas the entry point to your application, and you pointed the Vaadin servlet (in web.xml) or Vaadin portlet (in portlet.xml) to yourcom.vaadin.Applicationsub-class. In Vaadin 7, you instead supply a subclass of the newcom.vaadin.ui.UI. TheApplicationclass still exists behind the scenes, but it is rarely necessary to provide your own implementation. Also, just callsetContenton theUIto set its root component. There’s no more “main window” concept; the UI is the browser window. (As this article actually describes, Vaadin now supports multi-tabbed browsing, where each tab is linked to a separateUIinstance that maintains its own state; I haven’t tried this, but it sounds really cool. For now, you can stick with the old behavior (more or less) by annotating your UI class with@PreserveOnRefresh.)The
UI.init()method takes aVaadinRequestobject, and you should override it to build up your GUI.VaadinRequestis either aVaadinServletRequestor aVaadinPortletRequestdepending on your environment and it will provide direct access to theHttpServletRequestorPortletRequestthat caused the UI to be created, so you don’t need to implementHttpServletRequestListenerandPortletRequestListeneranymore to get to them. This is useful for authorization and personalization.We were overriding the
getSystemMessagesclass in ourApplicationin order to set a custom message for the Vaadin “Communication error” message. This is no longer the place to do this. Instead, we needed to subclass theVaadinServletandVaadinPortletfor this:public class MyVaadinServlet extends VaadinServlet { private static final long serialVersionUID = 1L; @Override public void servletInitialized() throws ServletException { super.servletInitialized(); getService().setSystemMessagesProvider(new MySystemMessagesProvider()); } } public class MySystemMessagesProvider implements SystemMessagesProvider { private static final long serialVersionUID = 1L; @Override public SystemMessages getSystemMessages(SystemMessagesInfo systemMessagesInfo) { CustomizedSystemMessages msgs = new CustomizedSystemMessages(); msgs.setCommunicationErrorCaption("..."); msgs.setCommunicationErrorMessage("..."); return msgs; } } - Change
web.xmland/orportlet.xml– The Vaadin servlet was moved fromcom.vaadin.terminal.gwt.server.ApplicationServlettocom.vaadin.server.VaadinServletandweb.xmlneeds to reflect this. Additionally, the servlet needs an init parameterUIpointing to your UI class (as described in the previous point). Theapplicationparameter can go.The Vaadin portlet was moved from
com.vaadin.terminal.gwt.server.ApplicationPortlet2tocom.vaadin.server.VaadinPortlet, so change this inportlet.xml. Additionally, as with the Vaadin servlet, the init parameterUIreferencing your UI class replaces theapplicationparameter.Our
portlet.xmlnow looks like this (remember we have a customVaadinPortlet; you will most likely just usecom.vaadin.server.VaadinPortletdirectly asportlet-class):<?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0"> <portlet> <portlet-name>my-portlet</portlet-name> <display-name>My portlet</display-name> <portlet-class>nl.trifork.vaadin.MyVaadinPortlet</portlet-class> <init-param> <name>UI</name> <value>nl.trifork.vaadin.MyUI</value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> <portlet-mode>edit</portlet-mode> <portlet-mode>help</portlet-mode> </supports> <portlet-info> <title>My portlet</title> </portlet-info> </portlet> </portlet-app> - Explicitly add a
VerticalLayouttoPanels – In Vaadin 6,Panels had an implicitVerticalLayout, and theaddComponentmethod onPanelcalled the corresponding method on theVerticalLayout. Now,Panelhas no moreaddComponentmethod. It just has a singlecontentcomponent that can be anything you want, including aVerticalLayout. One detail is that the defaultVerticalLayoutof the oldPanelhad a default 18px margin set, so to reproduce the old behavior in yourPanel, use the following code:VerticalLayout content = new VerticalLayout(); content.setMargin(true); Panel panel = new Panel(content); layout.addComponent(...); ...

- Replace
ProgressIndicatorwithProgressBar– there’s three things to keep in mind here:- the
ProgressIndicatorclass is deprecated and theProgressBarreplaces it - the progress bar doesn’t do polling for you anymore; this functionality has been moved to the
UIclass, so you need to callUI.setPollIntervalto have the client periodically request updates from the server andUI.setPollInterval(-1)to disable polling again once the server side thread is done and you’ve hidden the progress bar - since your server-side thread will be updating your progress bar (and possibly other parts of your GUI) while the client polling-initiated request might try to do the same, Vaadin provides a locking mechanism that you need to use to avoid synchronization errors. In Vaadin 6, this was implemented by using Java-level locking (with
synchronizedblocks) on theApplicationobject. In Vaadin 7, locking is done by calls toVaadinSession.lock()andVaadinSession.unlock(), like this:getUI().getSession().lock(); try { progressIndicator.setValue(newValue); } finally { getUI().getSession().unlock(); }The
try ... finallyis essential, or the session would be locked forever if anything went wrong in between thelock()andunlock()calls. See The API documentation for more details.
- the
- Replace
UriFragmentUtilitywithUI.addUriFragmentChangedListenerandPage.setFragment–
Back button and bookmarking support was previously handled by a kludgy component called UriFragmentUtility. Now, it’s a proper part of the Vaadin API. See The Book of Vaadin for more details. - Update import statements – Many classes were moved to a different package, but a simple “Organize imports” (Ctrl-Shift-O in Eclipse) will fix that.
- Fix deprecation warnings – this applies to
- constants that are now enums, e.g.
Notification.Type,Label.ContentMode - event handlers that are now more strongly typed, e.g. change
component.addListener(valueChangeListener)tocomponent.addValueChangeListener(valueChangeListener); this also removes ambiguity in classes that implemented multipleListenerinterfaces
- constants that are now enums, e.g.
Custom components and add-ons
Probably the most profound change in Vaadin 7 is the client-side architecture. In the old situation you had a server side component, and a client side component. The server-side component had a @ClientWidget annotation pointing to the client-side (GWT) implementation.
In Vaadin 7, a third Connector class is introduced which aims to separate the data transfer from the painting of the widget. The Connector is now annotated with the new @Connector annotation, and the @ClientWidget is no longer used.
Vaadin claims to ease migrating from the old situation by supplying a LegacyConnector, but unfortunately it’s far from trivial to migrate an old component. In some cases, a complete rewrite might be easier. Luckily, of the two add-ons we used, one (image strip) had been upgraded by the autor, and our modifications were easy to reapply afterwards; the other was an extension of Vaadin’s own twincolselect and was straightforward to upgrade. For more complicated situations, expect to invest a lot of time, or pay for Vaadin’s technical support.
Liferay integration
Liferay has for a while had good integration with Vaadin, running Vaadin portlets while having them look the same as other portlets.
Liferay ships with Vaadin JARs, themes, and widget sets, and we’ll need to upgrade these all to their respective Vaadin 7 versions. In addition, if you’re using add-ons, you’ll need the new Liferay Vaadin Control Panel to build a custom widget set containing the add-ons you need.
- Replace Vaadin JARs in Liferay – remove the existing
vaadin.jarinWEB-INF/liband copy the new Vaadin JARs and their dependencies in their place:vaadin-server-7.1.6.jar[ maven central ]vaadin-shared-7.1.6.jar[ maven central ]vaadin-shared-deps-1.0.2.jar[ maven central ]
as well as dependencies of these:
jsoup-1.6.3.jar[ maven central ]validation-api-1.0.0.GA.jar[ maven central ]validation-api-1.0.0.GA-sources.jar[ maven central ]
- Update the Vaadin resources in Liferay – download the following JARs and extract their VAADIN folders and their contents to Liferay’s
htmldirectory (e.g.cd html; unzip vaadin-server.jar 'VAADIN/*'):vaadin-server-7.1.6.jar[ maven central ]vaadin-client-compiled-7.1.6.jar[ maven central ]vaadin-themes-7.1.6.jar[ maven central ]
- Update portal-ext.properties – Add or update the following properties in your
portal-ext.properties. Note: it’s important that the widgetset be one that does not exist yet in your Liferay’shtml/VAADIN/widgetsetsdirectory; we’ll get to that in the next point when we compile a new widget set.# Path under which the VAADIN directory is located. # (/html is the default so it is not needed.) # vaadin.resources.path=/html # Portal-wide widget set vaadin.widgetset=com.vaadin.MyCustomWidgetSet # Theme to use vaadin.theme=reindeer
- Compile a new widget set – if you’re using add-ons then you will need to compile a Vaadin 7 widget set with those add-ons included. For this we install the new liferay-vaadin-plugin. You can download a prepackaged version from the Vaadin website (log-in required). However, this version doesn’t compile for IE10, which is what this whole thing was about. So we made a little code change. E-mail me if you want that version, or download the liferay-vaadin-plugin sources yourself and add the following lines in
src/main/java/com/arcusys/liferay/vaadinplugin/util/WidgetsetUtil.java, line 154 (below the line that readsprintStream.print("\n");:// Force ie10 inclusion printStream.print( "<inherits name=\"com.google.gwt.useragent.UserAgent\"/>\n"); printStream.print( "<extend-property name=\"user.agent\" values=\"ie10\"/>\n");Now deploy the plugin in the usual way by dropping the WAR file in Liferay’s deploy directory. If you log in to Liferay as an administrator now, you can select “Vaadin configuration” from the Control Panel:

The Vaadin configuration screen will open up:

Check that that the “Active Widget Set” is the one you entered in your
portal-ext.properties. If if still says com.vaadin.portal.gwt.PortalDefaultWidgetSet, or -worse-, com.vaadin.DefaultWidgetSet, checkportal-ext.propertiesand restart your Liferay application server.Now you’re almost ready to compile your widget set. First:
- Copy the add-on JARs to Vaadin’s
WEB-INF/lib. Remember the add-ons must be built with Vaadin-7 or this will not work. In other words, you will need to upgrade all of your add-ons! Unfortunately, not all add-ons have been upgraded yet. Not by far… - Put Vaadin’s client JARs in in the Liferay root under
WEB-INF/vaadin-client-jars(which you will need to create). The widget set compiler needs the following JARs to be present there:- vaadin-client-compiler-7.1.6 [ maven central ]
- vaadin-client-7.1.6.jar [ maven central ]
- vaadin-client-compiler-deps-1.0.2.jar [ maven central ]
Now click the “Re-scan” link, and select the add-ons you want included in your widget set. Finally, press the Compile Widget Set button, sit back, and wait. You can follow the progress in the Output Console. Your shiny new Vaadin 7 widget set will be in Liferay’s
html/VAADIN/widgetsets/com.vaadin.MyCustomWidgetSet(or whatever name you chose for it). - Copy the add-on JARs to Vaadin’s
- You’re done! Your Vaadin 7-based portlet should now be running under Liferay, with IE10 support. If you have a Liferay theme that styles your Vaadin widgets, or a custom Vaadin theme, you will most likely need to change the stylesheet. The Firebug extension on Firefox or the Web inspector on WebKit-based browsers will be of help here.
Automating it
We’ve scripted some of the update steps, including downloading and replacing the Vaadin JARs and resources in Liferay. Run it from your Tomcat home (i.e. the directory that contains bin, conf, webapps, etc.). Use at your own risk 😉 The source code is at the bottom of this blog post. You’ll need to have curl, unzip and basic Unix tools installed to run it. Tested on Mac OS X 10.6.8 and Ubuntu.
Finally
Please let us know: was this post useful? What problems are you running into upgrading to Vaadin 7? Any experiences you can share with other readers? We’d love to hear it. Just use the comment box below.
Links
- Migrating from Vaadin 6 to Vaadin 7 (vaadin.com)
- Migrating from Vaadin 7.0 to Vaadin 7.1 (vaadin.com)
- Upgrading to Vaadin 7 Step by Step (streamhead.com)
- Integrating Vaadin 7 with Liferay (vaadin.com)
- Vaadin Control Panel for Liferay (vaadin.com)
The Liferay upgrade script
#!/bin/bash
# Variables
CATALINA_HOME=`pwd`
PORTAL_EXT_PROPERTIES=$CATALINA_HOME/lib/portal-ext.properties
LIFERAY_WEBAPP=$CATALINA_HOME/webapps/ROOT
VAADIN_CLIENT=$LIFERAY_WEBAPP/WEB-INF/vaadin-clients-jars
TEMP=$CATALINA_HOME/temp
VAADIN_THEME=reindeer
# Check required commands are available
echo -n "curl: "
if ! which curl; then
echo curl not found. Please install curl and try again.
exit 1
fi
echo -n "unzip: "
if ! which unzip; then
echo unzip not found. Please install unzip and try again.
exit 1
fi
# Validations
if [ ! -d $CATALINA_HOME/webapps ]; then
echo $CATALINA_HOME/webapps does not exist. Script must be run from a Tomcat directory. Aborting.
exit 1
fi
echo "Tomcat directory: $CATALINA_HOME"
cd $CATALINA_HOME
if [ ! -d $LIFERAY_WEBAPP ]; then
echo $LIFERAY_WEBAPP not found.
exit 1
fi
if [ ! -f $LIFERAY_WEBAPP/WEB-INF/lib/portal-impl.jar ]; then
echo $LIFERAY_WEBAPP doesn\'t seem to be a Liferay installation. Aborting.
exit 1
fi
echo "Liferay web application: $LIFERAY_WEBAPP"
LIFERAY_VERSION=`unzip -c $LIFERAY_WEBAPP/WEB-INF/lib/portal-impl.jar META-INF/MANIFEST.MF|grep "Liferay-Portal-Version: "|awk -F": " '{ print $2 }'|sed -e 's/[^0-9\.]//g'`
if [ "x$LIFERAY_VERSION" == "x" ]; then
LIFERAY_VERSION="<unknown>"
fi
echo "Liferay version: $LIFERAY_VERSION"
echo "This will replace the Vaadin installation bundled with Liferay with a Vaadin 7.1.6 installation."
echo -n "Continue? [y/N] "
read RESP
if [ "x$RESP" != "xy" -a "x$RESP" != "xY" ]; then
exit 0
fi
if [ "x$LIFERAY_VERSION" != "x6.1.1" ]; then
echo -n "This script has only been tested with Liferay version 6.1.1. Found: \"${LIFERAY_VERSION}\". Continue? [y/N] "
read RESP
if [ "x$RESP" != "xy" -a "x$RESP" != "xY" ]; then
exit 0
fi
fi
# Remove existing Vaadin installation
echo
echo Removing old Vaadin JARs...
echo - `pwd`/$LIFERAY_WEBAPP/html/VAADIN
rm -rf $LIFERAY_WEBAPP/html/VAADIN
echo - `pwd`/$LIFERAY_WEBAPP/WEB-INF/lib/vaadin.jar
rm -f $LIFERAY_WEBAPP/WEB-INF/lib/vaadin.jar
# Download JARs in parallel from Maven's central repository
echo
echo "Downloading Vaadin JARs (this may take a few minutes)..."
mkdir -p $VAADIN_CLIENT
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-server/7.1.6/vaadin-server-7.1.6.jar >$LIFERAY_WEBAPP/WEB-INF/lib/vaadin-server.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-shared/7.1.6/vaadin-shared-7.1.6.jar >$LIFERAY_WEBAPP/WEB-INF/lib/vaadin-shared.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-shared-deps/1.0.2/vaadin-shared-deps-1.0.2.jar >$LIFERAY_WEBAPP/WEB-INF/lib/vaadin-shared-deps.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=org/jsoup/jsoup/1.6.3/jsoup-1.6.3.jar >$LIFERAY_WEBAPP/WEB-INF/lib/jsoup.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-themes/7.1.6/vaadin-themes-7.1.6.jar >$TEMP/vaadin-themes.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-client-compiled/7.1.6/vaadin-client-compiled-7.1.6.jar >$TEMP/vaadin-client-compiled.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-client-compiler/7.1.6/vaadin-client-compiler-7.1.6.jar >$VAADIN_CLIENT/vaadin-client-compiler.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-client/7.1.6/vaadin-client-7.1.6.jar >$VAADIN_CLIENT/vaadin-client.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=com/vaadin/vaadin-client-compiler-deps/1.0.2/vaadin-client-compiler-deps-1.0.2.jar >$VAADIN_CLIENT/vaadin-client-compiler-deps.jar &
curl -f -s -S http://search.maven.org/remotecontent?filepath=javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar >$LIFERAY_WEBAPP/WEB-INF/lib/validation-api.GA.jar
curl -f -s -S http://search.maven.org/remotecontent?filepath=javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA-sources.jar >$LIFERAY_WEBAPP/WEB-INF/lib/validation-api.GA-sources.jar
FAILED=0
for job in `jobs -p`; do
wait $job >/dev/null || let FAILED+=1
done
if [ $FAILED -gt 0 ]; then
echo Some downloads failed. Aborting.
exit 1
fi
echo Validating JARs...
unzip -tqq $LIFERAY_WEBAPP/WEB-INF/lib/vaadin-server.jar || exit 1
unzip -tqq $LIFERAY_WEBAPP/WEB-INF/lib/vaadin-shared.jar || exit 1
unzip -tqq $LIFERAY_WEBAPP/WEB-INF/lib/vaadin-shared-deps.jar || exit 1
unzip -tqq $LIFERAY_WEBAPP/WEB-INF/lib/jsoup.jar || exit 1
unzip -tqq $TEMP/vaadin-themes.jar || exit 1
unzip -tqq $TEMP/vaadin-client-compiled.jar || exit 1
unzip -tqq $VAADIN_CLIENT/vaadin-client-compiler.jar || exit 1
unzip -tqq $VAADIN_CLIENT/vaadin-client.jar || exit 1
unzip -tqq $VAADIN_CLIENT/vaadin-client-compiler-deps.jar || exit 1
unzip -tqq $LIFERAY_WEBAPP/WEB-INF/lib/validation-api.GA.jar || exit 1
unzip -tqq $LIFERAY_WEBAPP/WEB-INF/lib/validation-api.GA-sources.jar || exit 1
# Copy Vaadin resources to Liferay web application
echo
echo Copying Vaadin resources to Liferay web application...
pushd $LIFERAY_WEBAPP/html >/dev/null
unzip -q $LIFERAY_WEBAPP/WEB-INF/lib/vaadin-server.jar 'VAADIN/*'
unzip -q $TEMP/vaadin-themes.jar 'VAADIN/*'
unzip -q $TEMP/vaadin-client-compiled.jar 'VAADIN/*'
popd >/dev/null
# Add vaadin properties to portal-ext.properties (assuming it's in $PORTAL_EXT_PROPERTIES)
echo
echo Updating $PORTAL_EXT_PROPERTIES...
if [ ! -f $PORTAL_EXT_PROPERTIES ]; then
echo "$PORTAL_EXT_PROPERTIES not found. Please add the following properties manually:"
echo "# Path under which the VAADIN directory is located."
echo "# (/html is the default so it is not needed.)"
echo "# vaadin.resources.path=/html"
echo
echo "# Portal-wide widget set"
echo "vaadin.widgetset=com.vaadin.LiferayWidgetSet"
echo
echo "# Theme to use"
echo "vaadin.theme=$VAADIN_THEME"
elif ! grep -c vaadin.widgetset $PORTAL_EXT_PROPERTIES >/dev/null; then
cp $PORTAL_EXT_PROPERTIES ${PORTAL_EXT_PROPERTIES}.bak
cat >>$PORTAL_EXT_PROPERTIES <<EOF
# Path under which the VAADIN directory is located.
# (/html is the default so it is not needed.)
# vaadin.resources.path=/html
# Portal-wide widget set
vaadin.widgetset=com.vaadin.LiferayWidgetSet
# Theme to use
vaadin.theme=$VAADIN_THEME
EOF
echo "Updated $PORTAL_EXT_PROPERTIES."
else
echo "$PORTAL_EXT_PROPERTIES already contains vaadin.widgetset property. No changes made."
fi
echo
echo "Vaadin 7 upgrade complete! Please restart Tomcat."