A couple months ago, we asked the community to tell us about their GWT applications and their experience developing them. We were greatly pleased to see many responses, and lots of neat applications. In fact, we had so many responses that we needed a better way to showcase and share them with the community.

A couple months ago, we asked the community to tell us about their GWT applications and their experience developing them. We were greatly pleased to see many responses, and lots of neat applications. In fact, we had so many responses that we needed a better way to showcase and share them with the community.

Introducing the new GWT Application Gallery to save the day, now posted on the GWT homepage. Improving on the earlier GWT Application Gallery, the new gallery adds more features to make community interaction easier and application entries more meaningful. Here are some of these new features that you can look forward to:

  • An easier way to submit entries for any GWT-related tools or application that you would like to share with the community
  • A comment and rating system for others in the GWT community to rate your applications
  • More screen real estate for application screenshots and thumbnails for your application entry
  • Searchable tags that you can apply to your GWT application entry

We already have a number of entries both from the previous app gallery and newer entries from respondents to our call out a few months ago, and we'd love to hear from you too. So please, check out the new GWT App Gallery to see the kind of great applications the community has been developing, share your opinions through the comments and ratings feature, and add your own applications to the gallery.

As a sidenote, Google I/O is in full swing. In the spirit of sharing applications and development experiences, we've organized a Developer Sandbox area this year where third party developers who have used Google developer products can showcase their applications and talk about how they've created them. If you're attending Google I/O, drop by to check out some of these products live. I'll be around that area as well, so please come by to say hello.

We are pleased to announce updates to the Google API Libraries for the Google Web Toolkit  project.  The Google API Libraries for GWT project allows GWT developers to access some of Google's popular JavaScript APIs.  This release contains new bindings for two libraries:

We are pleased to announce updates to the Google API Libraries for the Google Web Toolkit  project.  The Google API Libraries for GWT project allows GWT developers to access some of Google's popular JavaScript APIs.  This release contains new bindings for two libraries:

These libraries each come with sample code and Javadoc documentation.

In addition, other libraries have been updated.  Highlights include:

  • UI Styling and full GoogleBar support for the Google Maps API.
  • Ajax Loader support integrated with Search, Maps, Language, and Visualization.
  • Formatters support, new event types, and new OrgChart features added to bindings for Google Visualization API.
  • Bugfixes for the Gears API wrappers, for a full release of support for Gears 0.4 features.
  • Locked Domain feature added and improved performance for the Gadgets API.

These updates are now available for download at the Google API Libraries for GWT  project hosted on Google Code.

Maven is a great resource that allows developers to enable dependency management within their GWT web applications. While a complete description of Maven's dependency management is beyond the scope of this article, we encourage you to read more here . Essentially, Maven allows you to modularize your GWT project, separating the reusable pieces of code (i.e. Custom Widgets or Data Transfer Objects) into their own projects while maintaining versioning. In addition, Maven allows you to incorporate several different modules without having to write/maintain a complex Ant build file.

Modularization

When developing your application you may quickly realize that it would be beneficial to separate large pieces into separate modules for easier management and reusability. We have multiple internal applications that use the same Data Transfer Objects and Custom Widgets. In our case, we found that separating these two pieces into separate modules made everyone's life easier. In order to accomplish this, we created two separate Maven modules, studyblue-data and studyblue-widgets.

Your resulting project hierarchy will look like this once its all hooked up:

Diagram illustrating a StudyBlue sample project hierarchy

Each of the new modules (data and widgets) look similar to the main project because they contain a gwt.xml file, however their project structure looks like this:

+ studyblue-data/
  + src/
    + main/
      + java/
        + com.studyblue.data/
          Data.gwt.xml
        + com.studyblue.data.client/
          Data.java
          ...
      + resources/
    + test
      + java/
      + resources/
  pom.xml

Your Data.gwt.xml file would look like this:

<module>
  <!-- Inherit the core Web Toolkit stuff. -->
  <inherits name="'com.google.gwt.user.User'/">     
  <source path="client">
</module>

Your Data.java file would be empty in most cases:

package com.studyblue.data;

import com.google.gwt.core.client.EntryPoint;

public class Data implements EntryPoint {
  
  public void onModuleLoad() {
  
  }
}

As per usual, your source code goes under the com.studyblue.data.client package. We created an additional project for studyblue-widgets similar to the one above. At this point, you should have three projects open in your Workspace (your main web app, your newly created data module, and your newly created widget module). Once you've organized your code, it's time to hook it up with your core web application via a few hooks with Maven and the gwt.xml files.

Connecting to Maven

