ProTip: RAD with Vaadin7, JavaEE7, Glassfish4 embedded + maven

While JRebel is usually the tool of choice when it comes to fast redeploy cycles, its not always required to get your app redeployed really fast and keep development iterations short.

This example shows you how you can use the embedded-glassfish maven plugin to develop apps with Vaadin7 that redeploy in under a second.

The basic idea is to keep the generated war file respectively the exploded directory as small as possible.
We can achieve this by packaging all the required libraries with the application server itself and only including them as dependency with “provided” scope.
The only thing left is to fix some classloader issues that prevent loading of UIs and Themes.

So lets get started:

Here’s the pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>parent</artifactId>
        <groupId>com.dominikdorn.vaadin7ee</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>javaee7demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>javaee7demo</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- don't use version 4.0 of the plugin, its broken -->
        <embedded-glassfish.version>3.1.2.2</embedded-glassfish.version>
        <glassfish.version>4.0</glassfish.version>
        <vaadin.version>7.1.3</vaadin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-server</artifactId>
            <version>${vaadin.version}</version>
            <!-- add the vaadin dependencies to the glassfish embedded plugin deps to keep war size small -->
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client</artifactId>
            <version>${vaadin.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client-compiled</artifactId>
            <version>${vaadin.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-themes</artifactId>
            <version>${vaadin.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.glassfish.embedded</groupId>
                <artifactId>maven-embedded-glassfish-plugin</artifactId>
                <version>${embedded-glassfish.version}</version>
                <configuration>
                    <app>target/${project.artifactId}-${project.version}/</app>
                    <ports>
                        <http-listener>8282</http-listener>
                        <https-listener>8383</https-listener>
                    </ports>
                    <contextRoot>${project.artifactId}</contextRoot>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.glassfish.main.common</groupId>
                        <artifactId>simple-glassfish-api</artifactId>
                        <version>${glassfish.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.glassfish.main.extras</groupId>
                        <artifactId>glassfish-embedded-all</artifactId>
                        <version>${glassfish.version}</version>
                    </dependency>


                    <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-client-compiled</artifactId>
                    <version>${vaadin.version}</version>
                    </dependency>
                    <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-client</artifactId>
                    <version>${vaadin.version}</version>
                    </dependency>
                    <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-themes</artifactId>
                    <version>${vaadin.version}</version>
                    </dependency>
                    <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-client-compiler</artifactId>
                    <version>${vaadin.version}</version>
                    </dependency>

                    <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-server</artifactId>
                    <version>${vaadin.version}</version>
                    </dependency>
                    <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-client</artifactId>
                    <version>${vaadin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

Note that we’re declaring the vaadin dependencies in provided scoped and additionally as plugin-dependencies for the maven embedded-glassfish plugin.
Also note, that at the time of this post, there’s an version 4.0 of the embedded-glassfish maven plugin, but it was broken (at least on my computer) resulting in non working glassfish instances.

Next we’ll need to create a subclass of the Vaadin Servlet to prevent issues with the classloader not seeing classes of our webapp. Create one like this

package com.dominikdorn.vaadin7ee.demo.example_one;

import com.vaadin.server.VaadinServlet;

/**
 * Subclass of the VaadinServlet to fix issues with the Classloader 
 * not finding our UIs and Themes.
 * 
 * @author Dominik Dorn <dominik -at- dominikdorn -dot- com>
 *         http://dominikdorn.com/
 */
public class ClassloaderFixVaadinServlet extends VaadinServlet {
}

Then register it in your web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        version="3.0"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    
    <servlet>
        <servlet-name>Vaadin7Example1Servlet</servlet-name>
        <!-- we're using our own servlet to fix classloading issues -->
        <!--<servlet-class>com.vaadin.server.VaadinServlet</servlet-class>-->
        <servlet-class>com.dominikdorn.vaadin7ee.demo.example_one.ClassloaderFixVaadinServlet</servlet-class>
        <init-param>
            <param-name>UI</param-name>
            <param-value>com.dominikdorn.vaadin7ee.demo.example_one.ExampleOneUI</param-value>
        </init-param>
        <async-supported>true</async-supported>
    </servlet>

    <servlet-mapping>
        <servlet-name>Vaadin7Example1Servlet</servlet-name>
        <url-pattern>/example1/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Vaadin7Example1Servlet</servlet-name>
        <url-pattern>/VAADIN/*</url-pattern>
    </servlet-mapping>
    
</web-app>

That’s it!

Compile your app with

mvn clean package

, then start the server with

mvn embedded-glassfish:run.

When changing classes, either recompile with

mvn compile package
or better configure your IDE to deploy classes to target/${project.artifactId}-${project.version}/WEB-INF/classes.
Then simply press ENTER in the window where you started the embedded-glassfish instance.

This should get you redeploys in under one second. If you’re app grows large and deployment wait time rises, I highly recommend to use JRebel.

I also wrote a post on what to do if embedded glassfish is complaining about expired certificates. It might come handy.

Was this article useful? Do you have other tips to improve the developer productivity with Vaadin ? Share them in the comments below!

Leave a comment

Your email address will not be published. Required fields are marked *