Matt RaibleMatt Raible is a Web Architecture Consultant specializing in open source frameworks.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Modularizing GWT Applications with GWT-Maven

Last week, I spent some time modularizing the GWT application I'm working on. By modularizing, I mean splitting the code from one GWT module into a "core" and "webapp" module. The reason for doing this was so the "core" module could be used by another GWT application. Creating GWT Modules is fairly straightforward, but it wasn't as intuitive as expected when using the gwt-maven-plugin.

The hardest part of moving the code was figuring out how to run tests in the new "core" module. After getting it all working, it seems easy enough. Hopefully this post will make it easy for others. Here's the steps I'd recommend:

  1. Convert your GWT project into a multi-module project where you have a top-level pom.xml and two sub-modules (e.g. gwt-core and gwt-webapp).
  2. Do the normal single-to-multi-project Maven stuff like declaring the <parent> element in the modules and moving plugins/dependencies to the top-level pom.xml.
  3. Refactor your gwt-webapp project to push down all shared classes (and their tests) to gwt-core.
  4. In the gwt-core project, include *.xml and *.java in your JAR so GWT can extract/compile the source code when building gwt-webapp.
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.java</include>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
    
  5. In gwt-core/src/main/java, create a Core.gwt.xml that references the modules you'd like to use in all your applications. For example:
    <module>
        <inherits name="com.google.gwt.user.User"/>
        <inherits name="com.google.gwt.i18n.I18N"/>
        <inherits name="com.extjs.gxt.ui.GXT"/>
        <inherits name="pl.rmalinowski.gwt2swf.GWT2SWF"/>
    </module>
    
  6. Now the tricky part begins, mostly because of how the gwt-maven plugin currently works. In src/test/java, create a NoOpEntryPoint.gwt.xml that inherits your Core module and defines an EntryPoint.
    <module>
        <inherits name="com.company.app.Core"/>
        <entry-point class="com.company.app.NoOpEntryPoint"/>
    </module>
    
  7. Create a NoOpEntryPoint.java class in the same directory as NoOpEntryPoint.gwt.xml.
    public class NoOpEntryPoint implements EntryPoint {
        
        public void onModuleLoad() {
            // do nothing
        }
    }
    
  8. In any class that extends GWTTestCase (I usually create a parent class for all tests), reference the NoOpEntryPoint in the getModuleName() method.
        @Override
        public String getModuleName() {
            return "com.company.app.NoOpEntryPoint";
        }
    
  9. Lastly, in the gwt-maven plugin's configuration (in gwt-core/pom.xml), reference the NoOpEntryPoint in <compileTargets>, a non-existent file in <runTarget> and only the "test" goal in the executions.
    <plugin>
        <groupId>com.totsp.gwt</groupId>
        <artifactId>maven-googlewebtoolkit2-plugin</artifactId>
        <version>2.0-beta26</version>
        <configuration>
            <compileTargets>
                <value>com.company.app.NoOpEntryPoint</value>
            </compileTargets>
            <runTarget>com.company.app.NoOpEntryPoint/doesntexist.html</runTarget>
            <logLevel>INFO</logLevel>
            <style>OBF</style>
            <noServer>false</noServer>
            <extraJvmArgs>-Xmx512m</extraJvmArgs>
            <gwtVersion>${gwtVersion}</gwtVersion>
            <testFilter>*GwtTestSuite.java</testFilter>
            <testSkip>${skipTests}</testSkip>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>test</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

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.

Posted in Java at Mar 23 2009, 10:36:08 AM MDT 11 Comments
Comments:

For your info, the gwt-maven plugin is now hosted at codehaus as part of mojo project. It's groupId is now org.codehaus.mojo, but features are still the same you used in this article

http://mojo.codehaus.org/gwt-maven-plugin/

Posted by nicolas.deloof on March 23, 2009 at 12:08 PM MDT #

@Nicolas - I haven't heard anything about this on the GWT-Maven Google Group. I'm assuming this move happened over the weekend? I know there was talk of merging, just didn't think it happened yet.

