Making GWT better

If you are interested in understanding the internals of Google Web Toolkit (GWT), building from source, or contributing ideas or modifications to the project, then this document is for you.

  1. Introduction
    1. Licensing
    2. Why is GWT Open Source?
    3. Design Axioms
  2. The GWT Community
    1. Please Be Friendly
    2. Where to Discuss GWT
    3. How to Report a Bug
  3. Working with the Code
    1. Checking out the Source
    2. Compiling from Source
    3. Testing
  4. Contributing Code
    1. Code Style
    2. Contributor License Agreement
    3. Submitting Patches
    4. GWT Committers
  5. Contributing to Webpage & Documentation

Introduction

To start with the basics, why does GWT exist in the first place? The short answer is that GWT exists to make the web better for users. We’ve infused a slightly longer answer into our mission statement:

GWT’s mission is to radically improve the web experience for users by enabling developers to use existing Java tools to build no-compromise AJAX for any modern browser.

We spent a lot of time on that sentence and really tried to pack it with meaning. So, if you’ll indulge us, let’s explain why our mission statement is formulated the way that it is:

to radically improve
The unconventional premise of GWT (i.e. compiling to JavaScript) sets the tone for how willing we are to be open-minded about approaches that make a big impact. We are willing to invest extra consideration and work to find solutions of the "order-of-magnitude better" rather than the "good enough" variety.
the web experience
The experience we want to optimize is the web experience. The web has different DNA than desktop applications, and GWT was designed to be of the web tradition rather than providing a way of slavishly cloning desktop idioms in a browser. Sure, there is some overlap. But when there's tension, we prioritize the simple, core web concepts like hyperlinks, history, URLs, and bookmarks.
for users
As in end users. We strongly prioritize features that can make the biggest differences to end users. Obviously, we want to make developers' lives easier, too, but never at the expense of the user experience. A classic example: synchronous RPC is a Bad Idea, even though it's so much more convenient for developers.
by enabling developers
GWT is about enabling developers to do great things, not necessarily spoon-feeding them or putting them in a straightjacket. GWT strives to be easy to use without sacrificing efficiency. We generally prioritize ensuring that the basics of GWT work very well rather than adding dozens of special-purpose widgets. It's much better to provide a solid platform so that other great libraries can be built on top of GWT rather than trying to be all things to all people out of the box.
existing Java tools
We aren't trying to build technology for its own sake! We chose the Java language primarily because there already are so many great tools out there, not to mention scads of books, articles, libraries, and expertise. GWT should take advantage of those tools by integrating with them rather than trying to replace them.
no-compromise AJAX
We want great results, where "great" is defined by how much it benefits end users. Sometimes there are conflicts between what is easy for us developers and what benefits end users the most. When the two are in conflict, end user experience almost always wins.

We definitely do not view development in GWT as a form of compromise. We firmly believe that GWT should generate better JavaScript code than you would write by hand, and will generally choose to avoid making concessions to convenience if they hurt the performance of the resulting AJAX code.

GWT is not intended to be an island. Great integration with JavaScript is a must-have, as is aggressive use of each browser's best capabilities, even if it requires yucky special-case coding (in which case, we'll try to hide it behind a no-overhead library).
any modern browser
We want GWT to be as portable as it can be so long as it doesn't involve sacrificing user experience in any significant way.

So that’s what GWT is all about. It’s also useful to say what kinds of things GWT isn’t about…

Language wars
Why does GWT support the Java programming language instead of language X? In a word, tools. There are lots of good Java tools. That's the entire explanation. It isn't that we don't like language X or that we think the Java programming language is somehow superior. We just like the tools.
Being a monolithic framework
We don't like those all-or-nothing heavy "app frameworks" any more than you do. That's why we designed GWT to be made up of independently useful parts.
Hiding the browser programming model
GWT is not an attempt to abstract away the browser from you. Neither is GWT an attempt to prevent you from writing JavaScript when you want to. GWT is simply a way to give us developers some extra leverage in the form of productivity tools and the ability to create higher-level abstractions when it's useful. If you're a JavaScript guru, we hope you'll find GWT is a great way for you to package up your best JavaScript work and make it easy to reuse.
Bait and switch
Hopefully, this one is self-evident by now. We've been saying from the beginning that we had no intention to ever charge for GWT, but hopefully now you know we mean it.
Cloning traditional desktop UIs onto the web
We want to foster good UIs, which may or may not be the same things as existing desktop UIs. We're trying to be pretty circumspect about introducing features "just because" they are used often in desktop applications.