So what is that pom.xml file all about? The first step is downloading the GWT-Maven plugin for Eclipse (which takes care of most of the heavy lifting) http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/index.html . Once you've installed the plugin, you're ready to organize your pom.xml files (one each for: data, widgets, web app).

Our studyblue-data pom.xml file looks like the combination of the following:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelversion>4.0.0</modelversion>
  <groupid>studyblue</groupid>
  <artifactid>studyblue-data</artifactid>
  <version>1.1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>studyblue gwt data</name>

This is the portion that indicates how the jar should be created. The jar's title is "[artifactId]-[version].[packaging]". The parts in red, you would subsitute with your own information. *Note: We use -SNAPSHOT to notify Maven that the jar should be updated on every build (see below).

  <repositories>
    <repository>
      <id>gwt-maven</id>
      <url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
    </repository>
  </repositories>

  <!--  include pluginRepository and repository for GWT-Maven -->
  <pluginrepositories>
    <pluginrepository>
      <id>gwt-maven-plugins</id>
      <url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
    </pluginrepository>
  </pluginrepositories>

The repositories tag tells your project where to download the gwt jars (servlet, user, etc). The pluginRepositories tag tells your project where to download the Maven-GWT plugin.

  <build>
    <plugins>
      <plugin>
        <artifactid>maven-compiler-plugin</artifactid>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactid>maven-eclipse-plugin</artifactid>
        <version>2.5.1</version>
        <configuration>
          <additionalprojectnatures>
            <projectnature>org.maven.ide.eclipse.maven2Nature</projectnature>
          </additionalprojectnatures>
          <additionalbuildcommands>
            <buildcommand>org.maven.ide.eclipse.maven2Builder</buildcommand>
          </additionalbuildcommands>
        </configuration>
      </plugin>
    </plugins>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/client/**</include>
          <include>**/*.gwt.xml</include>
        </includes>
      </resource>
    </resources>
  </build>

The build tag tells Maven what Java version you want your jar to be compiled into (1.6 in this case). The resources tag lets your project compiler know which java files should be included in the jar (i.e. ALL YOUR CODE).

  <properties>
    <gwtversion>1.5.3</gwtversion>
  </properties>

The properties tag allows us to set a variable (gwtVersion) so Maven knows which version of GWT it needs to download when compiling. When it's time to upgrade, just change the version and the rest takes care of itself.

  <dependencies>
    <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-user</artifactid>
      <version>${gwtVersion}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

The dependencies tag tells your project which jars you need to compile. In the case of the studyblue-data and studyblue-widgets modules, we reference the GWT user jar, so we need to include it. Notice it takes use of the gwtVersion variable. There are six different types of scope. The three most important are "runtime", "provided" and "compile". Runtime means "I don't need it during compilation of the jar, but I do need it when the jar is executed." Provided means "The project that depends on this module will provide the jar". Compile means "This module needs the jar immediately for compilation".

In this case, we plan on connecting the studyblue-data and studyblue-widget modules to our main web app, which will "provide" the necessary GWT jars for these modules.

    <dependency>
      <groupid>studyblue</groupid>
      <artifactid>studyblue-data</artifactid>
      <version>1.1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>

If one module needs to reference an additional module (i.e. studyblue-widgets depends on studyblue-data), you could insert the above code into studyblue-widget dependencies.

  </project>

Don't forget to close your project tag :) Make sure you generate the appropriate pom.xml for your widgets module as well.

Deployment

Alright, so you've separated your data and widgets from your main app. You built two projects and included a pom.xml file in each. Now it's time to build studyblue-data and studyblue-widgets into jars so you (and your teammates) can use them as necessary.

This part is super easy, just open command prompt or terminal and navigate to the project's root folder. Type the following:

  mvn clean deploy

That's it. Your project will be compiled with all the necessary libraries and is available for consumption by you and your teammates under the title entered above (studyblue-data-1.1.0-SNAPSHOT.jar and studyblue-widget-1.1.0-SNAPSHOT.jar).

Putting It All Together

So, you now have the two jars available, and you could just simply add them to your main web app's classpath. However, if you enable Maven on your main web app, you'll be able to take advantage of Maven's dependency management. This way you'll be able to download updated jars instantly and automatically. Additionally, assuming your main web app project is Mavenized you can include the GWT jar dependencies (servlet, user, etc) in the web app automatically.

