Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
com/lpt/a/1664
If you are a Java software and Ajax developer, chances are the Google Web Toolkit (GWT) has already grabbed your
attention.
Google released this free toolkit, under an Apache-style license, in M ay 2006. The GWT is designed for writing Ajax
applications in the Java language. Google has initially made available beta versions for Windows and Linux, with a promise
to add a M ac OS X version later on.
This article describes the development of a simple Ajax application on M ac OS X using GWT and familiar Java tools, such
as Apache Ant, the Tomcat 5.0 servlet container, and the IntelliJ IDEA integrated development environment (the latter is a
commercial IDE). The article assumes some knowledge of Java and Ant.
I downloaded the GWT Linux beta version, wrote my application in Java, and compiled and deployed the application on
an instance of Tomcat 5.0 using an Ant build file. The Ant file runs the GWT Java-to-JavaScript compiler for me. This
"compiler" is a command-line script that executes a GWT Java class, which writes the JavaScript for the application.
Using the GWT beta involves two modes of development: host mode and web mode.
Host mode is an intermediate development step that uses an embedded GWT browser; in this mode, your compiled code
continues to run in a Java Virtual M achine (JVM ). Host mode, however, is not available to us M ac OS X users hitching a
ride on the Linux version. Host mode will be available once a M ac OS X version is released.
This article delves into some of the typical web development related tasks GWT developers are likely to confront while
creating services for Remote Procedure Calls (RPCs). RPCs are a part of a software model designed for the applications
that use service oriented architecture (SOA). These development tasks include:
Automating the development and deployment steps with a build file (the build runs the GWT compiler, then
deploys the compiler's output plus your server-side Java class files to a servlet container like Tomcat, Jetty, or
Resin).
Viewing the HTM L generated by the GWT application using Firefox's DOM Inspector.
Redesigning the widgets on the page without access to the underlying HTM L (since you are using GWT's Java API).
M aking sure the HTM L is legal markup, for instance, based on a particular XHTM L document type required by
your organization.
At Your Service
First, I'll briefly describe the service that this application creates. It is designed to illustrate the model that GWT uses.
1 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
The application displays a form in a browser, requesting that the user enter their name, age, and country of origin. When
the user submits the form by clicking a button, the application displays a server response in a textarea, without initiating a
page refresh. Figure 1 shows what the application looks like in the Safari browser.
When the user clicks the OK,Submit button after leaving a TextBox blank, for instance, Figure 2 shows the result.
2 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
Using RPC with an Ajax application eliminates the necessity to explicitly deal with XMLHttpRequest and associated server
3 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
return values, because the GWT objects handle the plumbing for you.
Each service your application defines requires two Java interfaces and one Java class. To compile these classes, you have
to make sure that the gwt-user.jar library is on your classpath (an Ant file entry takes care of that). The following code
sample shows the Java interface that defines our service.
package com.parkerriver.gwt.testapp.client;
import com.google.gwt.user.client.rpc.RemoteService;
The service interface is required to extend the GWT interface RemoteService. It defines a single method
displayResponse().
You also have to define an interface that the client, or eventual downloaded JavaScript code, will use to call this service
method. The GWT uses a callback design pattern that I will describe when I show the client code (see MyForm.java).
package com.parkerriver.gwt.testapp.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
The naming convention is part of making available a service with GWT; add the "Async" suffix to the end of the service
interface name (ShowRespService). The purpose of the AsyncCallback object, which is part of the GWT API, is to
handle the service response for the client. At any rate, its behavior will become clearer after you look at the code where it is
used. Both of these object definitions are a part of the Java code that is used to generate the application's client-side
JavaScript.
Finally, you have to define a Java class that implements the remote service interface. This class will live on the server-side
of your Ajax application.
package com.parkerriver.gwt.testapp.server;
import com.parkerriver.gwt.testapp.client.ShowRespService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.util.Date;
4 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
buf.append(serverInfo);
return buf.toString();
}
}
This class must extend RemoteServiceServlet, a GWT API object that itself extends
javax.servlet.http.HttpServlet. In other words, this class and the interface it implements has to be deployed in your
servlet container.
The Steps
Now that the service is defined, let's step back for a minute to review the application's directory structure. Google Web
Toolkit includes a command-line script called applicationCreator that will generate a skeletal project directory structure
for you. After you have unzipped the GWT download, you can find applicationCreator in the top-level directory. I
used the following command line to start out:
applicationCreator generates the ./src directory and the MyForm-compile and MyForm-shell scripts. M y Ant file
executes MyForm-compile; the other script launches host mode in the GWT scheme of things. The ./src directory includes
nested directories to match your initial package name, as Figure 4 shows.
5 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
The MyForm.gwt.xml file is a generated configuration file that GWT calls a "module." It specifies the Java class that
represents the "entry point" for your application, similar to a Java class that contains a main() method.
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.parkerriver.gwt.testapp.client.MyForm'/>
</module>
The other files or directories are artifacts of an IntelliJ Web application project, including ./classes, ./WEB-INF, and
./gwtproj.ipr, so you do not have to pay special attention to them.
In addition, the ./www directory does not appear (unless you create it yourself) until you run the GWT comp iler that
generates your application code. M y project uses the Ant file gwtproj.xml, as well as the properties defined in
gwtproj.properties. Before I show you the Ant build file, we'll take a look at the MyForm.java class that represents the
entry point for the application.
Entry Point
The MyForm.java class implements the GWT API interface EntryPoint. As a result, the class must implement the
onModuleLoad() method, which the browser's JavaScript engine calls when the browser loads your Ajax application.
In other words, the GWT compiler compiles this class into JavaScript code. The MyForm.java class sets up the form
widgets for the browser view. The class also determines the response to the users clicking the OK, Submit button. The
comments in the code describe exactly what's going on, so I won't repeat these comments in the article's text.
package com.parkerriver.gwt.testapp.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import java.util.Iterator;
6 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
//status info
private String statusId = "status";
//A Grid object; actually, an HTML table
private Grid grid = new Grid(5, 2);
//Other user interface objects
private Label nmLab = new Label();
private Label ageLab = new Label();
private Label homeLab = new Label();
private TextBox nmTxt = new TextBox();
private TextBox ageTxt = new TextBox();
private TextBox homeTxt = new TextBox();
private Button okBut = new Button();
private TextArea tarea = new TextArea();
/* This method is called when the browser loads
the application. The method sets up 3 Labels and TextBoxes; as
well as a Button and the TextArea that will display the server's
response. */
public void onModuleLoad() {
7 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
tarea.removeStyleName("warning");
}
//Textarea displays the server's return value
tarea.setText((String)result);
}
public void onFailure(Throwable caught) {
//Textarea displays any exception messages
tarea.setStyleName("warning");
tarea.setText(
"Server request raised an error; Java exception : "+
caught == null ? "An unknown exception" :
caught.getMessage());
}
};
//Call the service method, validating the form
//values first.
try{
respService.displayResponse(
getPanelTextContent(grid,true),
callback);
} catch (Exception e) {
tarea.setStyleName("warning");
tarea.setText("Server request raised an error: "+
e.getMessage());
} finally {
//Remove the status message when we are finished
//making the RPC call
showRpcStatus(false);
}
}
});
8 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
//separated by a space
return buf.toString();
}
}
}
M ost of this code deals with the GWT API. It is interesting to note that if you have to implement JavaScript DOM
programming, as in the showRpcStatus() method, you can accomplish this task in Java by using the
com.google.gwt.user.client.DOM class.
Build File
1. Compiles the Java files into the project directory's ./classes directory.
2. Executes the GWT compile script (in this case called MyForm-compile).
3. M oves the resulting code generated in the ./www directory to a larger web application already deployed on Tomcat.
4. Copies the compiled Java servlet and associated interface (ShowRespService) to that same web application.
The two Ant targets that compile the Java classes and initiate the conversion to JavaScript are designed to make the overall
build fail if these tasks raise any errors.
Ant XML
web.deploy.location=/users/bruceperry/parkerriver/gwt
web.classes.location=/users/bruceperry/parkerriver/WEB-INF/classes
The following XM L represents just the highlights from the Ant file; the entire file is linked in the resources section of this
article.
9 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
<!-- copy the Java servlet classes to the web application -->
<target name="deploy.classes" depends="gwt-compile"
description="copy classes to web directory">
<copy todir="${web.classes.location}">
<fileset dir="${gwtproj.output.dir}">
</fileset>
</copy>
</target>
You can run this Ant file from within the IDE (as in IntelliJ) or by using this command line in the directory that contains
the build file:
For the most part, after making application changes and running Ant, you can see the changes in the browser by reloading
the browser page.
Final Set-Up
10 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
The last set-up aspect you may have to know about is adding the gwt-user.jar library to the /WEB-INF/lib directory of
your web application.
I created my own JAR file minus the javax package, named it gwt-user-deploy.jar, and added it to /WEB-INF/lib. This is
because Tomcat will not load an individual web application's library if it contains the servlet API classes.
applicationCreator also creates the HTM L front end of your Ajax application, in this case called MyForm.html.
What if your application HTM L has to meet a standard such as XHTM L transitional or strict? In terms of XHTM L
transitional, I first added the required DOCTYPE to the top of MyForm.html, as well as the html tag's associated
attributes:
I then uploaded MyForm.html to the World Wide Web Consortium's HTM L validator at http://validator.w3.org/.
After running the validator, I made a few simple changes to the HTM L, such as properly closing the meta tags and adding
a: type="text/javascript" to the script tag.
However, if you want to meet the XHTM L Strict standard, then a few more complex changes may be required. For
example, the W3C's validator flagged as an "undefined element" the iframe tag that is required for GWT's history support
(providing the same functionality as a browser back button). XHTM L Strict has removed the iframe element.
This may not represent a problem for you (and may be solved by the GWT's future releases, as well as any other apparent
issues); however, you can implement alternate strategies such as extending the GWT's classes and creating your own
compliant widgets.
An issue that always arises in web development involves the visual design of the application. The project's designer wants
the page to look exactly like their creation in Adobe Illustrator, right?
Although you may not be able to achieve this eye-candy utopia while working on a comp lex Ajax project, you can use
Firefox's DOM Inspector to at least view the HTM L that your Java classes ultimately generate. Then work from there.
11 of 12 8/1/2009 10:22 AM
XML.com: Google Web Toolkit http://www.xml.com/lpt/a/1664
Figure 5: DOM Inspector provides a behind-the-scenes glimpse (Click image for full-size screen shot)
This shows that the com.google.gwt.user.client.ui.Grid object you are working with in the Java code is
implemented as an HTM L table tag. The TD tag in this table that contains the OK, Submit button is associated with a
style attribute that has the value "verticle-align:top."
This lines the button up with the top of the textarea. Here is the associated Java code in the MyForm.java class that
initiated the correct alignment:
Without this call in the code, the button floated amateurishly down around the textarea's mid-section.
Now to get only that button to align flush left with the labels above it.
Resources
12 of 12 8/1/2009 10:22 AM