GWT

This is a beta version. If you find errors, please report them or change them!

TABLE OF CONTENTS

  1. What's with all the cache/nocache stuff and weird filenames?
  2. How do I change the location of my cache/nocache HTML files?
  3. Why is my GWT-generated JavaScript gibberish?
  4. Can I speed up the GWT compiler?
  5. Is the war directory used by the GWT compiler as both an input and output directory to the compiler process?
  6. Does the new WAR output directory layout require me to use Java on the server-side?
  7. What options can be passed to the Compiler process?

Note: "Hosted mode" and "web mode" have been renamed development mode and production mode, respectively.

What's with all the cache/nocache stuff and weird filenames?

During its bootstrap process, a GWT application goes through a series of sometimes cryptically-named files. These files, generated by the GWT Compiler, usually seem strange to developers new to GWT. To effectively deploy a GWT application, however, it is necessary to understand these files so that they can be placed appropriately on the web server.

The important files produced by the GWT Compiler are:

  • <Module Name>.nocache.js
  • <alphanumeric>.gwt.rpc

Each of the items listed above is described below. However, first it's important to understand the concept of deferred binding since that notion is at the heart of the bootstrap process injected into the <Module Name>.nocache.js file, so you might want to read a bit about deferred binding before continuing.

Before explaining what each file does, it's also useful to summarize the overall bootstrap procedure for a GWT application:

  1. The browser loads and processes the host HTML page.
  2. When the browser encounters the page's <script src="<Module Name>.nocache.js"> tag, it immediately downloads and executes the JavaScript code in the file.
  3. The .nocache.js file contains JavaScript code that resolves the Deferred Binding configurations (such as browser detection, for instance) and then uses a lookup table generated by the GWT Compiler to locate one of the .cache.html files to use.
  4. The JavaScript code in .nocache.js then creates a hidden <iframe>, inserts it to the host page's DOM, and loads the .cache.html file into that iframe.
  5. The .cache.html file contains the actual program logic of the GWT application.

That's the process in a nutshell. For an example the bootstrap process for a complete GWT application, check out the Developer Guide example. The sections below describe each of the GWT application files in detail.

The .cache.html Files

The "cache" files contain your application's logic. If you were to look inside a .cache.html file, you would see that it is JavaScript code wrapped in a thin HTML wrapper. You might wonder why the GWT Compiler doesn't simply emit it as a JavaScript .js file. The reason for this is that certain browsers do not correctly handle compression of pure-JavaScript files in some circumstances. This would effectively mean that users unfortunate enough to be using such a browser would download the .js file uncompressed. Since the GWT mantra is no-compromise, high-performance AJAX code, the GWT Compiler wraps the JavaScript in an HTML file to wiggle around this browser quirk.

They are named according to the MD5 sum of their contents. This guarantees deterministic behavior by the GWT Compiler: if you recompile your application without changing code, the contents of the output will not change, and so the MD5 sums will remain the same. Conversely, if you do change your source code, the output JavaScript code will likewise change, and so the MD5 sums and thus the filenames will change.

Because of this uniqueness guarantee, it is safe (and indeed preferable) for browsers to cache these files, which is reflected in their .cache.html file extension.

The .nocache.js File

The "nocache" file is where Deferred Binding occurs. Before the application can run, any dynamically-bound code must be resolved. This might include browser-specific versions of classes, the specific set of string constants appropriate to the user's selected language, and so on. In Java, this would be handled by simply loading an appropriate service-provider class that implements a particular interface. To maximize performance and minimize download size, however, GWT does this selection up-front in the "nocache" file.

The reason the file is named ".nocache.html" is to indicate that the file should never be cached. That is, it must be downloaded and executed again each time the browser starts the GWT application. The reason it must be re-downloaded each time is that the GWT Compiler regenerates it each time, but under the same file name. If the browsers were allowed to cache the file, they might not download the new version of the file, when the GWT application was recompiled and redeployed on the server. To help prevent caching, the code in gwt.js actually appends an HTTP GET parameter on the end of file name containing a unique timestamp. The browser interprets this as a dynamic HTTP request, and thus should not load the file from cache.

The .gwt.rpc File

In previous versions of GWT, if your application used GWT RPC, the types that you wanted to serialize across the wire had to implement the IsSerializable interface. As of GWT 1.4, types that implement the java.io.Serializable interface now also qualify for serialization over RPC, with some conditions.

One of these conditions is that the types that you would like to serialize over the wire must be included in the .gwt.rpc file generated by the GWT compiler. The .gwt.rpc file serves as a serialization policy to indicate which types implementing java.io.Serializable are allowed to be serialized over the wire. For more details on this and other conditions to use Serializable types in GWT RPC, check out this FAQ.

