Saturday, December 3, 2011

GWT Introduction

The Google Web Toolkit allows you to write Javascript-based web applications without having to write any Javascript yourself. It translates Java code that you write into Javascript automatically. In this informational overview, I'm going to walk you through creating a GWT application and then describe the basic components that make up a GWT application.

Install the Eclipse plugin

Google provides an Eclipse plugin you can use for developing GWT applications. This is what I'll be using here, but the raw GWT SDK is available as well for command-line junkies.

The Eclipse update URL for the plugin is:

http://dl.google.com/eclipse/plugin/<version>

where <version> is your Eclipse version (3.7, 3.6, etc).

You'll need to install these modules:

  • Google Plugin for Eclipse
  • SDKs > Google Web Toolkit SDK 2.4.0

Create a new project

Once the Eclipse plugin is installed, create a new "Web Application Project".

Enter "SimpleApp" for the project name and "com.acme.simpleapp" for the package. The package name will be the "base" package for all of the packages in your project as you'll see in a minute. If you haven't installed the Google App Engine plugin, then uncheck the "Use Google App Engine" checkbox (I was on my netbook when I wrote this, so it's hard to see in the screenshot). The Google App Engine is a cloud-based service that lets you upload your application to the web, but that's out of the scope for this article.

Running the project

When you create a new GWT project in Eclipse, it creates a sample application, so let's run it. Right click on the project folder and select "Run As > Web Application". A "Development Mode" view will appear, showing a URL.

Let's quickly take a look at the URL:

http://127.0.0.1:8888/SimpleApp.html?gwt.codesvr=127.0.0.1:9997

The web server (GWT uses jetty, a light-weight web container) runs on port 8888 (remember that "127.0.0.1" is the same as "localhost"). The "gwt.codesvr" query string parameter is how GWT is able to run the application without compiling the project into Javascript. This is called running it in "hosted mode" (which is what you'll always want to do while developing and debugging a project). If this parameter is removed, it will instead use the Javascript code that was generated the last time the project was compiled (more on compilation later). This is called running it in "web mode". We haven't compiled the project yet, so running it in web mode will throw an error because there's no Javascript code to use.

Now, load the URL in your browser. In order to run the application in hosted mode, you have to install a browser plugin, so install the plugin and then refresh the page.

After a few seconds the web page will appear, asking you to enter your name. Enter your name and click send.

A popup message will appear with some information. What it's doing here is sending a message to the server using GWT RPC, which is the main mechanism GWT uses to communicate between the client (a Javascript-powered web page) and the server (a Java web application).

Debugging the application

You can set breakpoints and debug the GWT application just like any other Java application. Just be sure to select "Debug As > Web Application" instead of "Run As > Web Application" when running the application.

Translatable vs non-translatable code

One thing to keep in mind when developing a GWT application is the idea of distinguishing between Java code that should be converted to Javascript, from the Java code that shouldn't be converted to Javascript. This is defined in the "SimpleApp.gwt.xml" file, which is a configuration file for the application.

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='simpleapp'>
  <!-- Inherit the core Web Toolkit stuff.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Inherit the default GWT style sheet.  You can change       -->
  <!-- the theme of your GWT application by uncommenting          -->
  <!-- any one of the following lines.                            -->
  <inherits name='com.google.gwt.user.theme.clean.Clean'/>
  <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>     -->

  <!-- Other module inherits                                      -->

  <!-- Specify the app entry point class.                         -->
  <entry-point class='com.acme.simpleapp.client.SimpleApp'/>

  <!-- Specify the paths for translatable code                    -->
  <source path='client'/>
  <source path='shared'/>
</module>

As you can see, the <source> tags mark the "client" and "shared" packages as Javascript-compatible, which means they will be converted to Javascript code when the application is complied.

Keep in mind that, GWT can only convert certain Java classes to Javascript (for a complete list, see the JRE Emulation Reference). So, for example, even though creating a FileOutputStream in the Java code won't throw any errors when the Java class is complied, an error will be thrown when the project is compiled to Javascript or run in hosted mode. To help you remember which Java classes are translatable, just remember that you're writing code for Javascript and there's certain things you can't do in this environment (like save files to disk, for example). As long as you keep this in mind, you won't need to refer to the JRE Emulation Reference very often.

Packages that are not defined as translatable code will run on the server as real Java code, so you can do whatever you want with them.

Source code

Let's just drill down each of the files in the "src" directory and describe what they do:

  • SimpleApp.gwt.xml: This file is called the "module definition". It contains the project's configuration settings including which Java classes are translatable to Javascript, the "entry point" class (like the "main" method for the client), and the application's look and feel.
  • GreetingService.java: An interface which defines the GWT RPC methods that are used by the client to communicate with the server.
  • GreetingServiceAsync.java: An alternate version of the GreetingService interface that the client uses to perform asynchronous communication with the server. Note that these two interfaces must remain in-sync, so any time the GreetingService interface is changed, the GreetingServiceAsync interface must also be changed.
  • SimpleApp.java: Contains all of the client-side GUI code. It is also the entry point class.
  • GreetingsServiceImpl.java: The server-side code that is called when the client sends requests to the server via GWT RPC. It provides the implementation of all of GWT RPC methods defined in GreetingService.
  • FieldVerifier.java: Contains validation code that is used on both the client and server. This is one of the advantages to using GWT--because the same code can be used for both the client and server, only one version needs to be maintained.

Client-side code

Let's quickly take a look at the client-side code. In this sample application most of the code is in one class, SimpleApp.

public class SimpleApp implements EntryPoint {

  private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

  public void onModuleLoad() {
    [...]
  }
  [...]
}

The SimpleApp class implements the EntryPoint interface and thus must implement the onModuleLoad() method. This method is where the application "starts" when the client loads it in her browser (like a "main" method). To communicate with the server over GWT RPC, an instance of the GreetingServiceAsync class is created.

Server-side code

When the client communicates with the server via GWT RPC using the GreetingServiceAsync class, the code in GreetingServiceImpl class is executed.

public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {

  public String greetServer(String input) throws IllegalArgumentException {
    [...]
  }
  [...]
}

Under the covers, this class is just a plain Java servlet, but with some GWT additions. Notably, it does the work of converting all requests and responses to JSON when sent over the wire.

The only GWT RPC method here is greetServer. It accepts a String as the request and returns a String in the response.

Compiling

When you're ready to deploy your GWT application to production, you'll want to compile it. This will translate all the client-side Java code into Javascript code, making it a fully-functional web application that you can run from a web container like Tomcat.

To do this, right click on the project folder and select "Google > GWT Compile". When it's done, just copy the "war" directory into the web container.

No comments: