The core of every GWT project is the project layout and the basic components required—host pages, entry points, and modules. To begin a GWT project, you need to create the default layout and generate the initial files. The easiest way to do this is to use the provided
Generating a project
ApplicationCreator is provided by GWT to create the default starting points and layout for a GWT project. ApplicationCreator, like the GWT shell, supports several command-line parameters, which are listed in table 1.
ApplicationCreator [-eclipse projectName] [-out dir] [-overwrite] [-ignore] className
Table 1 ApplicationCreator command-line parameters
|-eclipse||Creates a debug launch configuration for the named eclipse project|
|-out||The directory to which output files will be written (defaults to the current directory)|
|-overwrite||Overwrites any existing files|
|-ignore||Ignores any existing files; does not overwrite|
|className||The fully qualified name of the application class to be created|
To stub out an example calculator project, we’ll use ApplicationCreator based on a relative GWT_HOME path, and a className of com.manning.gwtip.calculator.client.Calculator, as follows:
It is recommended that you establish GWT_HOME as an environment variable referring to the filesystem location where you have unpacked GWT. Additionally, you may want to add GWT_HOME to your PATH for further convenience. We use GWT_HOME when referencing the location where GWT is installed and PROJECT_HOME to refer to the location of the current project.
For convenience, when referring to filesystem paths, we'll use forward slashes, which work for two-thirds of supported GWT platforms. If you are using Windows, please adjust the path separators to use backward slashes. Running ApplicationCreator as described creates the default src directory structure and the starting-point GWT file resources.
The standard directory structure
Even though it's quite simple, the GWT layout is very important because the toolkit can operate in keeping with a Convention over Configuration design approach. As we’ll see, several parts of the GWT compilation process make assumptions about the default layout. Because of this, not everything has to be explicitly defined in every instance (which cuts down on the amount of configuration required). Taking a look at the output of the ApplicationCreator script execution, you will see a specific structure and related contents, as shown in listing 1. This represents the default configuration for a GWT project.
Listing 1 ApplicationCreator output, showing the default GWT project structure:
The package name, com.manning.gwtip.calculator, is represented in the structure as a series of subdirectories in the src tree. This is the standard Java convention, and there are notably separate client and public subdirectories within.
Note that our client-side example does not use any server resources, but GWT does include the concept of a server path/package for server-side resources.
Figure 1 illustrates this default GWT project layout.
ApplicationCreator generates the structure and a required set of minimal files for a GWT project. The generated files include the XML configuration module definition, the entry point Java class, and the HTML host page. These are some of the basic GWT project concepts.
Along with the module definition, entry point, and host page, some shortcut scripts have also been created for use with the GWTShell and GWTCompiler tools. These scripts run the shell and compiler for the project. Table 2 lists all of the files created by ApplicationCreator: the basic resources and shortcut scripts needed for a GWT project.
Table 2 ApplicationCreator-generated initial project files that serve as a starting point for GWT applications
|GWT module file||ProjectName.gwt.xml||Defines the project configuration|
|Entry point class||ProjectName.java||Starting class invoked by the module|
|Host page||ProjectName.html||Initial HTML page that loads the module|
|GWTShell shortcut invoker script||ProjectName-shell.sh||Invokes GWTShell for the project|
|GWTCompiler shortcut invoker script||ProjectName-compile.sh||Invokes GWTCompiler for the project|
The starting points ApplicationCreator provides essentially wire up all the moving parts for you and stub out your project. You take it from there and modify these generated files to begin building a GWT application. If the toolkit did not provide these files via ApplicationCreator, getting a project started, at least initially, would be much more time consuming and confusing. Once you are experienced in the GWT ways, you may wind up using other tools to kick off a project: an IDE plugin, a Maven “archetype,” or your own scripts. ApplicationCreator, though, is the helpful default. The contents and structure that ApplicationCreator provides are themselves a working GWT “hello world” example. You get “hello world” for free, out of the box.
"Hello world", however, is not that interesting. The connection of all the moving parts is what is really important; how a host page includes a module, how a module describes project resources, and how an entry point invokes project code. These concepts are applicable to all levels of GWT projects—the basic ones and beyond. Understanding these parts is key to gaining an overall understanding of GWT. Next, we’ll take a closer look at each of these concepts, beginning with the host page.
Along with the script reference that loads the project resources, you can also specify several GWT-related tags in the host page. These tag options are not present in the default host page created by ApplicationCreator, but it’s still important to be aware of them. The GWT tags that are supported in a host page are listed in table 3, as a reference.
Table 3 GWT
tags supported in host pages
|gwt:module||<meta name="gwt:module" content="_module-name_">
||(Legacy, pre GWT 1.4.) Specifies the module to be loaded|
|gwt:property||<meta name="gwt:property" content="_name_=_value_">
||Statically defines a deferred binding client property|
|gwt:onPropertyErrorFn||<meta name="gwt:onPropertyErrorFn" content="_fnName_">
||Specifies the name of a function to call if a client property is set to an invalid value (meaning that no matching compilation will be found)|
|gwt:onLoadErrorFn||<meta name="gwt:onLoadErrorFn" content="_fnName_">
||Specifies the name of a function to call if an exception happens during bootstrapping or if a module throws an exception out of onModuleLoad(); the function should take a message parameter|
Thus, a host page includes a script reference that gets the GWT process started and refers to all the required project resources. The required resources for a project are assembled by the GWT compilation process, and are based on the module configuration.
To help with this large task, GWT uses modules as configuration and execution units that handle discreet areas of responsibility. Modules enable the GWT compiler to optimize the Java code it gets fed, create variants for all possible situations from a single code base, and make inheritance and property support possible.
One of the most important resources generated by the ApplicationCreator is the Module.gwt.xml module descriptor for your project. This file exists in the top-level directory of your project’s package and provides a means to define resource locations and structure.
In a default generated module file, there are only two elements: and . An element simply includes the configuration for another named GWT module in the current definition, and defines a class that kicks things off and moves from configuration to code. Table 4 provides an overview of the most common GWT module descriptor elements.
Table 4 A summary of the most common elements supported by the GWT module descriptor
||Identifies additional GWT modules that should be inherited into the current module|
||Specifies which EntryPoint class should be invoked when starting a GWT project|
||Identifies where assets that are not translatable source code, such as images and CSS files, are located|
||Injects a script element into a GWT module, ensuring it is present when inherited|
||Injects a stylesheet into a GWT module, ensuring it is present when inherited|
||Specifies the path to GWT RPC Service Servlet resources|
||Initially defines properties|
||Sets property values; for example, it is used in the UserAgent module to define the set of supported browsers|
||Specifies property value extensions; often used to specify locale information|
||Replaces components at runtime based on a decision process, such as different implementations for different browser versions|
The calculator module file is a simple default module file, with the addition of an injected stylesheet via the <stylesheet> tag. By using either the <script> or <stylesheet> tags, you can guarantee that those resources will be available with your module when it’s deployed. The difference between resource injection and simply adding a stylesheet reference, or script, to the HTML on your host page is that the module is in control. If you build libraries with GWT, or share entire projects, the host page is not distributed with your project. Users of your library will, therefore, not be using the same host page, and will not link to the same stylesheet. Script and stylesheet elements in host pages do work, but they are not certain to be present when others use your modules—injected resources are. Modules can bring other resources along with them, if needed.
Though the three lines of configuration in listing 1 may seem very simple, there is a bit more going on than meets the eye. GWT modules understand several default values for important properties. For example, the source path and public path locations are, by default, the client and public packages on the classpath, respectively. Because no other configuration is explicitly specified, our calculator example uses these defaults.
Modules are therefore significant on a number of fronts. In addition to setting configuration and properties, they also provide resources for projects, enable inheritance, give the compiler hints, and play a central role in the bootstrapping process. Once the bootstrap determines the correct permutation of an application, via the nocache script for a particular module, an entry point is invoked.
An entry point class, as we have learned, is simply the first project-specific code every GWT application invokes. This is generally where the first browser-based element is accessed, and it’s typically done with the static RootPanel.get() method. The RootPanel is a default container that is inserted directly before the HTML tag. With a reference to this panel, you can then compose your project and insert other elements from there.
The entry point class of our calculator example is a default EntryPoint implementation with the template "hello world" code removed, and a new custom widget added.
This process is the same for every GWT project. Whether you are building an entire application with multiple module inheritance, or just a single widget in a single module, the bootstrap we have discussed, from configuration to code, is the same.
This article is excerpted from Chapter 1 of GWT in Practice, by Robert Cooper and Charlie Collins, and published in May 2008 by Manning Publications.