Licensing

All GWT source and pre-built binaries are provided under the Apache 2.0 license.

Why is GWT Open Source?

A good first question is, “Why wasn’t GWT open source to begin with?” Since GWT’s release in May 2006 at JavaOne, we’ve tried to stay totally focused on lowering the barrier for building AJAX apps. We weren’t quite ready to open source the whole thing immediately because we knew we had plans for major infrastructure work (like Mac OS X hosted mode), and we really wanted to encourage everyone to focus on the idea of the product itself and how to write apps instead of creating distractions having to do with GWT’s open sourceness.

GWT took off much faster than we expected, and it quickly became clear that the most sensible way to advance GWT would be to open it sooner rather than later. While we’ve never actually felt particularly stingy about keeping the source closed, now all code for the GWT Java to JavaScript compiler, the hosted mode browser, and so on can progress before your eyes. We’re very much looking forward to contributions of ideas, bug reports, and patches.

Design Axioms

We adopted these on February 17, 2006.

  • User experience is primary
  • Simplify AJAX development
    • Java debugging is non-negotiable
    • Key facilities out of the box: history, RPC, localization, and unit testing
  • The big pieces must be independently useful
    • Simple browser abstraction (i.e. using DOM without using Widget classes)
    • Widget classes available but not required (i.e. use DOM and/or JSNI)
    • Application management available but not required (e.g. history support is optional)
    • RPC available but not required
    • Java-to-JavaScript compiler is useful without the rest of the user libraries (implies JSNI and debugging aren’t tangled up with gwt-user)
  • Interoperate with existing web pages
    • Other than RPC, components operate without a GWT-specific server
    • Scriptable from JavaScript and vice-versa
    • Styling with CSS
  • Facilitate reuse of AJAX code
    • Sharing of entire components and applications via self-contained JAR files
    • Ability to publish Google Maps-style JavaScript API from Java classes
  • Optimize performance aggressively
    • Don’t do at run-time what you can do at compile-time
    • Discourage unoptimizable patterns
  • Be secure by default
    • Don’t expose services automatically

The GWT Community

The GWT community exists primarily through mailing lists, the issue tracker and, to a lesser extent, the source control repository. You are definitely encouraged to contribute to the discussion and you can also help us to keep the effectiveness of the groups high by following and promoting the guidelines listed here.

Please Be Friendly

Showing courtesy and respect to others is a vital part of the Google culture, and we strongly encourage everyone participating in GWT development to join us in accepting nothing less. Of course, being courteous is not the same as failing to constructively disagree with each other, but it does mean that we should be respectful of each other when enumerating the 42 technical reasons that a particular proposal may not be the best choice. There’s never a reason to be antagonistic or dismissive toward anyone who is sincerely trying to contribute to a discussion.

Sure, web development is serious business and all that, but it’s also a lot of fun. Let’s keep it that way. Let’s strive to be one of the friendliest communities in all of open source.

Where to Discuss GWT

As always, discuss using GWT in the official GWT (GWT) developer discussion group. There is an additional group for people to discuss any of the stuff in this document (e.g. how to build, how to submit patches) called GWT Contributors. You don’t have to actually submit code in order to sign up. Your participation itself is a valuable contribution.

How to Report a Bug

See Issue Tracking.

Working with the Code

If you want to get your hands dirty with the code inside GWT, this is the section for you.

Checking Out the Source

Checking out the GWT source is most useful if you plan to compile GWT yourself. The pre-built GWT distribution already contains all the Java source, so you don’t actually need to check it out from the repository just to debug through it. Just tweak your IDE to read source from the GWT jars.

