GWT-Working with the Google Web Toolkit (2006-05-31), informatyka, java
[ Pobierz całość w formacie PDF ]
ONJava.com: Working with the Google Web Toolkit
Published on
ONJava.com
(
)
See this
if you're having trouble printing code examples
Working with the Google Web Toolkit
by
Robert Cooper
05/31/2006
The Google Web Toolkit
(GWT) was rolled out for JavaOne 2006 at an innocuously titled session. Due to
what I assume was a timing miscommunication, the Google Blog scooped the presentation, but the impact
was no less felt.
GWT is, in essence, a JavaScript generator. The interesting thing is what this JavaScript is generated
from:
Java
. GWT takes Java code written against a special API and converts it into browser-runnable
Ajax code. If that weren't enough to make it cool, it also includes a test harness (see Figure 1) that will
execute the Java code inline with a test browser, allowing you to step-through debug (see Figure 2),
profile and unit test your Ajax front end in your favorite IDE or at the command line.
Figure 1. GWT includes a console window with hierarchical logging.
1 of 8
2006-06-02 16:36
 ONJava.com: Working with the Google Web Toolkit
Figure 2. Java execution in the test browser allows for step-through debugging of code.
As they say, "But wait! There's more!" GWT also includes a basic RPC framework for making calls back
to your server application in the form of a servlet. The
RemoteServiceServlet
allows you to implement
service methods on an implementation and expose these to your generated Ajax application. This is done
by simply adding new
public
methods to the servlet, and the GWT will handle serialization and
deserialization to and from the client. How much would you pay for a framework like this? Don't answer
yet!
GWT also includes a set of core DOM mapped classes and layouts that are more familiar to desktop
application developers, such as the
dock panel
and
horizontal panel
.
Prefabbed widgets such as
PopupPanel
for context popups,
DialogBox
for popup blocker friendly dialogs, and
StackPanel
for
Outlook-bar style displays. There is also a URI and History management system for maintaining a
bookmarkable and "back buttonable" state through your application.
Getting Started
GWT is really just an executable Java application with some hooks into
Tomcat
and either Mozilla or
MSIE under Linux and Windows, respectively (sorry Mac users, you are out of luck for now). When you
download the GWT, it comes with several sample projects, including "KitchenSink," the GWT equivalent
of SwingSet. You can run the batch file in the
samples/KitchenSink
directory to see it run. Two things
will pop up: the GWT server monitor application and browser window where you can see the application
run. Executing
java com.google.gwt.dev.GWTShell --help
with your platform's
*dev.jar
and
gwt-user.jar
will show you the options available:
Google Web Toolkit 1.0.20
GWTShell [-port port-number] [-noserver] [-logLevel level]
[-gen dir] [-out dir] [-style style] [-notHeadless] [url]
where
-port Runs an embedded Tomcat instance on the specified
port (defaults to 8888)
-noserver Prevents the embedded Tomcat server from running,
even if a port is specified
-logLevel The level of logging detail: ERROR, WARN, INFO,
TRACE, DEBUG, SPAM, or ALL
-gen The directory into which generated files will be
written for review
-out The directory to write output files into
(defaults to current)
-style Script output style: OBF[USCATED], PRETTY,
or DETAILED (defaults to OBF)
-notHeadless Causes the log window and browser windows to be
displayed. Useful for debugging.
and
url Automatically launches the specified URL
Google includes an
applicationCreator
script that will generate a set of batch files, scaffolding classes,
and directories for a new GWT project. For our purposes here, however we are going to bypass this and
start from scratch. First you will want the GWT Maven plugin installed. You can install this by unzipping
2 of 8
2006-06-02 16:36
 ONJava.com: Working with the Google Web Toolkit