To do this, you need to insert the following into your main web apps pom.xml below the properties tag:

  <profiles>
    <profile>
      <id>gwt-dev-windows</id>
      <properties>
        <platform>windows</platform>
      </properties>
      <activation>
        <activebydefault>true</activebydefault>
        <os>
          <family>Windows</family>
        </os>
      </activation>
    </profile>
    <profile>
      <id>gwt-dev-mac</id>
      <properties>
        <platform>mac</platform>
      </properties>
      <activation>
        <os>
          <family>mac</family>
        </os>
      </activation>
    </profile>
    <profile>
      <id>gwt-dev-linux</id>
      <properties>
        <platform>linux</platform>
      </properties>
      <activation>
        <os>
          <name>Linux</name>
        </os>
      </activation>
    </profile>
  </profiles>

The profiles tag allows our developers to use whichever GWT jars are necessary for their operating system (takes care of Windows vs. Mac vs. Linux automatically :) ). No more keeping copies of all GWT jars and native libraries in your project folder.

Finally, modify the dependencies section to look like this:

  <dependencies>
    <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-servlet</artifactid>
      <version>${gwtVersion}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-user</artifactid>
      <version>${gwtVersion}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-dev</artifactid>
      <version>${gwtVersion}</version>
      <classifier>${platform}-libs</classifier>
      <type>zip</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-dev</artifactid>
      <version>${gwtVersion}</version>
      <classifier>${platform}</classifier>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupid>studyblue</groupid>
      <artifactid>studyblue-data</artifactid>
      <version>1.1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupid>studyblue</groupid>
      <artifactid>studyblue-widgets</artifactid>
      <version>1.1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

Notice here that the <scope> for the GWT jars is "compile", which ensures they are downloaded during compilation of the web app and "provided" to the dependent modules studyblue-data and studyblue-widgets. The GWT servlet jar is only needed when the web app is executed, so we choose "runtime" here.

Don't forget your gwt.xml

In order to make sure that our main web app knows about studyblue-data and studyblue-widgets we have to include the following lines in our main app's gwt.xml file:

<inherits name='com.studyblue.data.Data' />
<inherits name='com.studyblue.widgets.Widgets' />

Reflecting Updates In Your Modules

During development, we want our main web app to reflect changes that we make in the modules (studyblue-data and studyblue-widgets), everytime we build the project. This way every developer who is working on a project that references the modules (including our main web app), can get the latest build of the jars. We use the Maven keyword "-SNAPSHOT" when versioning our modules during development (i.e. studyblue-data-1.1.0-SNAPSHOT). Snapshot is a special version that indicates a current development copy. With a SNAPSHOT version, Maven will automatically fetch the latest SNAPSHOT every time you build your project. For rapidly moving code, this can be a necessity, particularly in a team environment. When you are ready to release the code, you finalize the version by removing "-SNAPSHOT".

To update your SNAPSHOTS before executing hosted mode or compilation, run this command in your project's root directory:

mvn clean --update-snapshots

Running Hosted Mode and Compiling

As long as your Maven dependencies are added to your project's classpath, you can execute hosted mode and GWT-Compile without worry. At StudyBlue, we use the Maven plugin for Eclipse (http://m2eclipse.sonatype.org/update/ ) to add all our Maven dependencies to our classpath, update snapshots and for editing the pom.xml files.

Conclusion

Maven can be tricky to setup, but once you've got it connected to your GWT project, you'll be amazed at how efficient and modular your application can become.

  • Prefer composition to inheritance. Unnecessarily exposing implementation details is generally a bad idea, and it's no different when you are building custom widgets. In GWT terms, this means that your custom widgets should typically extend Composite.
Developers often asked what's the best way to go about building custom widgets. There are of course a number of best practices to consider when answering this question. In this post I'll highlight a few I like to start off with.
  • Prefer composition to inheritance. Unnecessarily exposing implementation details is generally a bad idea, and it's no different when you are building custom widgets. In GWT terms, this means that your custom widgets should typically extend Composite.
// Here the HorizontalPanel implementation is exposed 
// Others may come to depend on the presence of one or more inherited methods public class OverExtendedWidget extends HorizontalPanel {
  public OverExtendedWidget() {
    //...
  }
}


// The use of HorizontalPanel is a hidden implementation detail
// We are free to change the implementation without affecting others public class ConservativeWidget extends Composite {


  private final HorizontalPanel panel;


  public ConservativeWidget() {
    panel = new HorizontalPanel();
    initWidget(panel);
    // ...
  }
}
  • Conservative API. Extending Composite also ensures that you do not inadvertently expose methods inherited from the parent classes into your new widget's API. Doing so can quickly lead to other classes depending on not only your class' implementation, but also the implementation of any parent classes. Remember, you can always add to your API. It's generally impossible to take anything away without introducing a breaking change.
