My favorites | Sign in
Google
                
Search
for
Updated Dec 11, 2008 by scottb@google.com
WAR_Design_1_6  
Plans for changes to GWT output for 1.6.

Design Doc for 1.6 WAR structure

In 1.5, GWTShellServlet served resources directly off the classpath (for public files), or generated files from a temporary location. This has the advantage of allowing fast refresh and resource updating, and making things "easy". However, it has the downside of not leaving the user with something that's easy to deploy.

We will rectify the deployment issue in 1.6 by standardizing GWT around the "expanded WAR format". The two key principles are:

  1. The result of running the GWT compiler (and possibly some associated tools/build rules) will be an expanded WAR directory structure that can be immediately deployed to a Java Servlet Container compatible web server.
  2. Hosted mode will operate using essentially the same format, in the same directory, to ensure that hosted and compiled web applications behave the same.

In 1.6, we always dump all resources directly into the WAR directory, which the server serves directly out of. We automate in hosted mode what a build process would do. This is triggered by the Hosted Browser actually executing a selection script; the selection script (when running hosted mode) forces a hosted mode link. Subsequent GWT.create() calls may cause incremental links.

Non-Goals / Off-the-table

Proposed Simple GWT project structure

MyProject/
  build.xml                                      <ant build file with various targets to javac, gwtc, hosted, server, clean>
  src/
    <source code, GWT modules, public resources>
  war/
    MyProject.html                               <a host HTML page>
    MyProject.jsp                                <another host page>
    MyProject.css                                <non-GWT static resources>
    WEB-INF/
      web.xml                                    <contains servlet mappings>
      classes/
        <classes compiled by IDE or build rule>
      lib/
        gwt-servlet.jar
        <other server-side libs>
    qualified.ModuleName/
      qualified.ModuleName.nocache.js            <selection script>
      public_resource.gif
      generated_resource.png
      <other public and generated files>
      scripts/
        STRONGNAME1.cache.js                     <compiled script>
        STRONGNAME2.cache.js                     <compiled script>
        <other compiled scripts>
    qualified.ModuleName2/
      <as above>
  extra/
    qualified.ModuleName/
      <non-deployed linker artifacts>
    qualified.ModuleName2/
      <non-deployed linker artifacts>

Note: the extra/ subfolder will not be produced by default.

Changes in Suggested Best Practices

The most key user-facing change is that we no longer suggest that host HTML pages live in the public path of the application module. Instead, we suggest that many static resources, most especially the host HTML page that includes a GWT module, should live in the war directory as a static resource rather than on the classpath.

Command Line Options, old vs. new

In 1.5, the output level options work this way:

This situation is undesirable because it the out directory is not immediately useful without addition build rules and processing. We propose for 1.6 that the output be in standard expanded WAR format. We will retain GWTCompiler and GWTShell for backwards-compatibility with 1.5, but newly created projects will use new entry points, Compile and HostedMode.

How Hosted Mode Will Work

We will no longer use GWTShellServlet and embedded Tomcat. Instead, we will used Jetty by default, but allow other servers to be plugged in through a lightweight interface.

  1. HostedMode performs an initial link for each module specified on the command line
    1. A generated selection script is copied into war/qualified.ModuleName/
    2. The generated selection script (and other resources) will not override an existing compiled selection script; this is to prevent clobbering a compile
    3. No public or generator produced resources will be copied
  2. HostedMode starts the web server, targeting it at war/.
  3. HostedMode launches a hosted browser window for each -startupUrl specified on the command line
  4. The hosted browser requests the host HTML page from the server.
  5. The host HTML page loads the generated selection script for the included modules.
  6. The selection script (in hosted mode only) calls window.external.initModule(<moduleName>)
    1. Hosted mode triggers a new initial link, copying public resources and possibly updating the selection script
    2. If the selection script was updated, initModule() returns true, which signals the selection script to force a full-page refresh in order to load the updated selection script
  7. The selection script loads hosted.html into an IFRAME, and hosted mode continues bootstrapping as per 1.5
  8. Whenever new resources are generated from a GWT.create() resolution, an incremental link is performed
  9. If the user presses "Compile/Browse"
    1. The set of modules passed in on the command line are compiled
    2. Each module output directory, war/qualified.ModuleName/ is cleaned out
    3. Each module is linked into its module output directory
    4. A web browser then loads the host HTML page, which loads the compiled selection script
    5. The compiled selection script detects that it is not running in the hosted browser, and therefore loads web mode normally

