A framework for GWT multipage applications
This article is about the development of Rich Internet applications with Google Web Toolkit (GWT) that consist of multiple HTML pages like flickr or facebook. It dicusses techniques to distinguish the different HTML host pages on the client side and an architecture to organize your entrypoints. Finally a framework for gwt multipage applications is introduced.
GWT applications, HTML host pages, modules and entry points
Some time ago I was developing a web application with jsp that consisted of a couple of jsp files. To enhance the usability of the user interface I wanted to add some ajax functionality to the pages and thus I was looking for a reasonable way to integrate GWT into my project. But that was not a simple thing, since the classical GWT application has got one HTML host page and only one entry point. I did not want to create one module per jsp file and so I was googling for a solution – I’m not the only one having this problem, but did not find a simple way to solve this problem. So I decided to develop my own solution and share it as an open source project on code.google.com.
How to choose the right entrypoint for the current page
If you’ve got one module for the entire web application with one registered entrypoint you have to know, which page is currently displayed to call the code according to the page. Some possibilities (this list is not complete!) are abvious:
- Render a javascript variable containing the name of the entrypoint on the server side into the header of the html page and read the value via JSNI.
- Render a meta tag to the header containing the name of the entrypoint on the server side and read the value via the DOM object.
- Use the page’s title or a part of the title and read the value via the Window object.
- Use the URL of the page and read the value with the Window object.
I decided to choose the last option and annotate entrypoints with a regular expression describing the adresses that are valid for the entrypoint.
A framework for multipage applications with GWT
Now we need an architecture for a framework that decides which entrypoint is the right one, creates an instance and calls its onModuleLoad method. The first step is to mark the entrypoints with java annotations containing a regular expression for which the entrypoints are valid:
package com.claudiushauptmann.gwt.multipage.sample.client;
import com.claudiushauptmann.gwt.multipage.client.MultipageEntryPoint;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
@MultipageEntryPoint(urlPattern = "MyMultipageEntryPoint.html")
public class MyMultipageEntryPoint implements EntryPoint {
public void onModuleLoad() {
Label label = new Label("MyMultipageEntryPoint");
RootPanel.get().add(label);
}
}
Second, we need a dispatcher entrypoint that is called instead of the target entry points, that decides which is the right entrypoint and calls it’s onModuleLoad method:
<module> <!-- Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <!-- Inherit the gwt-multipage module --> <inherits name='com.claudiushauptmann.gwt.multipage.gwt-multipage'/> <!-- Use this EntryPoint instead of your own one. --> <entry-point class='com.claudiushauptmann.gwt.multipage.client.EntrypointDispatcher'/> </module>
Via deferred binding the dispatcher entrypoint knows all possible entrypoints and looks whose regular expression matches the current url.
Conclusion
This framework was developed for multipage Rich Internet applications that are using GWT. The focus is about the pages and their entrypoints. There are some other issues about multipage Rich Internet applications that are not topic of this article but will perhaps find a place in this framework in the future.
If you are interested in this project you will find it at code.google.com:
http://code.google.com/p/gwt-multipage/
Please give some feedback and report bugs! The downloads are here, some more documentation will come soon.
11 Comments »
RSS feed for comments on this post. TrackBack URL
Hi Claudius,
If only I had found this article 10 months ago when I started building SambaJam!
I eventually had to settle for a different model and create different projects for each page. If you want to check it out, we are running a Beta (completely free, not trying to sell you anything) and I would love to get the opinion of a fellow GWTer. It’s a collaboration platform built on top of the Alfresco Open Source Content Management system.
Send me an email if you would like to have a look. It’s also not limited so if you like the application you can invite others to collaborate with you
Anyways, I’ve just bookmarked your blog, it’s definetely one of the best ones I would say.
Regards,
Ale
I have to say, this just saved me a lot of time. We have a very large GWT application. We have just discovered that we needed another entry point into our application. Out of all of the other solutions out there, this is by far the best and easiest. No code duplication, no increased compile time, and we did not have to change a thing in our deployment. Great work.
Awesome work. I would say its the struts framework for gwt.
The module XML file supports the declaration of multiple entry points, as many as you like. The OnModuleLoad() methods of these are invoked in the order that the entry points are defined within that file. So, a simple approach to supporting multiple HTML pages with a single module would appear to be (I have not yet tried this) just defining multiple entry points, and creating the corresponding entry point classes, and then, at the top of each entry point’s OnModuleLoad() method, check the HTML page using one of the techniques that you have described (e.g., checking the URL) and if the page does not correspond to that entry point, just return, at which point the next entry point’s OnModuleLoad() method would be invoked. Your framework will no doubt be more maintainable, but for just a couple of HTML pages this approach ought to work.
Pretty neat.
Another feature you may want to add is support for GWT.runAsync(). Right now, if I have 3 entry points, the first page is going to download the code for all 3 of them. But since there is such a clean separation between EntryPoints, you may want to wrap them in a GWT.runAsync call. That would significantly reduce the size of the javascript file.
I am guessing you could add this feature without an impact to any client code. Only EntryPointFactoryImplGenerator and EntrypointDispatcher would need to change.
Let me know if you agree with the idea; I can try and submit a patch in the next few days..
@Carl: Thank you for your hint! Some time ago I used this approach in a small project and it was working well.
@Sripathi Krishnan: This is a wonderful idea! I’m really looking forward to your patch!
This is really a nice framework!
Here is a tip on how using it when you have aliases for a web-page. I run my service in Jetty as the root context. So it is accessible directly via a FQDN (with urlPattern=”/”). In addition the same page should be accessible via FQDN/public_1.html and FQDN/index.html. So the urlPattern could look like “/|/index.html|/public_1.html” (for me it doesn’t work w/o the leading /’s ).
However the above regex, which works well when used with Java’s String.match() method, doesn’t work with GWT. The problem is that the choices after the standalone “/” are ignored. I.e. if you’d write: “/index.html|/|public_1.html” it would match the FQDN and “FQDN/index.html” but it would not match “FQDN/public.html”. Don’t ask me why, again it would work in plain Java. Having noticed this behaviour using the regex “/index.html|public_1.html|/” yielded the desired result.
Awesome. I was wondering what is the current status on this project.
thanks
Hello Fatih! Thank you! I’m very busy at the moment. The next steps are the migration of the build management to apache maven like gwt-maps-gxt (http://code.google.com/p/gwt-maps-gxt/), adding tests and supporting moving/changing context-roots. Is there a feature that you’re missing or are you having trouble? I’m as always looking forward to patches and new ideas! Claudius
Hello!
Release 1.0.0.Beta3 is available:
http://groups.google.com/group/gwt-multipage/browse_thread/thread/49164cab0cd1057a
http://code.google.com/p/gwt-multipage/downloads/list
Please have a look at the issues (kind of road map):
http://code.google.com/p/gwt-multipage/issues/list
thx
I don’t understand the value of Sripathi’s idea.
Doesn’t that devolve back to using separate projects – except with slightly worse performance when the runAsync is called?
Or is the target of this for legacy JSP apps. I’d appreciate some more information in case I’m not groking the idea correctly.