GWT is hosted at gwt.googlesource.com, so you check out the source for GWT using a Git client as you would for any other Git project:

git clone https://gwt.googlesource.com/gwt trunk

Compiling from Source

Other than a few native libs, everything is Java source that can be built on any supported platform with the included GWT Ant build files. At the moment, you can only build the native code binaries on Linux, and even then with a bit of effort that is currently beyond the scope of this document. To keep things simple, we’ve checked in pre-built native binaries. (Yes, we know that’s unusual. But the source and makefiles are all there… it’s just a pain to doc all that and make it build in a cross-platform way.)

  1. Install Apache Ant 1.7.0 or later. We’ll assume that the ant command is in your path.
  2. Check out the GWT prerequisite tools and third-party libraries: ~/gwt$ git clone https://github.com/gwtproject/tools.git tools
  3. Check out the GWT source: ~/gwt$ git clone https://gwt.googlesource.com/gwt trunk
  4. Optionally, set an environment variable that contains the full path to the directory into which you just checked out the tools. (If the tools directory is a sibling of the GWT source directory, you don’t have to specify GWT_TOOLS.) In this example, you executed the previous command from the directory ~/gwt, so you’d type:~/gwt$ export GWT_TOOLS=~/gwt/tools
  5. Switch to the directory into which you checked out the GWT source. Let’s assume you checked it out into ~/gwt/trunk. Make sure you’re in that directory… ~/gwt$ cd ~/gwt/trunk then just invoke Ant ant
  6. The GWT build creates each binary distribution in the build/dist subdirectory of the source root directory. In this example, the distributions would be in ~/gwt/trunk/build.

Testing

Testing is very important to maintaining the quality of GWT. Unit Tests should be written for any new code, and changes should be verified to not break existing tests before they are submitted for review. To perform the tests, simply run ant test and verify that there are no failures.

Ant JUnit Issues

There is a problem, detailed at ant.apache.org, where ant cannot find the JUnit classes. The simple workaround is to either:

  • Delete ant-junit.jar from the ant lib directory (for example, /usr/share/ant/lib/)
  • Copy junit.jar into your ant lib directory

Contributing Code

Now that GWT is open source, we’re excited that it is now easier for our users to fix bugs and create new features, and we hope to get great patches from the community. Before you fire up your favorite IDE and begin hammering away at that new feature, though, please take the time to read this section and understand the process. While it seems rigorous, we want to keep a high standard of quality in the code base. Also, please be aware that we code contributors must sign a Contributor License Agreement before we can accept any code.

Code Style

To keep the source consistent, readable, diffable and easy to merge, we use a fairly rigid coding style, and all patches will be expected to conform to the style outlined here. To keep things as simple as possible, many of these style rules will be automatically verified by the GWT build; style issues that can’t be caught by the build system should be addressed during code review.

To make it easier to format your GWT code correctly, use the GWT style formatter for Eclipse (Preferences | Java > Code Style > Formatter | Import…).

In general, the GWT style is based on the standard Java conventions, except for the differences spelled out below.

For the record, we know that coding style is often a controversial topic. We acknowledge that plenty of great approaches exist out there. We’re simply trying to pick one that is at least somewhat consistent with Oracle’s Java coding conventions, codify it well, and stick to it.

Comments and Javadoc

Every file should have an Apache license header at the top, prefaced with a copyright notice. A package statement and import statements should follow, each block separated by a blank line. Next is the class or interface declaration. In the Javadoc comments, describe what the class or interface does.

/*
 * Copyright 2006 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.foo;

import com.google.bar.Blah;
import com.google.bar.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */
public class Foo {
  ...
}

Class Structure and Member Sort Order

Java types should have the following member order:

  1. Nested Types (mixing inner and static classes is okay)
  2. Static Fields
  3. Static Initializers
  4. Static Methods
  5. Instance Fields
  6. Instance Initializers
  7. Constructors
  8. Instance Methods

