Tags First GWT

by Zack Grossbart on May 31, 2009

The Google Web Toolkit (GWT) speaks to all the Java programmers left petrified by the thought of web programming. GWT has a siren’s call: forget about cross browser issues, don’t bother with JavaScript, stay away from HTML. In reality, GWT requires deft piloting to stay off the rocks.

In case you’ve never heard of it, GWT is an open source project from Google that compiles Java code into JavaScript. You write your Java code just like a desktop application and get JavaScript on the other end. Instead of onClick=myFunction() you write myObject.addClickListener(this);

Desktop programmers love this style of programming because… well… we hate web programming. JavaScript feels beneath us. It isn’t strongly typed, isn’t object oriented, and doesn’t even have a compiler. A friend of mine described JavaScript this way: “You get a bunch of type safety bugs from the 1980’s.”

Desktop programmers want to focus on the implementation and the data; GWT speaks to us. “Don’t use a table tag, just use a FlexTable. Don’t use a div tag, just use a FlowPanel. Don’t worry about HTML. Forget about CSS. We’ll handle it for you.” And therein lies the rub. It does abstract away some of the complexity, but you can’t use GWT without an understanding of HTML and CSS. Without that, the developers and the designers have big problems. It happened in my company.

We started using GWT last year. We combined a team of seasoned desktop programmers with a designer who knows web programming. The designer spent awhile creating a prototype in HTML, CSS, and JavaScript. When he was satisfied with the prototype he sent it to the programmers and they said, “We can’t do that in GWT.”

Prototyping in HTML and then adding the data binding is a time tested design pattern. Why doesn’t it work with GWT? GWT doesn’t let you control the tags. You get table tags when you want div and div tags when you want span. GWT gave away a more polished UI for easier coding, and that is one exchange your users will never be thankful for.

StudyBlue ran into the same problem and their response was emphatic: “Use GWT to build the house, not to paint it.” Write the tags first. Don’t start with your database design or a UML diagram. Start with the HTML. Designing a prototype in HTML and working from that is possible. We’ll use the WordPress login screen as an example.

WordPress Login In GWT

wp_login

I use WordPress almost every day. Their admin UI is clean, functional, and polished. It’s one of the few web applications that makes me forget it is a web application. Let’s take the WordPress 2.7.1 login panel and write it in GWT.

Start by understanding the page. Notice that it has rounded corners, nice spacing, and pleasing background colors. It has something else. The HTML and CSS are already written. This is really important since most desktop programmers don’t have the experience to write CSS.

Using GWT’s FlexTable for this would meant rewriting the HTML and therefore the CSS. GWT widgets generate their own HTML tags and they don’t match up with the existing CSS. The goal is to keep the tags and use GWT for data binding. In order to use the existing CSS we need to keep the original HTML. Let’s look at it.

<form method="post" action="wp-login.php" 
id="loginform" name="loginform">
  <p>
    <label>Username<br/>
      <input type="text" class="input" 
      id="user_login" name="log"/>
    </label>
  </p>
  <p>
    <label>Password<br/>
      <input type="password" class="input" 
      id="user_pass" name="pwd"/>
    </label>
  </p>
    <p class="forgetmenot">
      <label>
        <input type="checkbox" value="forever" 
        id="rememberme" name="rememberme"/> 
        Remember Me
      </label>
    </p>
  <p class="submit">
    <input type="submit" value="Log In"
    id="wp-submit" name="wp-submit"/>
  </p>
</form>

This HTML doesn’t use any table or div tags. The designer used p tags and we don’t want to lose that. We’ll start by escaping the HTML into a Java string.

Escape the HTML

There is no way around it: escaping quotes is a pain in the butt. PHP has a nice syntax to include strings that haven’t been escaped, but Java doesn’t. GWT is working on a way around this which may be included in the 1.6 release. Until then we need to encode the HTML as a Java string which means we need to escape all the double quotes with backslashes. It looks like this:

String html = 
"<form method=\"post\" action=\"wp-login.php\"" + 
"id=\"loginform\" name=\"loginform\">" +
  "<p>" +
    "<label>Username<br/>" +
    "<input type=\"text\" class=\"input\"" +
    "id=\"user_login\" name=\"log\"/></label>" +
  "</p>" +
  "<p>" +
    "<label>Password<br/>" +
    "<input type=\"password\" class=\"input\"" + 
    "id=\"user_pass\" name=\"pwd\"/></label>" +
  "</p>" +
  "<p class=\"forgetmenot\">" +
     "<label>" +
        "<input type=\"checkbox\" value=\"forever\"" + 
        "id=\"rememberme\" name=\"rememberme\"/>" +
        "Remember Me" + 
     "</label>" + 
  "</p>" +
  "<p class=\"submit\">" +
    "<input type=\"submit\" value=\"Log In\"" + 
    "id=\"wp-submit\" name=\"wp-submit\"/>" +
  "</p>" +
"</form>";

Is this really necessary?

Escaping and embedding your HTML into a Java file is not ideal and there is an alternative. GWT includes an HTML file which anchors the JavaScript GWT will use. Normally this page includes only a single script tag.

We could add the HTML for our form there, but that would mean losing modularity. As your application gets more complicated the utility of separating different functions will become clear. Breaking your HTML up into separate pieces also encourages you to keep your HTML simple and use GWT to focus on data binding. Techniques like CSS-based form layout are a good way to simplify your HTML.

Remove the Fields

The power of GWT is in its data binding. We have the HTML, but we want to use GWT to bind the data. So we take all the fields out of the HTML and we are left with this:

