Structuring GWT modules for large applications


(18 comments)
February 22nd 2011


When creating large web applications with GWT, it's not always clear how to get started. The most important (but most difficult!) question, I've found, is exactly how to structure the project - i.e. what justifies creating multiple web applications, multiple GWT modules, multiple EntryPoints, or everything all in one. Although there is plenty of discussion out there (here, here, here, and here), the general consensus is still a little muddy. Like anything in our business, it seems the "right" answer is "it depends", and so in this post I hope to highlight a few of the factors in this decision.

Example: Web apps, GWT Modules, and EntryPoints

It's probably best to start with a simple example. Imagine you already have some ecommerce site (you can decide what it is that you sell!), and now you need to build an internal application to manage your business. There are two "sections" to this site: (1) the Inventory UI through which Customer Service Reps can see what's in stock, and (2) the Orders UI through which they can track orders and through which the Shipping Manager can fulfill orders and send them out.

Note that there is some code that both the inventory and orders sections will need to share ("common" above) - for example, base classes, domain classes, helpful utilities, etc.

The question is how do you structure this application within GWT? Here are a few choices:

  1. Two WARs: have a separate web application for the inventory and orders sections, each sharing the common.jar file.
  2. Two EntryPoint modules: have one web application, but create separate GWT modules for common, inventory, and orders, where inventory and orders both have EntryPoints defined (see picture below).
  3. One EntryPoint module, three dependent modules: have one web application, but split each of the three pieces (common, inventory, and orders) into their own GWT modules, and then create one main GWT Module with an entry point which imports the others (see picture below).
  4. One big GWT module: have one web application and just one GWT module and one entry point.

Just to be clear, here's a picture of the GWT module organization in options 2 and 3:

This decision is pretty fundamental, and so it's best to get it right up-front (or at least to try!). Here are some factors to consider:

Download Time

GWT applications are not like more traditional web applications. When the user first navigates to the site, he downloads the entire application (as a Javascript bundle), rather than downloading the HTML for each page incrementally as he navigates through. This means, all things being equal, the larger the application, the larger the Javascript bundle, and so the longer the initial load time of the application. The problem is, however, that if a user never accesses a whole section of the site (e.g. Shipping Managers never use Inventory), he still needs to wait for that portion of the Javascript to load. And if there are many unused sections in the site for a given user, this could mean a lot of wasted time.

At first blush, this may seem like a legitimate argument for either options 1 or 2 above (separate web applications or separate modules with entry points), especially if the different sections are sufficiently large. And while taking this approach and breaking things out could definitely solve your download latency issue, before you do this there are few caveats to first consider.

First, GWT 2.x has essentially solved this problem with code-splitting, a mechanism that allows you to partition your code, and only download portions as the user needs them, not all at once. (Note: structuring the dependencies to allow for effective code splitting can be tricky, so it is imperative that you think this through up-front). Second, Google is pretty clever in how it can boil down even a relatively big application into a small amount of Javascript, so unless the application is very large, this is usually not an issue. And lastly, the Javascript for the application is cached on the client, so only the first visit to the app could potentially be slow.

Looking at option 3, the different modules provide good possible division lines along which to code split, however code splitting is equally possible with option 4 (one GWT module) as well. Google has some helpful patterns defined for code splitting, and there are a number of other good sources as well (like here).

Essentially, application download time, in and of itself, is probably not a solid reason for breaking an application into multiple applications (either WAR or entry point), however if navigation between sections is rare, then it may be justified, which leads me to my next point...

Navigation and URL