Members that fall into the same category (e.g. static methods) should also be sorted in this order based on visibility:

  1. public
  2. protected
  3. default
  4. private

All methods should be sorted alphabetically. Sorting is optional but recommended for fields. For example, the following class excerpt is correctly sorted:

public abstract class Foo {
  // Type declarations.
  public class FooBaz {
  }
 
  private class FooBar {
  }

  // Static field declarations.
  // Remember, fields do NOT need to be sorted.
  static String B;
  static String A;

  // Static initializer declarations.
  static {
  }

  // Static methods declarations.
  // Remember, methods do need to be sorted.
  static void aStatic() {
  }

  static void bStatic() {
  }

  // Instance field declaration.
  String bField;
  String aField;

  // Instance Initializer declarations.
  {
  }

  // Constructors declaration.
  public Foo() {
  }

  protected Foo(String s) {
  }

  Foo(int i) {
  }

  private Foo(boolean b) {
  }

  // Instance method declaration.
  public void b() {
  }

  public void c() {
  }

  protected void a() {
  }

  protected void d() {
  }

  protected void e() {
  }

  protected void f() {
  }

  String h() {
  }

  // The "abstract" keyword does not modify the position of the method.
  abstract String i();

  void j() {
  }

  private void g() {
  }
}

Indentation

We use 2-space indents for blocks. No tabs at all, anywhere.

We use 4-space indents after line wraps, including function calls and assignments. For example, this is correct (4 spaces after the newline):

Instrument i =
    new Instrument();

and this is not correct (2 spaces after the newline):

Instrument i =
  new Instrument();

Imports

The ordering of import statements is:

  • GWT imports
  • Imports from third parties (com, junit, net, org)
  • java and javax

To exactly match the IDE settings, the imports should be:

  • Alphabetical within each grouping. Capital letters are considered to come before lower case letter (e.g. Z before a).
  • There should be a blank line between each major grouping (google, com, junit, net, org, java, javax).

Line Length and Wrapping

Each line of text in your code should be at most 100 characters long. Use linefeed characters to break lines (Unix-style). There are some exceptions:

  • Java identifiers referenced from within JSNI methods can get quite long and cannot be parsed if split across lines.
  • Exception: If a comment line contains an example command or a literal URL longer than 100 characters, that line may be longer than 100 characters for ease of cut and paste.
  • Exception: Import lines can go over the limit because humans rarely see them. This also simplifies tool writing.

Acronyms in names

Treat acronyms and abbreviations as words. The names are much more readable:

Good Bad
XmlHttpRequest XMLHTTPRequest
getCustomerId getCustomerID

This style rule also applies when an acronym or abbreviation is the entire name:

Good Bad
class Html class HTML
String url; String URL;
long id; long ID;

Note that this is a reversal of an earlier, regretted decision, and much code in GWT violates this rule. While it’s not worth breaking existing APIs for stylistic concerns, all new code should treat acronyms as words.

For further justifications of this style rule, see Effective Java Item 56 (Item 38 in 1st edition) and Java Puzzlers Number 68.

Parameterized type names

Parameterized type names should be one capital letter. However, if readability demands longer names (particularly due to having multiple parameters), the name should be capitalized and have suffix “T”. In a nutshell, prefer <T> or <K, V>, and devolve to <KeyT, ValueT> if necessary.

Good Bad Tolerable
Foo<T> Foo<FooClientType>
Bar<K, V> Bar<KeyType, ValueType>
Baz<V, E, X> Baz<EventType, ErrorType, ExpressionType> Baz<EventT, ErrorT, ExpressionT>

Unit Testing

Unit tests are very important, and we strongly encourage submissions that include them, adding new unit tests for new functionality or updating existing unit tests for bug fixes.

Tests for Java classes should be placed in a parallel source tree under test and the test class name should be suffixed with Test. For example:

src/com/google/gwt/core/client/EntryPoint.java
test/com/google/gwt/core/client/EntryPointTest.java

The use of the parallel test tree has two major advantages:

  • You can do package scope testing (vs. a tests subpackage).
  • There is a clear separation between production and test code making packaging easier. This reduces the number of build breaks and the amount of time spent updating build files.