Posted by Matt Raible on March 23, 2009 at 12:12 PM MDT #

Nicolas, we are still supporting the Google Code GWT-Maven plugin until I get a chance to get in and validate things. We aren't adding new features to GWT-Maven, but we are keeping it alive for those that use it, until a clean switch can take place. (I should be off of several other side projects within a few weeks, and then I will be in the mix there more - THEN once I am familiar with it all, I will freeze the GWT-Maven one and point people at Codehaus.

For now though, GWT-Maven is still what I would recommend. That recommendation though isn't a reflection that one is better than the other, it's just that I haven't used the Codehaus plugin yet, so I can't vouch for it - and again we are sill supporting GWT-Maven.

Matt, long story, I agreed to merge with Codehaus several months back but also told the GWT-Maven community that everything will remain the same until I can sign off on the Codehaus stuff. I want the transition for users to be seamless. (This was all discussed some time back on the GWT-Maven group, like I said, long story.) Eventually there will be only one, and it will be the Codehaus one, but we aren't there yet. And, if I do things correctly, as planned, all users won't have to change approaches/poms/etc.

And BTW, great article. Thanks.

Posted by Charlie Collins on March 23, 2009 at 07:07 PM MDT #

Do you have an idea of the date of the complete merge of GWT-Maven plugin with the mojo one ? An what about the next release ? I check the plugin homepage each mounth to know is this task has been completed... because we use a 2.0-beta26 since a very long time now ! And I would like to use a release for professional project...

Posted by Cyril Lakech on March 24, 2009 at 02:57 AM MDT #

Thanks man!

Posted by Gabriel on March 26, 2009 at 09:46 AM MDT #

I don't think you have to inherit the GWT modules in your own module if you inherit from GXT since GXT already inherits those itself.

Thanks for all the great articles!

Posted by Peter Leibiger on March 27, 2009 at 04:35 AM MDT #

Hi Matt,

Thanks for your post! Very useful as usual. Could you shed some light on what does "gwt-core" and "gwt-webapp" contains in your case? Do you use any MVC framework such as struts or spring in addition to GWT?

How different is your modular separation when compared to this:

http://gwt-maven.googlecode.com/svn/trunk/maven-googlewebtoolkit2-sample/

Thank you and looking forward to learning from you!

Posted by Oscar Perez on April 03, 2009 at 06:25 AM MDT #

My manager is a modularization freak. I prefer to have 1-project-with-1-module. The 1-project-with-1-module makes sure that I have super-high speed. A jetty:run with auto-redeploy or return-key-to-redeploy works better than mvn install on half a dozen modules and then running the jetty app.

I understand that things get different with GWT, but I still find multi module a bigger pain than single module projects.

Posted by Rahul Somasunderam on June 28, 2009 at 08:16 PM MDT #

Winner again Matt .

What's your opinion about MVP .

Nearly a decade ago we were happy to write spaghetti code in C++ (or at least I was at uni) then we were hit with MVC and life changed for better .

Now GWT has come up with MVP . I am missing the "C" . I feel applications have very tight coupling with the view if we do not have a controller .

And thoughts or blog on this .

Cheers

Posted by Shahzeb on April 28, 2010 at 11:16 PM MDT #

this was really useful. funny how hard it was to figure it out..not even the maven site helped me...is there a way to avoid doing the NoOpEntryPoint..so bizzare.

Posted by anon on January 04, 2011 at 05:55 PM MST #

Thanks for this post, helped me out a good bit.

A little tweaking I did though, since I did not want my sources wrapped up with the war file...

in the shared module (core):

<!-- force the installation of sources for gwt -->
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-source-plugin</artifactId>
      <version>2.1.2</version>
      <executions>
         <execution>
            <id>force_sources</id>
            <goals>
               <goal>jar</goal>
            </goals>
            <phase>package</phase>
         </execution>    
      </executions>
</plugin>

And then add that as a provided dependency in the app. Thanks for the post.

Posted by Justin Smith on June 24, 2011 at 05:55 AM MDT #

Post a Comment:
  • HTML Syntax: Allowed