String html = 
"<form method=\"post\" action=\"wp-login.php\" " + 
"id=\"loginform\" name=\"loginform\">" +
  "<p>" +
    "<label>Username<br/>" +
  "</p>" +
  "<p>" +
    "<label>Password<br/>" +
  "</p>" +
  "<p class=\"forgetmenot\">" + 
    "<label>Remember Me</label>" + 
  "</p>" +
  "<p class=\"submit\">" +
  "</p>" +
"</form>";

Create Your HTMLPanel

The format is ugly, but this chunk of HTML is very manageable. We can make it a GWT widget using GWT’s HTMLPanel. Using the string of HTML we just defined to create an HTMLPanel is easy:

HTMLPanel myPanel = new HTMLPanel(html);

Add Element IDs

The HTMLPanel really is that simple. However, we have two more steps before we can add the fields back. Each of our container tags must have an ID. I’ll show you why in a moment. We also want to remove the form tag. GWT submits all forms using JavaScript so you don’t need the form tag. We replace the form tag with a div tag, add IDs, and we get this:

String html = 
"<div id=\"loginform\" name=\"loginform\">" +
  "<p id=\"username\" >" +
    "<label>Username<br/>" +
  "</p>" +
  "<p id=\"password\">" +
    "<label>Password<br/>" +
  "</p>" +
  "<p id=\"forgetmenot\" class=\"forgetmenot\">" +
    "<label>Remember Me</label>" +
  "</p>" +
  "<p id=\"submit\" class=\"submit\">" +
  "</p>" +
"</div>";

Bind the Fields

Now we are ready to bind the fields. The field binding happens by using HTMLPanel to do some very simple DOM mnipulation. We also set an ID for the TextBox’s element and apply a class (GWT calls it a style name) from our CSS. It looks like this:

TextBox user = new TextBox();
user.addStyleName("input");
user.getElement().setId("user_login");
myPanel.add(user, "username");

The last line here is where the magic happens. The HTMLPanel will add the new TextBox as a child of the element with the id username. We’ll add the rest of the fields the same way:

TextBox password = new PasswordTextBox();
password.addStyleName("input");
password.getElement().setId("user_pass");
myPanel.add(password, "password");

CheckBox forgetMeNot = new CheckBox();
forgetMeNot.getElement().setId("rememberme");
myPanel.add(forgetMeNot, "forgetmenot");

Button submit = new Button("Log In");
submit.getElement().setId("wp-submit");
myPanel.add(submit, "submit");

All of these fields are first class GWT widgets. We can submit them back to the server using AJAX calls, add listeners to fire events when the user changes them, or set their values programmatically. We have full support for any data binding we want.

Now that we have all the pieces, let’s put it together into a GWT EntryPoint. An EntryPoint is the main page for your application and it gets initialized when the onModuleLoad method is called. This method is where we need to put all the code we have.

Put It All Together

GWT is Java and in Java you must define a class. We’ll combine all of our HTML and data bound widgets into a class that implements EntryPoint. We can then add our HTMLPanel to the main page using RootPanel and add a ClickListener so we can see when the user presses the login button. The result is:

public class MyModule
implements EntryPoint, ClickListener {
  private static final String html = 
    "<div id=\"loginform\" name=\"loginform\">" +
      "<p id=\"username\" >" +
        "<label>Username<br/>" +
      "</p>" +
      "<p id=\"password\">" +
        "<label>Password<br/>" +
      "</p>" +
      "<p id=\"forgetmenot\" class=\"forgetmenot\">" +
        "<label>Remember Me</label>" +
      "</p>" +
      "<p id=\"submit\" class=\"submit\">" +
      "</p>" +
    "</div>";
  
  public void onModuleLoad() {
    HTMLPanel myPanel = new HTMLPanel(html);
    
    // The username field
    TextBox user = new TextBox();
    user.addStyleName("input");
    user.getElement().setId("user_login");
    myPanel.add(user, "username");

    // The password field
    TextBox password = new PasswordTextBox();
    password.addStyleName("input");
    password.getElement().setId("user_pass");
    myPanel.add(password, "password");

    // The forget me not checkbox
    CheckBox forgetMeNot = new CheckBox();
    forgetMeNot.getElement().setId("rememberme");
    myPanel.add(forgetMeNot, "forgetmenot");

    // The log in button
    Button submit = new Button("Log In");
    submit.getElement().setId("wp-submit");
    myPanel.add(submit, "submit");
    submit.addClickListener(this);

    /*
     * Add our panel to the page
     */
    RootPanel.get().add(myPanel);
  }

  public void onClick(Widget sender) {
    /*
     * Our button was clicked...
     */
  }
}

The results will be exactly the same as the existing WordPress login, but have full data binding support from GWT.

Tags First

This example is simple, but the technique is a powerful way to write GWT applications. Tags first. You already know what you want the HTML to look like, so make GWT generate it. This technique has some clear advantages over the standard GWT way of doing things.

  1. You get total control over the tags.
  2. You don’t have to change your CSS.
  3. The integration between designers and programmers is much easier.
  4. You can still use standard GWT widgets when you want to.

This approach also scales very well. Create whatever complex HTML you need and then add the data binding. Want to create CSS form layouts like LinkedIn? No problem. Need to dazzle your clients with websites that rival Jason Santa Maria? You can still use the fast coding of GWT!

The promise of GWT is a powerful one: stop writing JavaScript. Not: stop writing JavaScript if you don’t care how your application looks. No tool is worth it if it doesn’t do what you want.