Note that there is a problem using JUnit tests with ant — a workaround is described above.

Submitting Patches

Please do submit code. Here’s what you need to do:

  1. Decide which code you want to submit. A submission should be a set of changes that addresses one issue in the GWT issue tracker. Please don’t mix more than one logical change per submittal, because it makes the history hard to follow. If you want to make a change that doesn’t have a corresponding issue in the issue tracker, please create one.
  2. Also, coordinate with team members that are listed on the issue in question. This ensures that work isn’t being duplicated and communicating your plan early also generally leads to better patches.
  3. Ensure that your code adheres to the GWT source code style.
  4. Ensure that there are unit tests for your code.
  5. Sign in to GWT’s Gerrit service and sign the Contributor License Agreement.
  6. Push your changes to Gerrit for review. The first time you will need to do some initial setup. Follow Gerrit’s documentation to create a change and upload it for review.
  7. After setting up gerrit on your system, you can push your changes for review using: git push origin HEAD:refs/for/master

Gerrit setup

Finally, to actually create an issue is slightly more involved, but most of the steps only need to be done once:

  1. Setup your HTTP Password: Go to Settings in Gerrit. Under Settings you will find “HTTP Password” and click “Obtain Password” and follow the steps to get your HTTP Password and/or to setup your .netrc file.
  2. Setup your Gerrit commit-msg hook (optional, but recommended): Gerrit provides a commit hook at https://gwt-review.googlesource.com/tools/hooks/commit-msg to automatically add Change-Id lines to your commits.
    Download this and add it to your checkout’s .git/hooks directory: curl -o .git/hooks/commit-msg https://gwt-review.googlesource.com/tools/hooks/commit-msg && chmod +x .git/hooks/commit-msg
  3. Make a change and commit it locally using git (e.g., edit a file foo and then run git commit -m "my first change" foofile). Push the commit to Gerrit for review: git push origin HEAD:refs/for/master.

If you have any problems you might want to consult the gerrit documentation on Uploading Changes

GWT Committers

The current members of the GWT engineering team are the only committers at present. In the great tradition of eating one’s own dogfood, we will be requiring each new GWT engineering team member to earn the right to become a committer by following the procedures in this document, writing consistently great code, and demonstrating repeatedly that he or she truly gets the zen of GWT.

Contributor License Agreements

Before we can accept a patch from you, you must sign a Contributor License Agreement (CLA). The CLA protects you and us.

  • If you are an individual writing original source code and you’re sure you own the intellectual property, then you’ll need to sign an individual CLA.
  • If you work for a company that wants to allow you to contribute your work to GWT, then you’ll need to sign a corporate CLA.

You can sign either CLA through GWT’s Gerrit service.

Contributing to webpage and Documentation

This webpage and the documentation hosted on it are completely written in markdown. If you find an error, want to make an improvement, write an article or do something to the webpage feel free to do so.

Here is how it works:

All the code is stored on github and can be directly edited on the web by pressing the “Edit me on Github” button. This is the easiest way to make a change, but if you are planing to make bigger changes to the website and want to test these locally first, you can clone the repository:

git clone https://github.com/gwtproject/gwt-site

The source code for this webpage will be found in src/main/markdown. You can edit existing files and add new ones. If you want to see your changes you will need to run:

mvn clean install

After that you can go to target/generated-site and see the generated site.

You can also launch the embedded Jetty server with

mvn jetty:run

and point your browser to http://localhost:8080.

If you think your change is ready to be published on gwtproject.org you can send us your changes with a pull request to http://github.com/gwtproject/gwt-site.

If you wish to contribute to the GWT code used on the site (to improve navigation), then you should

git clone https://gwt.googlesource.com/gwt-site-webapp

Global .gitignore

Since our .gitignore files don’t contain IDE or OS specific .gitignore entries you should setup your global .gitignore.

This is how you setup a global .gitignore.

Here you find a list of IDE specific global .gitignore files.