Building a Regular Website with the Google Web Toolkit
The Idea
Many nice and home-grown websites contain a navigation bar. But without a special design tool a navigation bar is not easy to build because it typically involves JavaScript programming. My idea was to build a simple and convenient tool such that a non-technical person with basic knowledge about static HTML can easily include a corresponding navigation bar in its pages.
The person configures the navigation bar by composing or adjusting a rather simple XML file. The HTML writer should not have to deal with server-side page scripting or anything a like. For the website to work, it should be sufficient to deploy the XML and a bunch of static HTML files along with some ready-made magic. Trying out the site should be as easy as double-clicking the main HTML file in the local file system.
I like Java and I did not want get my hands dirty with JavaScript and browser compatiblity issues. So how could I get the job done? Since I also like experimenting, I decided to give the GWT (the Google Web Toolkit) a go for the project.
When reading the GWT’s documentation, its seemed like the perfect choice for me: I program my navigation bar entirely in Java and in the end, it is all converted to a highly optimized and pure client-side JavaScript / HTML mash. Wow!
In the following, you can read about my related experience with the GWT and the many unexpected hurdles a had to take in order to reach my goal.
Here is a brief summary about the problems I encountered and my general impression, after playing with the GWT:
- The GWT misses (at least) some basic widgets, you may expect in an Ajax (library).
- (At least some) of the existing widgets are difficult to extend.
- The asynchronous programming model of the GWT (and Ajax in general) leads to problems,
when creating higher level API. (You are forced to give it an asynchronous design, too.) - The GWT does not well support dynamic locale changes (details will follow in an upcoming blog entry).
Although I was really enthusiastic about the GWT when I started, I have to admit that I got disappointed here and there.
An upside is the GWT’s basic infrastructure (i.e. the compiler and the debugger), which seems very mature and stable.
It’s really just the library that should be improved…
Getting in Touch with the GWT
If you are a reasonably experienced Java programmer, then getting started with the GWT is easy, and the quick results are motivating. So, after trying out some basic stuff, I wanted to make shure that the GWT API indeed allows me to realize my little project.
The Navigation Bar Hassle
The GWT library contains a widget, which is close to the kind of navigation bar I had in mind: the class com.google.gwt.user.client.ui.TabPanel. Unfortunately, it allows for creating horzitontal navigation bars only.
When looking at the GWT kitchen sink example, it seems like there is a vertical navigation bar included - but that impression is misleading. The vertical navigation bar in the kitchen sink does not use a ready-made GWT widget. Instead, it is a custom built thing made out of a bunch of hyperlink objects (of type com.google.gwt.user.client.ui.Hyperlink)
I wondered why Google did not add a built-in vertical tab panel and so I began to read the source code of the
TabPanel and the affiliated TabBar class. I could not find any good reason why this widget should not be vertical and so, I tried to subclass TabPanel in order to get a vertical version of it. Sadly, my attempt quickly came to a halt, because the TabPanel had not at all been created with extensibilty in mind. The first few lines of code of GWT’s TabPanel reads as follows:
public class TabPanel ... {
...
private DeckPanel deck = new DeckPanel();
private TabBar tabBar = new TabBar();
private TabListenerCollection tabListeners;
/**
* Creates an empty tab panel.
*/
public TabPanel() {
VerticalPanel panel = new VerticalPanel();
panel.add(tabBar);
panel.add(deck);
...
The TabPanel is a composite widget, which consists of simpler widgets, namely a vertical panel, a tab bar and a deck panel. However, given the code from above, none of these contained widgets can be exchanged by subclassing, and therefore, it is practically impossible to get a vertical tab panel by by subclassing TabPanel.
I felt disappointed: If the set of built-in widgets is small, then at least I expect a good degree of extensibilty of the corresponding framework.
So how did I get my vertical tab pane then? By copy and patch! I copied the entire TabPanel code and turned it into my so-called FlexibleTabPanel class.
Its first lines read as follows:
public class FlexibleTabPanel extends Composite implements TabListener,
SourcesTabEvents, HasWidgets, IndexedPanel {
private final WidgetCollection children = new WidgetCollection(this);
private final DeckPanel deck = new DeckPanel();
private final FlexibleTabBar tabBar;
private TabListenerCollection tabListeners;
/**
* Creates an empty tab panel.
*/
public FlexibleTabPanel(boolean horizontal) {
Panel panel = createOuterPanel(horizontal);
tabBar = createTabBar(horizontal);
panel.add(tabBar);
panel.add(deck);
...
The constructor of FlexibleTabPanel obtains a boolean, which decides, if the resulting tab pane is vertical or horizontal. The methods createOuterPanel() and createTabBar() may be overriden. Depending on the boolean flag, they create widgets for either the horizontal or the vertical case.
As you might guess, I also had to copy and patch the class com.google.gwt.user.client.ui.TabBar. I even had to subclass (the standard GWT classes) HorizontalPanel and VerticalPanel: Both classes have certain methods in common but the GWT does not factor them out in a common superclass or super interface. However, the original TabPanel class counts on these methods with respect to HorizontalPanel. Since I wanted to use the corresponding code in FlexibleTabPanel for both the HorizontalPanel and VerticalPanel, I was forced to do the following:
- I created an interface, which contains the missing super class methods and it looks
as follows:
public interface FlexibleIndexedPanel extends IndexedPanel {
public void add(Widget w);
public void insert(Widget w, int beforeIndex);
public boolean remove(Widget index);
}
(IndexedPanel is an existing interface of the GWT, which just lacks the methods from above.) - I subclassed HorizontalPanel and VerticalPanel in the following ways:
public class FlexibleHorizontalPanel extends HorizontalPanel
implements FlexibleIndexedPanel {
}
public class FlexibleVerticalPanel extends VerticalPanel
implements FlexibleIndexedPanel {
}
The new classes FlexibleHorizontalPanel and FlexibleVerticalPanel offer the functionality needed in FlexibleTabPanel. So far I could not find any good reason, why the GWT does not share this functionality in a common super class of the vertical and horizontal panel already.
Building the Builder
XML and Properties Files for Configuration
As I mentioned in the beginning, I wanted the navigation bar to be configurable via an XML file. Essentially the XML file should determine the structure of the bar and its contents. I wrote a little interpreter, which parses a related XML file and and turns it into a widget object hierarchy. This is a similar approach as in frameworks such as SwiXML and ULCXML, but for my purpose, the navigation builder, as I called it, acts on a much smaller scale.
Here is a sample XML file that the navigation builder is able to digest:
<?xml version=”1.0″ encoding=”ISO-8859-1″ ?>
<navigation>
<file id=”home” xhref=”home.html” mce_href=”home.html” html=”true”/>
<file id=”cv” xhref=”cv.html” mce_href=”cv.html” html=”true”/>
<file id=”concerts” xhref=”concerts.html” mce_href=”concerts.html” html=”true”/>
<navigation id=”gallery” orientation=”vertical” default=”true”>
<file id=”image1″ xhref=”image1.html” mce_href=”image1.html” html=”true” default=”true”/>
<content id=”image2″>This image is not yet available.</content>
</navigation>
<file id=”contact” xhref=”contact.html” mce_href=”contact.html” html=”true”/>
</navigation>
Based on this file, the interpreter creates an outer navigation bar with five tabs. The first tab has the id home, and when selected, it displays the HTML file home.html. The next two entry work similarly. The fourth entry defines an inner navigation bar, which is vertical and contains two tabs itself: The first inner tab relates to the HTML file image1.html and the second one adds the text This image is not yet available. in place.
As you can see, it’s usually HTML files, which determine, what’s displayed upon tab selection. But where do the display names of the tabs actually come from? For reasons I will explain later, I moved all of these names to Java properties files. E.g. the properties file navigation.properties for the XML file from above may look as follows:
home=Home
cv=CV
concerts=Concerts
gallery=Gallery
contact=Contact
image1=Image 1
image2=Image 2
Every id defined in the XML file is referenced in the properties file and is associated with an English display text.
Being Asynchronous is Contagious
After that, it was time to build the navigation builder class itself. The GWT comes with a convenient
DOM-based XML parser API and so, it was easy to write the interpreter code.
Interestingly, the way to read a corresponding XML file with the GWT has a serious impact on the entire program structure.
Reading files inside a Web page is real Ajax functionality, and the related GWT API must be used as follows:
HTTPRequest.asyncGet("myfileName", new ResponseTextHandler() {
public void onCompletion(String responseText) {
...
}
}
The code loads the file myfileName via a relative URL and upon success, the contents of the file is passed in as a string to the onCompletion() method.
Since the method asyncGet() returns its result via a callback, it is called asynchronous. The navigation builder uses asyncGet() and therefore its API became asynchronous too:
NavigationBuilder builder = new NavigationBuilder(...);
builder.buildNavigation(
new NavigationBuildHandler() {
public void onBuilt(Widget widget) {
...
}
public void onFailure() {
...
}
});
Asynchronous APIs considerably change the structure of depending programs and in the example above, an asynchronous low level API “infected” a higher level API.
In the context of the GWT this effect is hard to prevent, because the native
execution environment (Java Script) has no thread concept and no thread synchronization mechanisms.
Results
After putting it all together, I finally got a first version of the navigation bar. Follow this link to try out a corresponding example, which uses the XML file and the properties file from above.
The file GWTSample1.zip contains all the related source code.
Next week, I will talk about my adventures, when I tried to bring internationalization into the system. (Note that the code in the zip file contains the code for related feature already.)

Thomas Ernst said,
March 13, 2007 @ 11:56 am
Thanks for the nice intro. It made me curious and I wanted to have a look at the example. However, I recognized that the two links in the Results section don’t work.
Regards, Thomas (still curious…)
admin said,
March 13, 2007 @ 1:42 pm
The links have been fixed. Should work now.
Vipul said,
October 11, 2007 @ 12:01 am
Hi Danip,
I wanted to use your article and the code in a professional article, can you send your email address to my mail address and we can talk about the same.
thanks