GWT + Maven + GPE gotchas

Lately, the support of Maven for the Google Plugin for Eclipse (GPE) has been enhanced. Since GPE 2.1, you can File | Import… | Existing maven project, point it to your POM, and everything should just work. You can start the development mode without running any additional goals like ‘mvn eclipse:eclipse’ anymore. Or at least this is what I ‘d like to see happening while trying out the new GPE, but…

GEP fails to locate module descriptor in “src/main/resources”
Maven2 philosophy dictates that all non-java resources that should be available on the classpath should reside on “src/main/resources”. While placing your gwt.xml file under “src/main/resources” will work with ‘mvn gwt:run’, GPE will fail to discover it even if the <module/> configuration property of the gwt-maven-plugin has been specified. No matter what, running your app in Eclipse (Run | Run As | Web Applicaiton) will result in the following error:

Missing required argument 'module[s]'
Google Web Toolkit 2.3.0
...
module[s]        Specifies the name(s) of the module(s) to host

This one turned out to be a known GPE issue (Issue 3759) and the recommended workaround is to place your GWT module descriptor in “src/main/java”.

Contents of “src/main/webapp” are not getting copied to the hostedWebapp *Solved*
While running the development mode server the resources of “src/main/webapp” are expected to be found under the hostedWebapp directory (i.e. target/${project.build.finalName}) and using the copyWebapp configuration property should have copied them. Unfortunately, this is still not working for me and I ‘ve experienced errors like FileNotFoundExceptions and 404 errors despite using the AppEngineLauncher or the internal Jetty server.
To get around this, I have to run ‘mvn war:exploded‘ before starting the development mode. Read also this FAQ entry.

Update: As commented by David Chandler, in order for the GPE to copy the “src/main/webapp” to the hostedWebapp directory, you need to have the m2extras’ “Maven Integration for WTP” plugin installed as well as m2eclipse. Here is the m2extras update site: http://m2eclipse.sonatype.org/sites/m2e-extras

No App Engine SDKs found on the build path
This is a minor but annoying one. GPE will search your POM’s dependencies for a GAE SDK and if it doesn’t find one (let’s say because you don’t use GAE), Eclipse will report the following problem:

Google App Engine Problem (1 item)
 > The project 'xxx' does not have any App Engine SDKs on its build path

To get rid of it you can either go to Project | Properties | Google | App Engine and deselect ‘Use Google App Engine’ or consider adding a dependency for GAE SDK in your POM

<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-api-1.0-sdk</artifactId>
  <version>${gae.version}</version>
</dependency>
Posted in GWT | Tagged , , , , | 8 Comments

Efficient GWT development: Swap your gwt.xml with maven.

A module in GWT bundles together all the configuration settings that your GWT project needs. A common practice is to have a “development” module along with your “production” module in order to toggle the configuration of your application.

There are many scenarios where this kind of setup would become handy.
For example, the production module for a possible project, name it Example.gwt.xml could be like this:

<!DOCTYPE module PUBLIC "//gwt-module/" "http://google-web-toolkit.googlecode.com/svn/tags/2.1.1/distro-source/core/src/gwt-module.dtd">
<module rename-to='example'>
    <!-- Inherit necessary modules etc -->
    <inherits name='com.google.gwt.user.User'/>

    <!-- (other configuration) -->
    
    <!-- [1] Create permutations for every supported browser -->
    <set-property name="user.agent" value="ie6,ie8,gecko1_8,safari,opera" />
	
    <!-- [2] Create permutations for many different locales -->
    <extend-property name="locale" values="el_GR"/>
    <extend-property name="locale" values="en_US"/>
    <set-property name="locale" value="el_GR,en_US"/>

    <!-- [3] Turn logging off -->
    <inherits name="com.allen_sauer.gwt.log.gwt-log-OFF" />

    <!-- [4] Use shorter obfuscated class names. -->
    <set-configuration-property name="CssResource.obfuscationPrefix" value="empty" />

    <!-- [5] Set custom deferred binding rules -->
    <replace-with class="j.gonian.example.RealGeocodeService">
        <when-type-is class="j.gonian.example.GeocodeService" />
    </replace-with>