Linker Stack Changes

The linker stack must now support hosted mode fully and correctly. When a hosted browser begins to load a GWT application, a module-session is created, and an initial link is performed into the module-session directory. This module-session is retained throughout the life of that hosted browser remaining on the page. The initial link takes only public resources as inputs, but should produce a selection script based on zero CompilationResults. In the future, we may choose to synthesize a HostedModeCompilationResult to represent the actual deferred binding properties of the browser associated with the module-session.

As the application runs, calls to GWT.create() may generate new resources. Each time new resources are generated, the linker stack will call a new relink method on all of the linkers in the stack, passing in the set of newly generated artifacts. Each linker must retain its own internal state if it needs to consider previously-encountered artifacts. The lifespan of a linker is guaranteed that each instance will be associated with exactly one module-session.

A further implication of the incremental resource generation is that the servlet container must also support loading resources that have not yet been created by the time the webapp context is instantiated.

Coordination with Eclipse Plugin

Make sure that it expects to track the list of active modules for a given project.

Deprecation Policy

The 1.6 release should deprecate the legacy entry points so that they may be removed entirely in the subsequent release. Without a forcing function, there is no incentive for users to migrate to newer entry-points, leaving them as the proverbial albatross.

Misc

Open Issues

  1. We could provide a "server reload" button on the main shell window in hosted mode. Is this worth pursuing for 1.6?
  2. How do we isolate the web app classloader to ensure same behavior in deployment?
  3. war/qualified.ModuleName/scripts/ is likely to change in 2.0 with runAsync
  4. Will this design work with Maven?

Open Tasks

  1. Make sure app creator and samples follow this structure.
  2. We need to parse user's web.xml and verify that all module <servlet> tags have been declared; if not we should warn and provide the correct text to add.

Comment by giulio.roggero, Dec 05, 2008

Hi Scott, there is a road map for this implementation?

Comment by scottb@google.com, Dec 05, 2008

Real Soon Now. Like, a week?

Comment by m.massenzio, Dec 06, 2008

+1

how did you manage to read my mind? This is exactly what I need.... :-)

Comment by danigb, Dec 09, 2008

great!! i really like this!

Comment by a.allahbaksh, Dec 13, 2008

Really good design goals. I am looking forward for the release.

Comment by srdrucker, Jan 22, 2009

A qualified.ModuleName?/ directory for GWT artifacts sounds great. However, I don't see a need to call the nocache file qualified.ModuleName?.nocache.js, it could just be nocache.js. Then, in MyProject?.html, you could just have src="qualified.ModuleName?/nocache.js" for javascript loading. For example, src="com.google.gwt.sample.Hello/nocache.js".

Comment by harald.schilly, Jan 28, 2009

looks good for me, a nice ant target would be "deploy" to upload it on the real server.

Comment by scottb@google.com, Jan 28, 2009

A user could always add one, since they actually know the details of their server deployment and how to upload it.

Comment by daniele.renda, Feb 18, 2009

What about ImageBundle?? Images have to be in src directory in the package where there is che ImageBundle? interface? Is possibile to store images (static content) in war directory and use that with Image Bundle?

Thanks

Comment by zaid.fattuhi, Feb 20, 2009

Hope that there will be a new Maven plugin which simplifies setting up gwt.

Comment by atifijazkhan, Feb 28, 2009

A quick question about 1.1 "A generated selection script is copied into war/qualified.ModuleName?/"

Will the folder for a module will always be created in the "war/" directory? What if the Launch html file is not in the root "war/" directory but is in another subdirectory?

Currently I see no option to specify the location for the module specific directory.

Comment by scottb@google.com, Mar 02, 2009

It will always be put into root war directory, there's currently not an option to deploy deeper.

Comment by matthew.mceachen, Mar 02, 2009

If you have your compiled artifacts get copied directly into "war/" alongside checked in files, how do you implement a "clean" target?

This has been solved before -- have a "source" war directory, "src/main/webapp/" (maven-style), have your war target copy the static files into a staging directory ("target/war/" or whatever), and plop the compiled artifacts there too.

Comment by scottb@google.com, Mar 02, 2009

That's correct, a more advanced setup would involve having a "source" war folder and copying it's contents into a "target" war folder; the GWT compiler would output into the "target" war folder, and you could clean just by blowing away the whole folder.

Comment by scottb@google.com, Mar 04, 2009

We're considering relaxing the constraints. See  issue #3435 .


Sign in to add a comment