With GWT, one application is just one URL (e.g. http://www.foo.com/index.html), and different "pages" are just inner links (e.g. "index.html#my-orders"). It may be important (for usability, SEO, security, etc.), however, for different "sections" of the site to have different URLs (e.g. "/orders/index.html" and "/inventory/index.html") rather than just one with inner links (e.g. "index.html#section=orders" and"index.html#section=inventory").

A most obvious solution would be to split it into different web applications (option 1), but in many cases (including the example above), this won't work - e.g. the two sections may need to share an HTTP session, etc.

Creating different GWT entry point modules (option 2) could solve this issue as well - there would be only one web application this time, but each module would be accessible via a different URL. The downside here, however, is navigating between these modules (e.g. inventory-to-orders or orders-to-inventory). First, the normal mechanism for navigating in GWT 2.1 (i.e. placeController.goTo()) only works within modules, and so it'll be necessary to "hard-code" the module that you are navigating to in the navigation code (e.g. Window.Location.assign()). Second, client-side state cannot be shared between GWT modules with different entry points, so if a module needs to know about something from another module, it'll have to go to the server.

These disadvantages may be acceptable, especially if the different sections are accessed by mutually exclusive sets of users, and so cross-section navigation is rare. Otherwise, keeping things together, either in one entry point but multiple GWT modules (option 3) or one module altogether (option 4), will be necessary, and you'll just have to live with the new, AJAXy-style URLs.

Compile Time

As you know, in GWT applications, Java code gets compiled into Javascript. This compilation can take a fair amount of time for larger applications (even when compiling for just one browser), and slow builds make developers less productive. Not good. Of course GWT is smart enough to only compile what's changed, and most times developers are working within the hosted mode which doesn't necessitate a manual build, but even still, in a team environment "clean" builds are sometimes justified, and if these are slow it can significantly disrupt a developer's flow.

Surprisingly, segmenting applications into multiple entry point GWT modules (option 2) can often do more harm than good, especially in the case where the shared code is large. For each entry point module, GWT re-compiles everything it needs, so if there are two modules, "orders" and "inventory", and they both share "common", then "common" will be compiled twice (note: this is true even if common is a separate project and has already been compiled into a common.jar - i.e. the JAR contains no Javascript!). In this case, segmenting into multiple entry point modules would therefore significantly hurt build time, not help.

If the application is significantly large, then finding a way to speed build times, outside of the well established configurations/optimizations, might still be necessary. Segmenting into separate GWT modules with one entry point (option 3), allows for a possible work-around. If developers typically work within only one functional module at a time (e.g. orders or inventory), it's possible for them to comment out (in their local environment only!) the references (e.g. imports in gwt.xml or code references, etc.) to the other un-used functional modules, thereby bypassing the GWT compile for these unnecessary modules in their local build. Basically, the idea is, using the example above, don't make the developer of the Orders section compile the Inventory section code when he'll only ever be working within Orders.

Of course developers have to remember not to check these files in, and of course the main build (e.g. Hudson, etc.) will build everything (e.g. Orders plus Inventory) and so will take the normal amount of time, but at least locally things would be faster. (Note: this is a trick we've used on projects with success, but I haven't heard others mention it - I'd love to hear about your tricks...or if you see a flaw in this approach).

Maintainability and Reusability

From a maintainability and reusability perspective, creating one monolithic application is a well-known path to a big ball of mud. If different teams of developers work on different sections, or if different pieces of the application may be re-used in the future by other applications, then modularizing in some way will be helpful (options 1, 2 or 3). In some cases this may mean creating one share-able set of client code (e.g. common), or possibly many (infrastructure, domain model, etc.) - depending on the expectation for re-use. Again, in general, for an enterprise-scale GWT application, it's important to put some thought into dependency organization, using either projects, web applications, GWT modules, or packages as a unit of structure.

Conclusion

As I mentioned at the start, the "right" approach to structuring a large-scale GWT application completely depends on the requirements of the project. I hope this post has at least shed some light on a few of the factors that are important to consider, but I know I've only scratched the surface...so please let me know about your experiences, or what I might be missing!

I'm an "old" programmer who has been blogging for almost 20 years now. In 2017, I started Highline Solutions, a consulting company that helps with software architecture and full-stack development. I have two degrees from Carnegie Mellon University, one practical (Information and Decision Systems) and one not so much (Philosophy - thesis here). Pittsburgh, PA is my home where I live with my wife and 3 energetic boys.
I recently released a web app called TechRez, a "better resume for tech". The idea is that instead of sending out the same-old static PDF resume that's jam packed with buzz words and spans multiple pages, you can create a TechRez, which is modern, visual, and interactive. Try it out for free!
Got a Comment?
Comments (18)
Stephen
November 14, 2016
For each of our GWT based projects, we have a single

App.gwt.xml

which builds all variants of the complete application, and then a

AppCustom.gwt.xml

which inherits from App.gwt.xml.


Developers run local compiles using AppCustom, the production builds are built from App.

Developers disable/adjust the config depending on what they are working on.


The AppCustom.gwt.xml isn't committed to source control - so there is no danger of developers inadvertantly checking in their custom version and screwing up other developers or the production build.


This works well for us, especially as different developers work on different platforms and in different languages.


We use option (4) btw, however our applications are used internally by businesses, so having a single largish download (over 1Mb unzipped) per app isn't an issue.
Ben
November 14, 2016
Thanks Stephen! That's a really good strategy.

Jim
November 14, 2016
At my company we have thought through many of the same issues.


Stephen's strategy is a little more straightforward, but what we have done to help developers compile only those modules they are interested in is create text file which lists a GWT module on each line. This file is read in by an Ant script which ignores modules commented out with a hash -- this makes it very easy to tune which modules are compiled.


To speed continuous builds, we have created copies of each module's gwt.xml file which compiles each module for a single browser. These versions are only used when we set a build flag; this enables us, along with use of the --draftCompile flag and PRETTY formatting, to see build times of half of what they are when we are not using them. For getting fast confirmation that the build is not broken, this has been fantastic.


There are other tricks, which I have outlined here, but your article definitely covers this topic in much more depth.

Ben
November 14, 2016
im - very clever approach...and great tips in your post (wish I found it a few months ago actually!).


Unfortunately, we're using Maven...which limits some of our flexibility in building...so our approach is definitely less elegant than yours or Stephen's.


Thanks for commenting!
Ashton
November 14, 2016
Nice article. It's nice to learn from veterans and gain this feedback without actually having to put in the hours:)


My experience:


I use a similar solution as Jim in that I only compile for one variation and for one module when I need. My compile times are only 3-5 minutes now so it's not terrible. (I work 24/7 so sometimes I let it do a clean complete compile just for a break)


* My comments below are bias to my application and will probably taint the objective nature of Ben's post *


However, when using code splitting you may want to compile soyc reports to understand what's going on under the hood. In this case, compile time shoots up again


As far as organizing modules, I agree you will always have that "common" aspect and the balance between components built on top of the common aspects depends on all factors. You mentioned business units as separate components and another could be device. GWT makes it very easy to compile for different user agents.


However, I think that if you make a mobile version of your app then it probably needs to be a separate module if you are really going to make it worth anything. This is very tricky because you should have "common" areas all over the place. But the reason for building a mobile or tablet app would be so users could interact with it in a different way and the app could interact with the user in a different way. It should be (and by should I mean in my case the my app needs to function significantly different on other devices - different kinds of users are using it for different reasons) a different app with different application logic and flow (well different enough to where the pros of organizing into different modules may actually outweigh the cons).


I also use a different module to separate Admin functions from normal functions. Here there is a lot of overlap and I would like to have it as one module. However, I am building a user facing application and don't want the Admin app logic (however ever obfuscated it may be - or what size) downloading with ever normal user. I briefly tried using code splitting to solve this problem but it just makes things too complicated and then I would have to authorize a client to download admin code and other problems arise. So that situation isn't perfect


It depends. So that was my experience
Ben
November 14, 2016
Thanks Ashton! Great comments.


The "admin" vs. "normal-mode" module, I suspect, is the most common scenario, and actually that might have been a better example in the post. A separate module and EntryPoint is probably always warranted - the two "sections", in this case, are really two separate apps (admin users only want to download admin code, there's probably not much navigation between sections, no need to share state, etc.).


Developing an app for different clients can be extremely tricky, since as you said they can end up being pretty different. That's a whole other post! :)
jens
November 14, 2016
thanks a million times for this helpfull post!!!! jens

Ahmed
November 14, 2016
Thanks for laying out different options and issues related to them Lots of good tips in comments too.

James
November 14, 2016
Thanks, this proved useful.
David Pinn
November 14, 2016
What a relief to discover that other people are struggling with the same issues! Thanks for your comprehensive post, Ben. I wonder if you, or your readers, would be kind enough to do a sanity check on my thinking; here goes:


There's an architectural issue that is troubling me, which I'll explain in a moment; but first I need to present some background information.


I have a web app that is fronted by a set of 'landing' pages, which have marketing gumph and a nice big green Sign Up button. Because I want search engines to fully index the marketing goodness, I want the landing pages to be delivered to the browser as HTML (as opposed to a ball of untrawlable GWT JavaScript). So far so good; the landing pages can be implemented as HTML files served up by Tomcat.


Now I want to add a login panel to the masthead of my landing pages. Returning users can enter their email address and password into that panel, and be given access to the application proper. OK, so that's just a simple HTML form, and a servlet/JSP on the server-side to handle the authentication, as per Google's article, Using a Dynamic Host Page for Authentication and Initialization.


Here's where it gets tricky. I want to give the login panel some smarts; for example: labels that are rendered inside the fields, and fade when you type over them; a cool animated wait icon; and nifty handling of error conditions. I guess I could use JQuery for that, but hey, I already have my hammer (GWT), and this login panel looks a lot like a nail.


It seems to me that I have two architectural options:


TWO MODULES: one module for the login panel, and one for the application proper. The login module is really small and attaches itself to the masthead of my landing page(s). Upon successful login, the login panel uses Window.Location.assign() or whatever to flip to the HTML host page that embeds the main application.


ONE MODULE: the module cleverly detects whether it is hosted a landing page or the main application host page, perhaps by looking for the DOM element that represents the container of the login panel. If it's on a landing page, it inserts itself into the appropriate place, and activates just the code that it needs to perform the login, leaving the bulk of the application behind a split point. If it's on the main application host page, then it attaches itself to the body of the document, and lights up the main application code.


I'm drawn to the two-module option because code splitting is fiddly and time-consuming, but having read your article, I'm no longer sure. I'd be grateful for your thoughts on the matter.
Ashton
November 14, 2016
David, this is probably a common problem and an issue that I am working with currently. My current solution is a big hack so I will create a new way and post the solution
Ashton
November 14, 2016
I have created a sample application which uses a separate LoginModule to handle any pre-authentication/login stuff. I have included two main modules


Overview:

You have two main module that you want to put behind a login and you want to have full GWT-Control over your login page. I have created a Login module which loads and will fire a quick rpc to check for an existing session (if so redirect). It will show a form to either login or register


The web.xml defines two servlets for the two main modules and a servlet for the login module. The two main module servlets are very basic. All they do is check for an existing user (if yes: return an html page which poitns to ModuleX.nocache.js, Otherwise, return an html page the loads the login.nochache.js)


The default welcome file will just load login.


Just wanted to post this as a reference to whoever stumbles across it..


Check out the web.xml and the servlets and login (entry point)


Demo:

http://gwt-advanced-login.appspot.com/


Code:

https://github.com/ashtonthomas/GwtAdvancedLogin
David
November 14, 2016
Hi David -


Sorry for the super slow reply - I didn't see this comment!


Honestly, I think I would lean toward the two module solution as well...just because the code seems so distinct/separate...there's no real navigation between the two modules...and like you said, you wouldn't have to bother with code splitting. That's just my 2 cents though!
sahil
November 14, 2016
Can any one tell me that i am making a chat server in GWT and now i want to do the server side ..so what i can use for that in GWT....can any one provide me some example...
AndyD
November 14, 2016
Hi Ben, thanks for a great article. I'm relatively new to GW,T but just today I ran into some of these same issues. I had just split my "user" and "admin" stuff into two modules and ran across this post while googling for a solution to a problem I'm having in eclipse (can't seem to run both modules in parallel in development mode - the 2nd one I run complains about not finding my gwt.xml file). I have to thank Ashton, too... I'm bookmarking his sample app to handle login, since I'm going to be working on that in the future.
Rana
November 14, 2016
Hello,


Thanks for the article, it is very useful.

I am actually searching for a solution for our problem. Our application is a large one (mathematical application). We are using a common project (Application) with an empty EntryPoint. And the main application with another EntryPoint.


The problems are related to the number of supported languages:

1- In the development mode, compiling all the permutations takes ages, and lots of resources, to an annoying extent.

2- The size of the application is big, to the extend we are unable to use app.spot (space limitation) using all the supported languages.


Did you encounter such a scenario? Do you have by chance any idea for a solution?


I tried runtime-locale, but it didn't do much for my case https://developers.google.com/web-toolkit/doc/latest/DevGuideI18nLocale#RuntimeLocales

I tried to break the main application into two modules, one only for handling languages, and the other one, the application itself. But, it didn't help either.


Many thanks

Rana
Anu
November 14, 2016
We have a situation where we are thinking of restructuring our application.

At present, we have -

1. common module : no entry point. we create a common.jar.

2. GWT module A : with an entry point. build.xml of A common.jar and A.gwt.xml inherits common.

3. GWT module B : with an entry point. build.xml of B common.jar and B.gwt.xml inherits common.

So, A and B have local copies of common.

Case : we were setting a value in common from A and get it in B, which is always null in B , as A and B have localised common.


Can we resolve this by option 3 you have suggested in the article?

Also, is there any way A and B share same copy of common.jar?


Please advice.
Vineet Jaiswal
March 13, 2019
I know it is very old post!
But if possible please help me out.

My Application is producing 1.6GB of war file and taking 7 to 8 hrs. for complete build of 5 permutation.
configuration of machine on which we are compiling is:
OS: windows server 2012 R2
RAM: 64GB
Processor: Intel R ZEON R CPU E3-1225 V5
Core : 4
we have defined gwt compile parameters as follows:
GWT Compiler JVM Arguments: -Xmx61440M
GWT Dev Mode JVM Arguments: -Xmx61440M
GWT Test JVM Arguments: -Xmx61440M

we are facing two major problems

from last few days we are receiving out of memory error during compilation.
it is taking very huge time to build.
we wish our project could break into smaller sections (modules compiled individually separately) and bundled in a single war at the time of release. like we use multiple dlls and use it in single exe. and in case of changes in any dll we need not to build whole exe again instead we only compile a dll and deploy it to client.

any suggestion \ help will be highly appreciated.

thank you!