</module>

Now, the development module ExampleDevelopment.gwt.xml could be as follows (points 1-5 show how the production configuration is respectively overridden):

<!DOCTYPE module PUBLIC "//gwt-module/" "http://google-web-toolkit.googlecode.com/svn/tags/2.1.1/distro-source/core/src/gwt-module.dtd">
<module rename-to='example'>
    <!-- Make sure to inherit from the "production" module -->
    <inherits name='j.gonian.example.Example'/>
    
    <!-- [1] Reduce the compilation time by creating permutations for specific browsers -->
    <set-property name="user.agent" value="ie6,ie8,gecko1_8" />
	
    <!-- [2] Reduce the compilation time by creating permutations for a single locale -->
    <set-property name="locale" value="en_US"/>

    <!-- [3] Turn logging on -->
    <extend-property name="log_level" values="INFO,DEBUG,TRACE" />

    <!-- [4] Ease application style development -->
    <!-- turn off data urls-->
    <set-property name="ClientBundle.enableInlining" value="false" />
    <!-- turn off merging of CSS rules -->
    <set-configuration-property name="CssResource.mergeEnabled" value="false" />
    <!-- produce human-readable CSS -->
    <set-configuration-property name="CssResource.style" value="pretty" /> 

    <!-- [5] Set custom deferred binding rules -->
    <replace-with class="j.gonian.example.MockGeocodeService">
        <when-type-is class="j.gonian.example.GeocodeService" />
    </replace-with>
</module>

Ok, now we need an easy way to swap our gwt.xml files based on our working environment. This can be easily achieved with Maven by using build profiles. Although, I believe it should be trivial to achieve a similar setup with ant as well.

So, lets configure our POM to use the development configuration by default (for everyday development) and add a profile to activate the production configuration in order use it e.g. on the Continuous Integration server or when we need to deploy to a staging environment. To achieve this we modify the gwt-maven-plugin section:

...
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>gwt-maven-plugin</artifactId>
    <configuration>
        <!-- By default, load the 'development' module -->
        <module>j.gonian.example.ExampleDevelopment</module>
        <!-- (optionally) change GWT JavaScript compiler output style -->
        <style>PRETTY</style>
    </configuration>
</plugin>
...
<profiles>
    <profile>
    <id>production</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>gwt-maven-plugin</artifactId>
                <configuration>
                    <!-- Load the 'production' module -->
                    <module>j.gonian.example.Example</module>
                    <style>OBF</style>
                </configuration>
            </plugin>
        </plugins>
    </build>
    </profile>
</profiles>

We are good to go!
mvn gwt:run fires up dev mode with development settings (pretty CSS etc)
mvn package packages the compiled JS with development settings (logs enabled, pretty JS etc)
mvn gwt:run -Pproduction fires up dev mode with production settings (obfuscated CSS etc)
mvn package -Pproduction packages the compiled JS with production settings (logs disabled, obfuscated JS etc)


Following the concept presented above you can create as many gwt.xml module configurations and as many profiles suit your needs.


cheers,

Posted in GWT, Java | Tagged , | 7 Comments

Maven Checkstyle and Eclipse

Have you ever tried to setup your multi-module Maven project with a shared checkstyle configuration and connect it to your eclipse IDE? If you have, I am sure you ‘d agree that it was not as trivial as it should be…

Recently, I had the opportunity to help with the maven-ization of gwt-platform. It used to be a single ant-build project with Checkstyle setup. Also, this setup was working fine in Eclipse without particular manual effort. With the migration to maven the project was split into many sub-modules and a single Checkstyle configuration consisting of: config, header and suppressions files. If this is what you are searching for then stay tuned.

The first step is to share Checkstyle configuration among the sub-modules. You should create a separate host project for the shared Checkstyle configuration. Then you add it as a dependency to maven-checkstyle-plugin e.g.

<plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <version>2.6</version>
      <configuration>
            <configLocation>/checkstyle.xml</configLocation>
            <headerLocation>/header.txt</headerLocation>
            <suppressionsLocation>/suppressions.xml</suppressionsLocation>
      </configuration>
      <dependencies>
            <dependency>
                  <groupId>${project.groupId}</groupId>
                  <artifactId>build-tools</artifactId>
                  <version>${project.version}</version>
            </dependency>
      </dependencies>
