Dynamic Reloading of Vaadin Applications With Maven and Eclipse, Pt. I

Developing Vaadin web applications is a lot of fun. One reason for this is that you very quickly get presentable results without having to bother with the intricacies of web protocols or the horrors of JavaScript coding. While developing Vaadin applications, you’ll typically want to see the results of your changes in a browser without being constantly delayed by a time-consuming redeployment process. There are commercial tools on the market, such as JRebel, which allow an instant reloading of changed classes in the JVM during runtime so that you don’t need to redeploy at all. But similar results can be achieved for free with only a few configuration settings.

We assume that your project setup consists of a Maven project together with the Eclipse IDE as your development environment.

In this article we’ll explore what configuration options you have to apply to your project’s pom.xml in order to enable a dynamic reloading of your Vaadin application in a running Jetty server during development. This article is split into two parts. In this first part, we’ll take a look at single module projects. The second part of the article will carry the concept over to Maven multi-module projects.

When you’re using Maven together with Eclipse you’ll get no automatic application reloading out of the box. Granted, you can deploy your application with WTP, with the option to republish your code changes to a running web container. But this is unsatisfying as you don’t get an instant reloading of these changes which gets worse when you have a multi-module project. Running a Jetty container with the Maven Jetty plugin that automatically reloads the application when you make changes to any of your classes would give you a lot more fluent coding experience.

So, what do we have to do to achieve that? Let’s first take a look at a standard Maven project for Vaadin without any sub-modules.

The Jetty container has the ability to scan the deployment directory of a web application for changes and to restart the application when changes have been detected. In a Maven project, the default deployment directory is located in target/${project.build.finalName}, e.g. target/my-webapp-1.0. We can have Jetty deploy this directory with the Maven goal jetty:run-exploded. If we configure Jetty to scan the deployment directory for changes, Jetty will restart the webapp each time the contents of this directory change. So, we only have to assure that our code changes are pushed to this deployment directory and we’re all set.

Given Maven’s default configuration, this will soon turn out to be very clumsy, though. The deployment directory is updated in Maven’s package phase, so we would have to run mvn package each time we made changes to our code. Running mvn compile won’t help us here, since this phase only compiles our classes to target/classes, which the Jetty plugin is unaware of. This is not exactly what the term dynamic reloading promises.

Therefore, our goal is to redirect all compilation results to WEB-INF/classes in our deployment directory. From there, Jetty is able to detect changes in the compiled classes and to restart the application if needed. We can achieve that by redefining the in our pom.xml. We’ll set the output directory to WEB-INF/classes in the deployment directory. As we deviate from Maven’s standard directory layout by that, we will put this change into an own development profile. Thus, we can use our adjustment only for development purposes and will not disturb all other standard build processes.

In order to do this, we have to use a configuration trick, since the output directory of a Maven build can not directly be altered in a profile. What we can do instead is define properties in a profile. With that, the necessary configuration is defined as follows.

<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/maven-v4_0_0.xsd">
...
	<properties>
		<!-- Default name of our target directory defined by -->
		<!-- our own property. -->
		<target.dir>target</target.dir>
	</properties>

	<profiles>
		<profile>
			<id>development</id>
			<properties>
				<target.dir>
					target/${project.build.finalName}/WEB-INF
				</target.dir>
			</properties>
		</profile>
	</profiles>

	<build>
		<!-- Redefine the output directory with the help of properties. -->
		<outputDirectory>${basedir}/${target.dir}/classes</outputDirectory>
	...
	</build>
	...
</project>

Here, we define a property named target.dir. This is set with target by default. In the section, we redirect the output directory to a directory ${basedir}/${target.dir}/classes. With the default value for target.dir, this evaluates to the standard Maven output directory target/classes.

Next we define a profile development where we redefine property target.dir with target/${project.build.finalName}/WEB-INF which evaluates to the classes directory of our deployment directory.

With that, we can compile to the deployment directory by selecting the development profile:

$ mvn compile -P development

The next step necessary is to make Jetty scan the deployment directory for changes. This can be achieved with the Maven Jetty Plugin’s scanIntervalSeconds configuration option. We set this interval to one second (any other value greater than zero can be chosen as well, of course):

<build>
	<plugins>

		<plugin>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>maven-jetty-plugin</artifactId>
			<version>6.1.24</version>
			<configuration>
				<stopPort>9966</stopPort>
				<stopKey>stopJetty</stopKey>
				<!-- Redeploy every x seconds if changes are detected, 0 for no automatic
					redeployment -->
				<scanIntervalSeconds>1</scanIntervalSeconds>

				<!-- Use the following option if you want to initiate the restart manually -->
				<!-- by pressing Enter in Jetty's console window. -->
				<!-- <reload>manual</reload> -->

				<!-- make sure Jetty also finds the widgetset -->
				<webAppConfig>
					<contextPath>/Hello_Maven</contextPath>
					<baseResource implementation="org.mortbay.resource.ResourceCollection">
						<resourcesAsCSV>
						src/main/webapp,${project.build.directory}/${project.build.finalName}
						</resourcesAsCSV>
					</baseResource>
				</webAppConfig>
			</configuration>
		</plugin>
	</plugins>
