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,

Advertisements
This entry was posted in GWT, Java and tagged , . Bookmark the permalink.

7 Responses to Efficient GWT development: Swap your gwt.xml with maven.

  1. Great post, very useful and hard-to-find information. A couple of remarks:
    – Your use of <!–– … ––> in ExampleDevelopment.gwt.xml could lead to think you have to repeat the shared configuration. Since you Development.gwt.xml, you don’t have to.
    – Using to swap GeocodeService can be cumbersome if you use Gin for injection (and if you GeocodeService implementations need to be injected with some dependencies). On Gin trunk there is a nice little configuration-property you can use to swap modules from the .gwt.xml and get the same behavior in a easier way, see:
    http://code.google.com/p/google-gin/issues/detail?id=129
    This mechanism could be deprecated soon, though, in favor of a more flexible one:
    http://code.google.com/p/google-gin/issues/detail?id=142

    Cheers!

    Philippe

  2. jgonian says:

    Thanks for the comment Philippe,
    – You were right about the <!–– … ––>. It was ambiguous so I removed it from ExampleDevelopment.gwt.xml.
    – The GeocodeService here is for demonstration of deferred binding only and I agree with you that GIN can handle way better this kind of behavior. I should probably come up with a better example for deferred binding 🙂

  3. Dang, there is a bunch of other XML missing from my original post! 🙂
    “Since you Development.gwt.xml”

    ==>
    “Since you <inherits> Development.gwt.xml”

    “Using to swap GeocodeService”
    ==>
    “Using <replace-with> to swap GeocodeService”

  4. Sam Edwards says:

    Thank you for sharing this, this is exactly what I was looking for, and thanks to Philippe also for the tip!

  5. eder says:

    Thanks for the post! It saved me some time!

  6. Pingback: Optimize GWT performance « Opinions regarding…

  7. Thank you very much, that realy helped!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s