Summary

That is the story behind the somewhat strange GWT file names. The <module>.nocache.js performs the deferred binding resolution and selects a cache file based on the execution context

How do I change the location of my cache/nocache HTML files?

The bootstrap process of a GWT application involves a <Module Name>.nocache.js file, and a number of .cache.html files. In the development mode environment, these applications are automatically placed in a war style directory based on the output directory specified in the -out argument. For instance, if the -out argument specified in your build.xml development target reads myapp, then the development mode process will read your host HTML page at /test/war/MyApp.html.

When a GWT application is deployed, however, it must coexist with the rest of the web site. To correctly integrate a GWT application into a web site's file structure, the site administrator must understand how GWT applications bootstrap. Otherwise, the files may not be at the locations where the GWT infrastructure expects to find them, and the application will not load. The details below describe each of these principle components, as well as where they should be located to properly load up your GWT application

  • The application's host HTML file (that is, the file containing the <script> tag referencing the <module>.nocache.js file) may exist anywhere on a web site. There are no constraints on this URL.
  • The location of the <module`>.nocache.js file relative to the host HTML page is not significant; the .nocache.js file attempts to locate files relative to the URL from which it was loaded, not relative to the URL of the host HTML page.
  • The .cache.html and other files generated by the GWT compiler must be located at the same path as the .nocache.js file.

Example download sequence using the GWT bootstrap model

In the GWT 1.4 bootstrap model, GWT expects to find all its files in the same path as the <module>.nocache.js file. For example, let's suppose your GWT Module's name is com.company.app.MyApp, and that the host HTML file is at http://host.domain.tld/myApp/index.html. Further suppose that the <module>.nocache.js and other files generated by the GWT compiler are in the same path as the host HTML file. With this setup, the following sequence of requests will occur:

  1. http://host.domain.tld/myApp/index.html
  2. http://host.domain.tld/myApp/MyApp.nocache.js
  3. http://host.domain.tld/myApp/CAFEBABE12345678DEADBEEF87654321.cache.html

For an example of the bootstrap sequence for a complete GWT application, check out the Developer Guide docs.

Relocating the files

The configuration above may not work in your own case. For example, for organizational reasons you might want to place the host HTML page at the root path, but place the GWT-related files at a different location, such as /gwt-files.

To relocate the GWT application files to the /gwt-files path, all you need to do is update the <script> tag referencing the <module>.nocache.js file to include the relative (or absolute) path to the file. The files generated by the GWT compiler, including the .cache.html files, must also reside at the same path as the <module>.nocache.js file.

In this case if your GWT Module is com.company.app.MyApp, the <script> tag in the host page (index.html) would be:

<script language="JavaScript" src="/gwt-files/MyApp.nocache.js"></script>

The example above would result in the following file download sequence:

  1. http://host.domain.tld/index.html
  2. http://host.domain.tld/gwt-files/MyApp.nocache.js
  3. http://host.domain.tld/gwt-files/CAFEBABE12345678DEADBEEF87654321.cache.html

Additional considerations

Usually applications will need additional content, such as images and CSS files, and of course dynamic resources such as RPC or JSON URLs. The techniques described above will change not only the path used to fetch GWT's application files, but also the value returned by the GWT.getModuleBaseURL() and GWT.getModuleBaseForStaticFiles() methods. If your application uses that method to construct URLs to additional resources, be sure that the resources are located in the appropriate directory. For example, if you remap your GWT files to '/gwt-files/', but your host page is /index.html, then the code GWT.getModuleBaseForStaticFiles() + "myImage.png" will result in the URL /gwt-files/myImage.png.

It's important to take care if your code refers to resources using GWT.getModuleBaseURL() or GWT.getModuleBaseForStaticFiles(). This is an especially common concern for those using Java Servlets, because the Servlet mapping must be set appropriately in the module XML file (.gwt.xml).

Why is my GWT-generated JavaScript gibberish?

By default, GWT obfuscates the JavaScript it produces. This is partly done to protect the intellectual property of the application you develop, but also because obfuscation reduces the size of the generated JavaScript files, making them faster to download and parse.

If you prefer not to have GWT obfuscate its output, then you can use the -style flag on the GWT Compiler. This flag has one of three possible values:

  • OBF (for obfuscated), the default
  • PRETTY, which makes the output readable to a human
  • DETAILED, which improves on PRETTY with even more detail (such as very verbose variable names)

If you are curious about what GWT's generated JavaScript is doing, then you can use -style PRETTY. On the rare occasion where you are debugging GWT's output, then -style DETAILED might be helpful.

Can I speed up the GWT compiler?

If you are compiling a large application, you may find that compiling to production mode takes a long time. One issue is that the compiler actually builds several versions of your application based on client properties for locale and browser. For deployment, this is crucial, but for everyday development, you are probably only using a single browser and locale. If that is the case, then you can take a shortcut and compile only a single permutation during the development cycle.

Creating this shortcut setup requires creating a new module and manipulating the client properties. What you need to do is to create a module that inherits from your existing module that specifies exact values for client properties that you want to nail down. Let's use Hello as an example...

  1. Create a module called HelloFirefox that inherits Hello
  2. Use <set-property> in the HelloFirefox module that explicitly sets a value for the user.agent client property. (See <define-property> in UserAgent.gwt.xml for the possible values.)
  3. Use rename-to in the HelloFirefox with the same value as in the Firefox module so the generated .nocache.js file will have the same name (see Renaming modules.)
  4. Compile the HelloFirefox module instead of the Hello module.
  5. Look in the war/<modulename>/ directory: there should be only one permutation compiled.

You can do the same thing for locale or any other client property. The subsystem that generates all those permutations is completely extensible, so this technique is a general one. You can thus keep two module XML files in parallel, one for solid development to be tested on all browsers, and another working copy with most permutations suppressed for draft code.

Hopefully this example also starts to show that the idea of a module isn't as trivial as it might seem at first. Modules play an important role letting you determine what exactly you're trying to build. You can have as many modules as you want for different configurations for the same code base. You can imagine module variations like "MySuperBigModuleWithDebuggingAndLoggingTurnedOn.gwt.xml".

Is the war directory used by the GWT compiler as both an input and output directory to the compiler process?

Starting with GWT 1.6, the compiler generates output in a directory structure following the Web Application Archive (WAR) standard layout. This feature makes it easier to deploy your application on any servlet container, like Jetty, Tomcat, or the Google App Engine Java runtime. See Chapter 9 of the Servlet 2.5 API specification for more details on the WAR standard layout.

Following the convention, developers may place their static resources, including their host HTML page, in the war/<appname> directory, where <appname> is the name you specify in your module XML file via the rename-to attribute (i.e. <module rename-to="myapp">). The question has come up as to whether the GWT compiler requires this resources to be present in the same war directory structure that will be used for output, or if it is possible to specify a separate input source that could be used to read in required resources. The answer: it is indeed possible to use a totally independent input source and only use the WAR directory uniquely for the compiler's generated output. Since the GWT build process now uses the Apache Ant build tool, all you would need to do is add a copy target in your project build script (build.xml) that will copy and place the required static resources in the final war output directory.

For example, here is the build.xml file generated by the GWT webAppCreator script:

  <target name="gwtc" depends="javac" description="GWT compile to JavaScript">
    <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
      <classpath>
        <pathelement location="src"/>
        <path refid="project.class.path"/>
      </classpath>
      <!-- add jvmarg -Xss16M or similar if you see a StackOverflowError -->
      <jvmarg value="-Xmx256M"/>
      <!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
      <arg value="com.google.gwt.sample.hello.Hello"/>
    </java>
  </target>

Let's suppose that the static resources that you want to copy over are located in the src/com/myapp/resources folder. You could define a copy target that takes these resources and copies them over to the war output directory like so:

  <target name="copyresources" description="Copy static resources to war output directory">
    <copy todir="war/myapp">
      <fileset dir="src/com/myapp/resources">
        <include name="**/*"/>
      </fileset>
    </copy>
  </target>

Lastly, update the gwtc target to depend on the newly created copyresources target:

  <target name="gwtc" depends="javac,copyresources" description="GWT compile to JavaScript">

At this point, you should be ready to go. That is, of course, if you're planning on using Java on the server-side. If you're deploying on a different server-side technology, the new WAR style directory probably isn't very interesting to you, but you can nonetheless treat the input and output directories separately, as well as extract what you need from the WAR output directory for whatever server-side your application uses.

Does the new WAR output directory layout require me to use Java on the server-side?

Like in previous versions of GWT, you can always use the server-side of your choice to deploy your GWT application. The new WAR output directory structure that the GWT compiler uses to generate output was introduced in GWT 1.6 to make it easier for developers who use Java on the server-side to deploy their applications directly from the generated output, as is the case for the Google Plugin for Eclipse.

All you need to do to deploy your GWT application your custom web server is to extract the important files generated during the GWT compilation and place them on your web server. These files are the <appname>.nocache.js and other <md5>.cache.html files. For more information on the generated files, check out this FAQ which describes them in more detail. The generated JS and HTML files are placed in the war/<appname> folder during compilation. All you need to do is copy these files to your web server's active directory, as well as any other static resources required by your application like images or stylesheets, and you're done.

What options can be passed to the Compiler process?

See GWT Compiler Options.