Vaadin add-ons and Maven
Introduction
One (of the many) thing I like about Vaadin, is its community of ‘add-ons’ to the Vaadin framework – what they call the Vaadin Directory. An ‘add-on’ is a community-contributed addition to the framework, and can be anything from for example a new client-side widget to a Lazy loading container for a data table. Something similar I would definitely like to see for Activiti!
Vaadin widgets are basically precompiled GWT widgets. GWT widgets on itself are Java classes, but the GWT compiler compiles them to Javascript that works accross all browser. So, when you want to use a certain add-on (that has new client-side visuals) in your Vaadin webapp, you will have to compile them yourself since you must include the new Javascript in your webapp.
If you are using the Vaadin Eclipse plugin, all is happy and fine. Just add the add-on jar to your project, and the plugin autodetects and compiles the new widgets. However, when your webapp is built using Maven, it’s not that simple. But throwing out Maven and manually copying all your dependency jars is not necessary at all. It’s 2011 after all.
The default way of doing the GWT compilation in Maven is, in my opinion, not efficient. So let me guide you through what setup works the best for me and how I tweaked the Maven pom.xml.
For the impatient-ones: check the source on github: https://github.com/jbarrez/vaadin-mvn-addon
Creating a new Vaadin webapp with Maven
This step is well-documented, just check the Vaadin wiki.
Short version: use following archetype:
mvn archetype:generate -DarchetypeGroupId=com.vaadin-DarchetypeArtifactId=vaadin-archetype-clean -DarchetypeVersion=6.5.6 -DgroupId=com.jorambarrez -DartifactId=vaadin-mvn-addon -Dversion=1.0 -Dpackaging=war
Add the add-on
In this example webapp, I’m going to use two cool Vaadin add-ons:
- Paperstack: a container that allows to display components as pages of a book
- Refresher: a client side component that polls the server for UI changes
Both add-ons have new client side widgets, so a run through the GWT compiler is definitely needed.
Tweak pom.xml
Open up the pom.xml. The archetype already generated all you need to work with custom add-ons. Look for commented sections, and just uncomment them. That’s all there is.
Create the webapp
The following Vaadin webapp shows a simple use of these two components. We’ll just display ‘Activiti’, with each character on a new page of the paperstack component. We also have a button, that will auto-flip through the pages using the Refresher component and a server-side thread:
public class MyVaadinApplication extends Application { private static final String DISPLAYED_WORD = "ACTIVITI"; private Window window; private Refresher refresher; private Button goButton; private PaperStack paperStack; @Override public void init() { window = new Window("My Vaadin Application"); setMainWindow(window); initGoButton(); initPaperStack(); } private void initGoButton() { goButton = new Button("Flip to the end"); window.addComponent(goButton); goButton.addListener(new ClickListener() { public void buttonClick(ClickEvent event) { goButton.setEnabled(false); startRefresher(); startPageFlipThread(); } }); } private void startRefresher() { refresher = new Refresher(); window.addComponent(refresher); refresher.setRefreshInterval(100L); } private void startPageFlipThread() { Thread thread = new Thread(new Runnable() { public void run() { goButton.setEnabled(false); int nrOfUpdates = DISPLAYED_WORD.length() - 1; while (nrOfUpdates >= 0) { paperStack.navigate(true); nrOfUpdates--; try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } } // Remove refresher when done (for performance) goButton.setEnabled(true); window.removeComponent(refresher); refresher = null; } }); thread.start(); } private void initPaperStack() { paperStack = new PaperStack(); window.addComponent(paperStack); for (int i=0; i<DISPLAYED_WORD.length(); i++) { VerticalLayout verticalLayout = new VerticalLayout(); verticalLayout.setSizeFull(); paperStack.addComponent(verticalLayout); // Quick-hack CSS since I'm to lazy to define a styles.css Label label = new Label("<div style=\"text-align:center;color:blue;font-weight:bold;font-size:100px;text-shadow: 5px 5px 0px #eee, 7px 7px 0px #707070;\">" + DISPLAYED_WORD.charAt(i) + "</div>", Label.CONTENT_XHTML); label.setWidth(100, Label.UNITS_PERCENTAGE); verticalLayout.addComponent(label); verticalLayout.setComponentAlignment(label, Alignment.MIDDLE_CENTER); } }
Tweak web.xml
To make Vaadin aware of the custom add-ons, add following lines to the Vaadin Application Servlet:
<init-param> <param-name>widgetset</param-name> <param-value>com.jorambarrez.CustomWidgetset</param-value> </init-param>
Also add a file ‘CustomWidgetset.gwt.xml’ in the package com.jorambarrez (matching whatever you have put in the web.xml). Just copy the following lines, and don’t worry about putting the add-on GWT descriptors there (which would be logical), the maven plugins will find them automatically in the add-on jars.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd"> <module> <inherits name="com.vaadin.terminal.gwt.DefaultWidgetSet" /> </module>
Run the webapp
Go to your project, and execute following command:
mvn clean package jetty:run
This starts up a Jetty webserver and deploys our webapp. You should now be able to play around with the webapp.
The problem
When running the previous command, you’ll should see the GWT compiler kicking in and compiling the custom widget. The problem is, the GWT compiler does take its time to do its magic (1.30 minutes on my machine, while simply starting Jetty takes 5 seconds).
I’m not going to sit and watch the GWT compiler sprinkling pixie dust over my add-ons every frick’n time when I want to run my app. Sure JRebel, could help out a lot here, but it should most definitely not be necessary to have my widgets compiled every time. After all, I’m not changing these add-ons at-all, right.
Tweaking pom.xml (The Sequel)
So we just learned that the default pom.xml generated by the Vaadin archetype isn’t friendly when it comes to add-ons. If you take a look at the configuration of the GWT compiler plugin, you’ll notice that the compiled widgets are added to the target folder, and not in the sources of your project:
<webappDirectory>${project.build.directory}/${project.build.finalName}/VAADIN/widgetsets</webappDirectory>
If we change that to our source folder:
<webappDirectory>src/main/webapp/VAADIN/widgetsets</webappDirectory>
the result of the GWT compilation is put in the source of my webapp. This also means I can just check them in together with the rest of my webapp.
The only thing we now need to do, is to make sure we don’t recompile the widgets on every run. I’ve chosen to simply put it in a profile as follows:
<profiles> <profile> <id>compile-widgetset</id> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>gwt-maven-plugin</artifactId> ....
Whenever I now add a new add-on to the project, I now run the following command:
mvn -Pcompile-widgetset clean compile
and it will compile all add-ons and put the result in my source folders. Running the Jetty webserver as shown above, will now just copy these sources to the war file and boot time is reduced to a minumum again (5 seconds here).
Source
The whole webapp as described in the above steps in fully available on GitHub: https://github.com/jbarrez/vaadin-mvn-addon
Conclusion
Using add-ons with Maven is not that hard, all of that is well-documented (as anything in Vaadin). However, the Maven archetype generates a Maven configuration that isn’t that efficient since it recompiles the add-on widgets on every run. The above steps show how to tweak the config to make it more suitable for real rapid development!
Any comments or improvements are welcome of course!
Reference: How to: Vaadin add-ons and Maven from our JCG partner Joram Barrez at the Small steps with big feet blog
Related Articles :
Hello
Are the steps any different for a Spring ROO + vaadin project using MAVEN. I did not use the archetypes to create my project and when i add the above changes to my pom.xml file, i get a “vaadin” unknown error given by Maven