Running Hosted Mode in GWT Libraries (when using Maven)
Earlier this year, I wrote about Modularizing GWT Applications with GWT-Maven. Fast forward 8 months and I'm still working with GWT and using this same technique. However, this time I'm working with the Maven GWT Plugin from Codehaus. In my last post, I wrote:
The results of modularizing your application are beneficial (shared code) and detrimental (you have to mvn install
gwt-core whenever you make changes in shared classes). If you know of a way to configure the gwt-maven plugin to read sources from both gwt-core and gwt-webapp in hosted mode, I'd love to hear about it.
The good news is I found a solution for this, using the Builder Helper Maven Plugin. The GWT Maven Plugin's Productivity tip for multi-project setup has more information on how to configure this (note: we use IntelliJ and Eclipse on my project and did not need to configure this in a profile).
All was fine and dandy with this configuration until I wanted to be able to run hosted mode to develop/test everything in my library before including it in my main project. Luckily, you can still run mvn gwt:run on a JAR project. However, when you configure your pom.xml so sources are included in your JAR, you run into an issue: your *.java files will be copied to war/WEB-INF/classes and hosted mode will use these files as source rather than the ones you're editing in src/main/java.
To solve this, I changed my pom.xml to do two things:
- Only copy resources right before packaging (in the test phase).
- When packaging is complete, delete the *.java files from war/WEB-INF/classes (using Ant).
Below is the XML I used to make this possible. Please let me know if you have a way to simplify this configuration.
<plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.4.1</version> <executions> <execution> <phase>test</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.outputDirectory}</outputDirectory> <resources> <resource> <directory>src/main/java</directory> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <delete> <fileset dir="${project.build.outputDirectory}" includes="**/*.java"/> </delete> </tasks> </configuration> </execution> </executions> </plugin>
This solution seems to work pretty well. As far as developing your library in hosted mode, you'll need to configure two *.gwt.xml files, one that doesn't have an <entry-point> defined and one that does. Configure the one with the entry point as the <module> in your gwt-maven-plugin configuration.
As a side note, I found a few issues with the 1.1 version of the Maven GWT Archetype. Below are the steps I used to fix these issues and upgrade to GWT 1.7.0 (I realize 1.7.1 is out, but gwt-dev-1.7.1-mac.jar doesn't exist in Maven central).
First, create a new project by running the following from the command line:
mvn archetype:generate \ -DarchetypeGroupId=org.codehaus.mojo \ -DarchetypeArtifactId=gwt-maven-plugin \ -DarchetypeVersion=1.1 \ -DgroupId=com.yourcompany \ -DartifactId=gwt-project -Dversion=1.0-SNAPSHOT -B
After creating the project, you'll need to modify the pom.xml as follows:
- Change the gwt-maven-plugin's version to 1.1.
- Change the ${gwtVersion} property to 1.7.0.
- Add
<runTarget>Application.html</runTarget>
to the <configuration> element of the plugin. - Move Application.html and web.xml so they're under the "war" directory.
- Update Application.html to prepend the GWT module name in the <script> tag.
I hope these instructions help you create modular GWT projects with Maven. This setup is working great on my current project.