COMP 405
Spring 2014

Google Web Toolkit (GWT)

Home  Info  Owlspace  Java Resources  Eclipse Resources  SharePoint  Piazza

Having problems with GWT?  See the Known Issues and Problems below and/or the GAE How-To's page.

Google Web Toolkit (GWT) is a development toolkit used to build browser-based web applications that use GAE-based server-side processing.   The toolkit enables client-side applications to be written in Java but deployed as Javascript.   The toolkit also includes a UI designer, ala WindowBuilder, for drag-and-drop browser-based UI creation.   The toolkit also includes debugging and performance monitoring capabilities for GWT applications.

Note: GWT is included in the Google Plugin for Eclipse.   No additional installations are necessary.   Be sure to chose the GWT and GAE options when installing the Google Plugin.

GWT web pages act differently than regular web pages.   Instead of progressing to a new page in response to a user action, a GWT page acts more like a desktop application which mutates its view in response to user actions.  

Key Parts of a GWT Project

All files and folders mentioned here, unless explicitly identified otherwise, are specified relative to the root of the GWT code's package

[GWT module name].gwt.xml

 

client/[GWT module name].java

 

shared/[RPC service name].java, preferably, though in the sample code it is client/[RPC service name].java

 

shared/[RPC service name]Async.java, preferably, though in the sample code it is client/[RPC service name]ASync.java

 

server/[RPC service name]Impl.java

 

/war/[path]/[GWT Module name].html

 

/war/WEB-INF/app.yaml

 

References:

 

Making a new GWT web page

See the "GWT Wizards" topic in the Google Plugin for Eclipse documentation.

  1. Make a new GWT Module:  File/New/Other.../Google Web Toolkit/Module
  2. Make a new GWT Entry Point: File/New/Other.../Google Web Toolkit/Entry Point Class
  3. Make a new GWT HTML page: File/New/Other.../Google Web Toolkit/HTML Page

 

GWT Designer

Be sure that you have the GWT Designer configured properly before you start!

The GWT Designer can be used to edit EntryPoint classes in much the same way as WindowBuilder.  There are a few caveats to remember however:

 

Server-side processing (Remote Procedure Calls)

The Java code in a GWT module is cross-compiled into client-side Javascript.   This makes it easy to off-load a fair amount of GUI processing onto the client.   But to make a server-sdie call, one can use GWT's Remote Procedure Call (RPC) mechanism to make what is really a servlet call into what seems to be a simple method call on an client-side object.   This is conceptually the same as what Java RMI does, though a little different because a normally blocking, synchronous call must be translated into a non-blocking, asynchronous call.

To create an RPC call from a GWT client to a servlet backend, several pieces are needed:

  1. In the module's "shared" folder (be sure the shared folder is listed as a "source" in the module's .gwt.xml file!):
    1. The interface that defines the server to the client. i.e. defines what RPC calls can be made.
    2. An "Async" proxy of the above interface.   This can be auto-generated from the above interface.
  2. In the module's "server" folder (the shared folder is NOT listed in the module's .gwt.xml file because it's contents are not cross-compiled into Javascript):
  3. In the module's EntryPoint class
  4. In the app.yaml configuration

Be careful when refactoring that you don't break the relationships between the above 5 entities!

 

Returning Objects from the Server to the Client

It is critical to always remember that a GWT server is a Java program but a GWT client is a Javascript program.   Thus, any interaction between them is fundamentally a cross-language process as well as a cross-machine one.    This has several specific consequences:

  1. No returning of anonymous inner classes -- the GWT compiler will complain about not finding a specific class to serialize.  Plus, the closure issues are just going to cause trouble.
  2. Any returned objects must implement com.google.gwt.user.client.rpc.IsSerializable  -- this is the GWT equivalent of java.io.Serializable.
  3. Any returned object type must have a public no-parameter constructor -- This is because the deserializer will first call the no-parameter constructor to create an instance of the object and then proceed to set the field values.   Having an additional, parameterized constructor is fine for use by the server to easily instantiate the object.
  4. Access to contained data should be via getters and setters -- encapsulate the data.   Read-only data simply means a getter but no setter for the affected value(s).

The above restrictions are essentially the description of a Java Bean..   Because any returned data types are shared between the client and server, the code should be in the "shared" folder of the GWT module.

References:

 

System Design with GWT

Reusing common code

If multiple modules use the same operations or data or GUI elements, then one should refactor that code out into a separate module.   Note that modules are not required to have an entry point, which is just the UI portion of the module.   This is particularly useful for defining common data classes that are used for information transport between the front and backends. 