</plugin>

This technique is better explained here. Maven-wise your Checkstyle setup is ready. You may run mvn checkstyle:checkstyle to perform a Checkstyle analysis, and generate a report on violations.

The second step is to let Eclipse know about your Checkstyle configuration. This will require to setup maven-eclipse-plugin e.g.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-eclipse-plugin</artifactId>
    <version>2.8</version>
    <configuration>
        <additionalBuildcommands>
            <buildcommand>net.sf.eclipsecs.core.CheckstyleBuilder</buildcommand>
        </additionalBuildcommands>
        <additionalProjectnatures>
            <projectnature>net.sf.eclipsecs.core.CheckstyleNature</projectnature>
        </additionalProjectnatures>
        <additionalConfig>
            <file>
                <name>.checkstyle</name>
                <location>/eclipse-checkstyle.xml</location>
            </file>
        </additionalConfig>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>build-tools</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>
</plugin>

Notice the eclipse-checkstyle.xml. This file is located in build-tools as well and contains the information needed by Eclipse to setup Checkstyle. It should look like this:

<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
    <local-check-config name="[CS_CONFIG_NAME]" location="target/checkstyle-checker.xml" type="project" description="">
        <additional-data name="protect-config-file" value="false"/>
    </local-check-config>
    <fileset name="all" enabled="true" check-config-name="[CS_CONFIG_NAME]" local="true">
        <file-match-pattern match-pattern="^src[/\\]." include-pattern="true"/>
    </fileset>
</fileset-config>

In the above snippet, you might noticed that Eclipse will look for the target/checkstyle-checker.xml file which is created by maven-checkstyle-plugin when checkstyle goal runs. For that reason, checkstyle goal should run before the execution of eclipse:eclipse. Also, you should take into account that maven-eclipse-plugin will invoke the execution of the lifecycle phase generate-resources before executing itself.
Apparently, a suitable lifecycle phase to run checkstyle is the validate phase e.g.

<plugin>
    ...
    <artifactId>maven-checkstyle-plugin</artifactId>
    ...
    <executions>
        <execution>
            <id>validate</id>
            <phase>validate</phase>
            <goals>
                <goal>checkstyle</goal>
            </goals>
        </execution>
    </executions>
</plugin>

We are almost there… Now you should make sure your checkstyle configuration is found properly inside eclipse (in particular your header and suppression files). Unfortunately, eclipse will not resolve relative paths inside your Checkstyle configuration file resulting in errors e.g.

You need to wire the header and the suppressions file into your Checkstyle configuration in an Eclipse friendly manner i.e. use full paths🙂

After struggling for a while with various tweaks (like this one) I found a relative clean workaround which works with both, Eclipse and Maven.

<plugin>
    <artifactId>maven-checkstyle-plugin</artifactId>
    <configuration>
        <propertiesLocation>/checkstyle.properties</propertiesLocation>
        <propertyExpansion>basedir=${project.basedir}</propertyExpansion>
        ...
    </configuration>
    ...
</plugin>

the checkstyle.properties file resides in build-tools module and should look like:

header.file=target/checkstyle-header.txt
suppressions.file=target/checkstyle-suppressions.xml

and finally, inside your Checkstyle configuration:

...
<module name="Header">
    <property name="fileExtensions" value="java"/>
    <property name="severity" value="error"/>
    <property name="headerFile" value="${basedir}/${header.file}"/>
</module>
<module name="SuppressionFilter">
    <property name="file" value="${basedir}/${suppressions.file}"/>
</module>
...

Finally! Now, you should be able to get your checkstyle reports from both Eclipse and Maven.

For a complete/complex working example you might check the sources of gwt-platform.

PS1. I found a similar approach in Apache CXF, which I found it in some extend complicated since it is using a combination of ant, xslt, and the ‘copy’ task to create all of the desired settings files.

PS2. This is my first ever blog. Hooray!

Posted in Java | Tagged , , | 3 Comments