the plugin project and typing
maven plugin:install-now
. Also, you will want to copy the
gwt-user.jar
to
~/.maven/repository/com.google.gwt/jars/
manually. Since this JAR needs to be included in your final
WAR file, it needs to be registered as a dependency in the Maven POM file.
Related Reading
Head Rush Ajax
By
Brett McLaughlin
Table of Contents
Index
Sample Chapter
Project Basics
GWT uses a basic structure that might seem a little alien at first, so let's take a quick tour. The code we
will be using is available as a ready-to-run application in the
Resources
section. It provides an
implementation of a simple Table class that will toggle a CSS element on a selected row and an RPC call
to fetch information for the table from the server.
First is the
[Module].gwt.xml
file. This is an XML marker in your project that maps to an
EntryPoint
class for a particular module. Think of a module as being a self contained display, like a
JFrame
. In
"Table.gwt.xml," our module is as follows:
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.totsp.gwt.client.TableEntryPoint'/>
</module>
Next, to start up our module, we need a root HTML document to run. Here we are using
src/java/com/totsp/gwt/public/Table.html
. To embed your entry point into your HTML document, you
need to include two things. First, add a
meta
tag that indicates what the module you want to include is:
<meta name='gwt:module'
content='com.totsp.gwt.Table'>
Second, at the point in the HTML where you want the GWT to start rendering, you include the
gwt.js
boilerplate JavaScript file:
<script type="text/javascript"
src="gwt.js"></script>
This will then run a default script and inspect the
gwt:module
value to decide what it needs to start up.
Also notice that you place your HTML host page, CSS files, and graphic assets in the
public
package of
your Java source tree, not in the web app. This is a little counter-intuitive, but the
GWTShell
and the
GWTCompile
steps expect to load them out of here. You can't, however, really put them in the web app
folder, because GWT will clobber them with defaults if you do.
Pretty simple so far. Now we need to start actually writing our classes. The first one is our
EntryPoint
implementation. This is what actually starts rendering stuff.
3 of 8
2006-06-02 16:36
ONJava.com: Working with the Google Web Toolkit
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
public class TableEntryPoint implements EntryPoint {
private Table table;
public void onModuleLoad() {
table = new Table( null, "myTable" );
table.setStyleName("myTable");
RootPanel.get().add(table);
getData(); //just ignore this for the moment.
}
Looking over these classes, we have a few things here. First is the
Window
class. This maps, roughly, to
what you would think of as the JavaScript
window
object. It exposes
alert()
and
getClientWidth()
among other things. The
RootPanel
is a singleton class that returns the root for placing widgets via
get()
. This singleton methodology is pretty convenient for working with, so we are going to add this to
our classes. Next is
Widget
. This is the base class for widgets and is used for event handlers, such as the
following from the "Hello" example:
Button b = new Button("Click me", new ClickListener() {
public void onClick(Widget sender) {
Window.alert("Hello, Ajax");
}
});
To start up our
EntryPoint
class, we need to override the
onModuleLoad()
method with our code to build
our display. For the purposes of this article, we are only going to use our simple
Table
class.
The
Table
class contains a very simple operation. It extends
FlexTable
, then adds itself as a listener to
itself. When a table row is clicked that isn't the header row (if there is one), it adds a CSS style name
postfixed with
-selected
to that row. Everything else is done in the CSS.
public void onCellClicked(SourcesTableEvents sender,
int row, int cell) {
this.getRowFormatter()
.removeStyleName(selectedRow, selectedStyle);
if ((source.getHeaderRow() == null) || (row > 0)) {
this.getRowFormatter()
.addStyleName(row, selectedStyle);
selectedRow = row;
}
}
The table also has a method for populating data from a
TableDataSource
. Let's look at that next.
Building the Table
Our table class here just does a pretty simple thing: draw a table from a
TableDataSource
implementation, then toggle a stylesheet class on the selected row so we can highlight it. To do this, we
are going to extend the GWT's
FlexTable
class. This is a class that represents an HTML table, but lets
the author create table cells on the fly. To populate our table we are going to use a very simple
TableDataSource
that we can fetch from our RPC servlet. For now, lets just look at the code.
The first step is to build your service interface. Ours is pretty simple:
public interface DataService extends RemoteService {
public Person[] getData();
}
4 of 8
2006-06-02 16:36
 ONJava.com: Working with the Google Web Toolkit
Next, we need to create an
Async
interface for the service. This is done entirely with naming conventions.
You need to create an interface that matches the service interface and all methods. However, instead of
return types, every method is
void
and the last argument is an
AsyncCallback
implementation, thusly:
public void myMethod( Param p..., AsyncCallback callback)
. Finally, the interface class name
should match the
RemoteService
interface name, postfixed with
Async
.
For our simple service, it looks like this:
public interface DataServiceAsync {
public void getData(AsyncCallback callback);
}
Next, you need your service implementation. This needs to extend the GWT's
RemoteServiceServlet
servlet and implement your service interface.
public class DataServlet
extends RemoteServiceServlet implements DataService {
public Person[] getData(){
//...
}
}
Whew. Almost there. Now we want to add the servlet to both the
web.xml
(so it will be there when we
deploy the war)
and
we want to add a declaration to our
Table.gwt.xml
file. This second entry tells the
GWTShell to load the servlet and also mounts it in the testbed Tomcat and generates client stubs for you.
<servlet path="/DataService"
class="com.totsp.gwt.server.DataServlet"/>
Now, we are ready to deal with the call itself. GWT
only
supports Asynchronous calls. There are a
number of technical reasons for this, notably that the most obvious path to do a synchronous call would
be to spin waiting for the response. Unfortunately, many browsers will not actually fire the
XmlHttpRequest
event until said spinning is done. But hey, this is Ajax, not Sjax. Right?
Now we add the
getData()
method to our
EntryPoint
class. To do this, we need to get a
DataServiceAsync
implementation from the
GWT
class, then create an
AsyncCallback
handler. This is a
simple interface that just has an
onSuccess()
and
onFailure()
method to handle the return state of the
callback.
private void getData(){
DataServiceAsync dataService =
(DataServiceAsync) GWT.create( DataService.class );
ServiceDefTarget endpoint = (ServiceDefTarget) dataService;
endpoint.setServiceEntryPoint("/DataService");
dataService.getData(new AsyncCallback(){
public void onSuccess(Object result) {
table.setSource(
new SimpleDataSource( (Person[]) result ) );
}
public void onFailure(Throwable caught) {
Window.alert("Unable to get data from server: "
+caught.toString());
}
});
}
Notice the unfortunate cast to
ServiceDefTarget
. Why they couldn't have made a
GWT.create(Class
clazz, String url)
method is a bit beyond me, but you gotta do it.
Now, we simply call the
setSource()
method on our table object and
voila
, the table will render itself
5 of 8
2006-06-02 16:36
Â
[ Pobierz całość w formacie PDF ]