To use the common code in another modules, do the following:

  1. "Inherit" the common module by adding the following line to the .gwt.xml file of the module using it:   <inherits name="[common module root package].[common module name]">,  e.g. <inherits name="edu.rice.comp405.common.Common"/>
  2. If the utilizing module is using common RPC server functionalities, in the utilizing module's EntryPoint class, create an Async proxy for the common RPC server implementation.
  3.  Create a hybrid URL route in the app.yaml since the common code is actually imbedded in the untilizing module's Javascript.   The URL route should look like:
  - url: utilizing_module_short_name/common_module_relative_path   # e.g. user_serv/common_service
    servlet: common_server_classname   # e.g. edu.rice.comp405.common.server.CommonServerImpl
    name:   unique_name     # e.g. userCommonServerImpl

All 3 steps above must be repeated every time the common module is used in another utilizing module.

References:

 

Custom GWT Widgets

When creating a complex GUI with multiple, non-trivial panels of controls or when you want the same generic set of controls to be used in multiple places in your system, you should avoid duplicating code by creating a custom GWT widget.

To make a custom GWT widget, you need to use the rather non-obviously named GWT "UiBinder" wizard  under "New/Other.../Google Web Toolkit/UiBinder".   Give the new widget class an appropiate name and make sure that for "Create UI based on:" is set to "GWT widgets".    Deselect the "Generate sample content" because the sample code is more confusing than useful.

Custom GWT widgets are slightly different than GWT module EntryPoint classes.   Two files will be generated:

The Java code that you normally see in the "Source" tab in the GWT Designer is in the associated Java file, not the renamed "XML Source" tab.   The graphical layout editor is still on the "Design" tab.

You can add public or package private methods to the widget's Java code to enable the user of the widget to set values and otherwise interact with it.    Adding events can be a bit tricky however.

Attaching events to custom GWT widgets

When you use the GWT Designer to create an event handler for a widget, it will create the event handler in the Java code as a method rather than as an event handler installed into a widget.    The problem is that the custom widget is an encapsulated entity with regards to theparts of the system that use the widget.   You need event handlers that can communicate both with the rest of your system and the internal pieces of the widget.   There are two approaches to this problem:

  1. Make a non-private method of your widget that will install an externally supplied event  handler into the desired GUI control.
  2. Delegate to an overridden method

Known Issues and Problems

 

GWT Designer very slow to load

The first time it is invoked, the GWT Designer can take over a minute to load.    It will also eat up a large fraction of your system resources.   Subsequent loads shold be faster.   Increasing the amount of memory available to Eclipse may help, see below.

 

 "This is not a GUI class and can't be edited graphically" Error

This error will arise if you try to edit an EntryPoint class with a defined but empty onModuleLoad() method, e.g. a newly created file.   For some reason, the GWT Designer wants at least one GUI widget to be defined in the onModuleLoad() method before it can perform graphical editing.   Follow the directions above for creating some startup code for the GWT Designer to work with.

References:

Out of Memory Error

If Eclpse crashes with an "out of memory error", try the following configuration changes:

  1. Start your favorite text editor (Windows:  start "As Administrator")
  2. In the root of the Eclipse EE installation folder, open eclipse.ini
  3.  Find the -Xms and -Xmx parameters, probably at the end of the file (the exact values may be different):
    -Xms40m
    -Xmx512m
  4. Try doubling these values and see if GWT still crashes.
  5. If it still crashes, add the -XX:PermSize and -XMMaxPermSize values right after the  -Xms and -Xmx declarations:
    -Xms80m
    -Xmx1024m
    -XX:PErsmSize=512m
    -XX:MaxPermSize=1024m
  6. Adjust the parameter values until the "Out of memory" error goes away.

Google recommends the following settings:

-vmargs 
-XX:MaxPermSize=128m 
-Xms256m 
-Xmx512m

References:

SVN Errors

The Development Mode Server must be stopped when doing a commit to SVN because the development server has a hold of some temporary files that SVN will fail to commit.

One can set svn:ignore for the gwt-unitCache folder since it is just files to help the GWT compiler remember what has been compiled.

Another option is to mark the gwt-unitCache folder as "Derived" in the folder's Properties.

Removing gwt-unitCache from SVN

The best thing seems to be to set the svn:ignore before the gwt-unitCache is ever committed for the first time to SVN.   But, if you have already committed the cache to the repository at least once already, follow these steps to get SVN to ignore it:

  1. Commit everything as usual.
  2. In Eclipse, delete the entire gwt-unitCache directory.
  3. Commit the entire project again.
  4. Right-click the project root and select Team/Set Property
  5. Save everything and commit again.  

If you now do a GWT compile, the gwt-unitCache folder will automatically be recreated. but it should now show up in Eclipse's  Project Explorer with no adornments on its icon indicating any SVN status.  The cached files will not be committed to the repository anymore.

References:

 

 

 

 


© 2013 by Stephen Wong