public class LabeledTextBox extends Composite {


  // Be wary of multiple constructors as they can quickly get out of hand
  public LabeledTextBox(String labelText) {
    // ...
  }


  public LabeledTextBox(String labelText, boolean hideUserEnteredText) {
    // ...
  }


  public LabeledTextBox(String labelText, String textBoxText, boolean hideUserEnteredText) {
    // ...
  }


  // Only expose getters and setters if you have a use case for them
  public void setLabelText(String labelText) {
    // ...
  }
  public String getLabelText() {
    // ...
  }
}
  • Recycle and reuse. When your widgets repeat themselves try to avoid mirroring that repetition in your implementation. Often it is better to compose your new widget out of smaller, reusable widgets. This can both reduce widget complexity and allows improved testability. In a future post we'll explore widget design trade offs and lighter weight alternatives to widget composition to ensure the best possible user experience, which is GWT's ultimate mission (see GWT's mission statement for details).
public class LoginPanel extends Composite {


  private final VerticalPanel container;


  // We've decomposed the Label/TextBox pair into a separate LabeledTextBox widget class
  private final LabeledTextBox usernameTextBox;
  private final LabeledTextBox passwordTextBox;


  private final Button loginButton;


  public LoginPanel() {
    container = new VerticalPanel();
    initWidget(container);


    usernameTextBox = new LabeledTextBox("Username");
    container.add(usernameTextBox);


    passwordTextBox = new LabeledTextBox("Password", true);
    container.add(passwordTextBox);



    loginButton = new Button("Login");
    container.add(loginButton);
  }


  @Override
  protected void onLoad() {
    super.onLoad();
    usernameTextBox.setFocus(true);
  }
}
  • Design for real use cases. Instead of just imagining how your API might be used, you should write actual use cases that you want to support. You can start with a few lines of code which construct and use your new widget. Once you get the hang of it, you may want to consider test-driven development, a software development method whereby you write failing tests before you implement the features and functionality to make those same tests pass. While it may feel odd to write code that uses non-existent classes and/or interfaces and doesn't even compile, it can really help to flush out design problems early on. This should also help you with your 'Conservative API' efforts since the compiler will only complain about methods you actually try to use. As a bonus you can use your IDE to help you stub out your code. Eclipse, for example, provides many different kinds of Quick Fixes.

Eclipse Quick Fix offers to create a new Java class for you.



Eclipse Quick Fix can add missing methods or make other code changes for you.


  • Use Style. Your widgets should have a default look and feel. Your widgets should also allow for easy styling so that they will fit in with the rest of the page they live on. Providing CSS class names to key DOM elements in your widget is a good start. Setting a (primary) style name in the constructor is generally a good practice as well. This allows a designer to easily use different class names for different instances of your widgets on the same page. Browse the source for some of the out of the box GWT widgets to get an idea on how to do this.
public class RadioButton extends CheckBox {


  public RadioButton(String name) {
    // ...
    setStyleName("gwt-RadioButton"); 
  }


  // ...
}
  • Clean up after yourself. If you do extend Widget directly, use onLoad()/onUnload() rather than onAttach()/onDetach() to perform any DOM attachment setup or detachment cleanup. Any JavaScript references, such as event listeners, should be cleaned up in onUnload() to avoid memory leaks. Those same references should be setup in onLoad() rather than in the widget constructor. See for example the Checkbox source code. Recall that the widget life-cycle consists of three stages (1) construction, (2) attach to DOM, (3) detach from DOM. The most common life cycle for a widget is simply 12. Since GWT is all about building AJAX applications, many of your widgets will at least see a 123 life cycle. Widgets that move around the DOM as they are manipulated on the page will likely see a 123, 23, 23, ... life cycle. A common way to be tripped up by life cycles is when you, say, move your initialization code from widget construction to the onLoad() method without realizing that onLoad() is called each time your widget is (re)attached to the DOM.
  // This method is called when a widget is attached to the browser's document
  @Override
  protected void onLoad() {
    setEventListener(inputElem, this);
    // ... 
  } 


  // This method is called when a widget is detached from the browser's document 
  @Override   protected void onUnload() {
    // Clear out the inputElem's event listener (breaking the circular
    // reference between it and the widget); avoid memory leaks
    setEventListener(inputElem, null);
    // ...
  }

I hope you enjoyed reading a few high level best practices for widget design. In a follow-up post we'll continue to look at widget design through the eyes of the GWT compiler.

Finally, I hope you join us at Google I/O where we will have a number of sessions dedicated to GWT and plenty fellow developers to talk to, both on the conference room floor and in the developer sandbox.