</build>

You can now make use of Jetty’s dynamic reloading with the following steps

  1. Start the webapp in one console with mvn jetty:run-exploded. This will build the project and start the Jetty container. Jetty will then deploy the exploded deployment directory. Running mvn jetty:run will not work as this command deploys the generated WAR file which would defeat our whole idea. [Edit: I stand corrected on this. You can alternatively use mvn jetty:run -Pdevelopment to achieve the same results. Note that with jetty:run activating the development profile is necessary.]
  2. Make changes to your code.
  3. Run mvn compile -P development in a different console without stopping the running Jetty container.

You’ll see that Jetty detects the changed classes and restarts the application.

Enter Eclipse

With these preparations accomplished, it is now easy to include Eclipse in our scheme. If you’re using the Eclipse m2e plugin, you should do the following steps to enable dynamic reloading of your Vaadin application in Eclipse.

First, you’ll have to import your project as a Maven project using the development profile. In Eclipse, select File -> Import… -> Existing Maven Projects and select your Maven project. In the project selection dialog, it is important that you add our development profile in the Advanced section. If you forget to import your project using this profile, you will not get the desired results.

The effect of importing with the development profile is that Eclipse’s default output folder is set to the deployment directory as well. You can check this when you select the properties of your project in Eclipse and open the Java Build Path panel. The output folder is shown on the Source tab.

There’s one more thing to do to get an automatic reloading of your application. Start the Jetty container either on a console with

$ mvn jetty:run-exploded

or create an Eclipse run configuration as shown in the figure below and start the server with this configuration.

Maven Run Configuration for running the Jetty plugin

Once the Jetty server is running you can start editing your classes. You’ll see that each time you’re saving your Java files, the Jetty server will restart the application. Reloading the browser window pointing to your application will show you the results of your code changes. You don’t even have to run mvn compile or similar after applying changes to your code. Just saving the edited files will update the running application.

Eclipse Without m2e

You don’t necessarily have to use an Eclipse Maven plugin for this to work. If you’re using an Eclipse installation without Maven support, just make sure that the output folder of your project points to the WEB-INF/classes folder in the deployment directory. Start Jetty in a console with mvn jetty:run-exploded and let the server run in the background.

Maven Multi-Module Projects

You can have a dynamic reloading of your application even when you’re working with a Maven multi-module project. The second part of this article will explore how the project configuration has to be designed in this case.

Example Project

You find a working example for this article on GitHub in project DynamicReloadingWithMavenAndEclipse.

Appendix

For reference, find below the full Maven pom.xml for the example described in this article.

<?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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>de.oio.vaadin.blog</groupId>
	<artifactId>HelloMaven</artifactId>
	<packaging>war</packaging>
	<version>1.0</version>
	<name>Vaadin Web Application</name>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<vaadin.version>7.0.0.alpha3</vaadin.version>
		<gwt.version>2.3.0</gwt.version>
		<gwt.plugin.version>2.2.0</gwt.plugin.version>
		<target.dir>target</target.dir>
	</properties>

	<profiles>
		<profile>
			<id>development</id>
			<properties>
				<target.dir>target/${project.build.finalName}/WEB-INF</target.dir>
			</properties>
		</profile>
	</profiles>

	<build>
		<outputDirectory>${basedir}/${target.dir}/classes</outputDirectory>

		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>6.1.24</version>
				<configuration>
					<stopPort>9966</stopPort>
					<stopKey>stopJetty</stopKey>
					<!-- Redeploy every x seconds if changes are detected, 0 for no automatic
						redeployment -->
					<scanIntervalSeconds>1</scanIntervalSeconds>
					<!-- Use the following option if you want to initiate the restart manually -->
					<!-- by pressing Enter in Jetty's console window. -->
					<!-- <reload>manual</reload> -->

					<!-- make sure Jetty also finds the widgetset -->
					<webAppConfig>
						<contextPath>/HelloMaven</contextPath>
						<baseResource implementation="org.mortbay.resource.ResourceCollection">
							<resourcesAsCSV>
							src/main/webapp,${project.build.directory}/${project.build.finalName}
							</resourcesAsCSV>
						</baseResource>
					</webAppConfig>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>com.vaadin</groupId>
			<artifactId>vaadin</artifactId>
			<version>${vaadin.version}</version>
		</dependency>
	</dependencies>

</project>
Short URL for this post: http://blog.oio.de/TvpD4
This entry was posted in Build, config and deploy, Did you know?, Java Web Frameworks and tagged , , , , , . Bookmark the permalink.

4 Responses to Dynamic Reloading of Vaadin Applications With Maven and Eclipse, Pt. I

  1. Pingback: RE: ?restartApplication issue - Forum - vaadin.com

  2. Pingback: Dynamic Reloading of Vaadin Multi-Module Applications With Maven and Eclipse, Pt. II | techscouting through the java news

  3. Pingback: RE: Vaadin 7, Gradle, Jetty, Eclipse - Forum - vaadin.com

  4. piotr says:

    Great tutorial. It saved me a lot of time. Thanks

Leave a Reply