Cherry picking bug fixes from trunk into release branch: 1014801, 1013801, 1020801, 1019801, 1003801


git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.1@9109 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/distro-source/core/src/release_notes.html b/distro-source/core/src/release_notes.html
index 85660f0..801a1b6 100644
--- a/distro-source/core/src/release_notes.html
+++ b/distro-source/core/src/release_notes.html
@@ -8,1187 +8,22 @@
             background-color: white;
             color: black;
             font-family: Arial, sans-serif;
-            font-size: small;
+            font-size: large;
             margin: 20px;
          }
-
-         li {
-            margin-bottom: 0.5em;
-         }
-
-         li div {
-            margin-top: 0.2em;
-         }
-
-         code {
-            font-size: medium;
+         a {
+            color: blue;
+            font-weight: bold;
          }
       </style></head>
 
    <body>
       <h1 style="margin-bottom: 0;">Google Web Toolkit Release Notes</h1>
-      <p style="margin-top: 5px; margin-left: 5px; font-weight: bold; font-size: 115%;">for all versions</b>
-      <ul>
-        <li><a href="#Release_Notes_Current">@GWT_VERSION@</a></li>
-        <li><a href="#Release_Notes_2_0_2">2.0.2</a></li>
-        <li><a href="#Release_Notes_2_0_1">2.0.1</a></li>
-        <li><a href="#Release_Notes_2_0_0">2.0.0</a></li>        
-        <li><a href="#Release_Notes_2_0_0_rc2">2.0.0-rc2</a></li>
-        <li><a href="#Release_Notes_2_0_0_rc1">2.0.0-rc1</a></li>
-        <li><a href="#Release_Notes_1_7_1">1.7.1</a></li>
-        <li><a href="#Release_Notes_1_7_0">1.7.0</a></li>
-        <li><a href="#Release_Notes_1_6_4">1.6.4</a></li>
-        <li><a href="#Release_Notes_1_6_3">1.6.3</a></li>
-        <li><a href="#Release_Notes_1_6_2">1.6.2</a></li>
-        <li><a href="#Release_Notes_1_5_3">1.5.3</a></li>
-        <li><a href="#Release_Notes_1_5_2">1.5.2</a></li>
-        <li><a href="#Release_Notes_1_5_1">1.5.1 (RC2)</a></li>
-        <li><a href="#Release_Notes_1_5_0">1.5.0 (RC)</a></li>
-        <li><a href="#Release_Notes_1_4_60">1.4.60</a></li>
-        <li><a href="#Release_Notes_1_4_59">1.4.59 (RC2)</a></li>
-        <li><a href="#Release_Notes_1_4_10">1.4.10 (RC)</a></li>
-        <li><a href="#Release_Notes_1_3_3">1.3.3</a></li>
-        <li><a href="#Release_Notes_1_3_1">1.3.1 (RC)</a></li>
-        <li><a href="#Release_Notes_1_2_22">1.2.22</a></li>
-        <li><a href="#Release_Notes_1_2_11">1.2.21 (RC)</a></li>
-        <li><a href="#Release_Notes_1_1_10">1.1.10</a></li>
-        <li><a href="#Release_Notes_1_1_0">1.1.0 (RC)</a></li>
-        <li><a href="#Release_Notes_1_0_21">1.0.21</a></li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_Current"></a>
-      <h2>Release Notes for @GWT_VERSION@</h2>
       <p>
-      This 2.0.3 release contains a fixes that was not included in the 2.0.2 release.
+          Release notes for the
+          <a href="http://code.google.com/webtoolkit/doc/latest/ReleaseNotes.html">Latest Version</a>
+          and <a href="http://code.google.com/webtoolkit/release-notes.html">Older Versions</a>
+          can be found on the GWT project hosting website.
       </p>
-      <h3>Noteworthy Fixed Issues</h3>
-      <ul>
-        <li>Using a PopupPanel in Internet Explorer without a history IFrame throws a NullPointerException (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4584">#4584</a>)</li>
-        <li>Opera support for History is not working (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3956">#3956</a>)</li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_2_0_2"></a>
-      <h2>Release Notes for 2.0.2</h2>
-      <p>
-      This 2.0.2 release contains a fix that was not included in the 2.0.1 release.
-      </p>
-      <h3>Noteworthy Fixed Issues</h3>
-      <ul>
-        <li>Standard.css missing new layout styles (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4429">#4429</a>)</li>
-      </ul>
-      
-      <hr/>
-      <a name="Release_Notes_2_0_1"></a>
-      <h2>Release Notes for 2.0.1</h2>
-      <p>
-      This 2.0.1 release contains fixes for bugs found in the 2.0.0 release.
-      </p>
-      <h3>Potentially breaking changes and fixes</h3>
-      <ul>
-        <li>
-        Fixed a bug in how code generators collect method arguments from generated source, which impacted the Messages interfaces generated for UiBinder template files.
-        In GWT 2.0, such argument names were incorrectly changed to ARGn. Most GWT applications will be unaffected, but external systems relying on these names will need to be updated.
-        </li>
-        <li>The development mode server will, by default, only bind to localhost which will break cross-machine debugging.  You can get the old behavior by specifying 
-        <code>-bindAddress 0.0.0.0</code>.  Please see issue (#<a
-        href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4322">4322</a>)
-        for more details.  For webAppCreator-generated ant files, you can pass
-        this with <tt>ant -Dgwt.args="-bindAddress 0.0.0.0" devmode</tt>.</li>
-        <li>The CurrencyList/CurrencyData APIs are now public - if you were relying upon these classes in their non-public location, you should only need to update your 
-        imports.</li>
-      </ul>
-
-      <h3>Noteworthy Fixed Issues</h3>
-      <ul>
-        <li>UiBinder Image class with resource attribute, removes styles on that image (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4415">#4415</a>)</li>
-      	<li>Widgets lose focus if its placed on FocusPanel (Opera, Safari) (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1471">#1471</a>)</li>
-      	<li>Remove method in SplitLayoutPanel is broken (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4217">#4217</a>)</li>
-        <li>Splitter constructor hard codes the background color of the splitter to white (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4335">#4335</a>)</li>
-        <li>Image should provide method to set alternative text (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4335">#4335</a>)</li>
-        <li>CssResource cannot parse unescaped '-', '_' in class selectors and unknown at-rules (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3946">#3946</a>)</li>
-        <li>Focusable implementation breaks ScrollPanels in Safari (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1313">#1313</a>)</li>
-        <li>RequestBuilder restricted to GET and POST (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3388">#3388</a>)</li>
-        <li>HTMLTable.Cell.getElement() calls getCellFormatter().getElement() with row and column swapped RequestBuilder restricted to GET and POST (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3757">#3757</a>)</li>
-        <li>MenuBar steals focus when hovered (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3884">#3884</a>)</li>
-        <li>TabLayoutPanel tabs don't line up properly on IE (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4447">#4447</a>)</li>
-        <li>webAppCreator produces ant build files which support the gwt.args
-        property for passing additional flags to the gwtc and devmode rules,
-        such as <tt>ant -Dgwt.args="-style PRETTY" gwtc</tt>.</li>
-      </ul>
-      <p>
-        See the GWT issue tracker for
-        <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status:Fixed,FixedNotReleased%20milestone:2_0_1&num=1000">
-        the complete list of bug fixes and enhancements</a> in this release.
-      </p>
-      <hr/>
-      <a name="Release_Notes_2_0_0"></a>
-      <h2>Release Notes for 2.0.0</h2>
-      <p>
-        This release includes some minor bug fixes found in the release candidate.
-        See <a href="doc/latest/ReleaseNotes.html">What's New in GWT 2.0</a> plus the release notes
-        for <a href="#Release_Notes_2_0_0_rc1">2.0.0-rc1</a> and <a href="#Release_Notes_2_0_0_rc2">2.0.0-rc2</a>
-        for the full list of features and bugs fixes included in the GWT 2.0.0 release.
-      </p>
-      
-      <hr/>
-      <a name="Release_Notes_2_0_0_rc2"></a>
-      <h2>Release Notes for 2.0.0-rc2</h2>
-      <h3>New Features</h3> 
-      <ul>
-        <li>
-          GWT 2.0 introduces a number of new panels, which together form a stable basis for fast and predictable
-          application-level layout. The official doc is still in progress, but for an overview please see
-          <a href="http://code.google.com/p/google-web-toolkit/wiki/LayoutDesign">Layout Design</a> on the wiki.
-          The new set of panels includes
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/RootLayoutPanel.html">RootLayoutPanel</a>,
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/LayoutPanel.html">LayoutPanel</a>,
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/DockLayoutPanel.html">DockLayoutPanel</a>,
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/SplitLayoutPanel.html">SplitLayoutPanel</a>,
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/StackLayoutPanel.html">StackLayoutPanel</a>, and
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/TabLayoutPanel.html">TabLayoutPanel</a>.
-        </li>
-        <li>
-            UiBinder now directly supports <code>LayoutPanel</code>. For example:<pre style="margin-left: 2em;">
-&lt;g:LayoutPanel&gt;
-  &lt;g:layer left='1em' width='20px'&gt;&lt;g:Label&gt;left-width&lt;/g:Label&gt;&lt;/g:Layer&gt;
-  &lt;g:layer right='1em' width='20px'&gt;&lt;g:Label&gt;right-width&lt;/g:Label&gt;&lt;/g:Layer&gt;
-  &lt;g:layer&gt;&lt;g:Label&gt;nada&lt;/g:Label&gt;&lt;/g:Layer&gt;
-&lt;/g:LayoutPanel&gt;</pre>
-        </li>
-        <li>
-          <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/Window.Navigator.html">Window.Navigator</a>
-          now provides access to the native browser's navigator object.
-        </li>
-      </ul> 
-
-      <h3>Breaking changes and known issues/bugs/problems</h3> 
-      <ul>
-        <li>
-          Windows users who have previously installed the <i>Google Web Toolkit Developer Plugin for IE</i> will have
-          to uninstall the old version. Use the following steps:
-          <ol>
-            <li>From the Windows "Start" Menu, open "Control Panel"</li>
-            <li>Select "Add/Remove Programs"</li>
-            <li>Select "Google Web Toolkit Developer Plugin for IE" then click "Uninstall"</li>
-            <li>
-              Run Internet Explorer and browse to
-              <a href="http://gwt.google.com/samples/MissingPlugin">http://gwt.google.com/samples/MissingPlugin</a>
-              to install the new  version of the plugin
-            </li>
-          </ol>
-        </li>
-        <li>
-          Running a <code>GWTTestCase</code> as compiled script was previously done using <code>-Dgwt.args="-web"</code>.
-          The <code>-web</code> argument is now deprecated in favor of <code>-prod</code>, consistent with the
-          terminology change from <i>web mode</i> to <i>production mode</i>.
-        </li>
-        <li>
-          The <code>-portHosted</code> command line argument for <code>DevMode</code> and <code>GWTTestCase</code>
-          has changed to <code>-codeServerPort</code> to be consistent with the new term <i>code server</i>.
-        </li>
-        <li>
-          The <code>junitCreator</code> command line utility has been removed.  Instead, the <code>webAppCreator</code>
-          utility takes new argument: <code>-junit <i>&lt;path-to-junit-jar&gt;</i></code>, which incorporates the
-          functionality previously in junitCreator and generates <code>ant test</code> targets.
-        </li>
-        <li>
-          When running development mode on on Chrome, any JavaScript objects that pass into Java code will
-          be assigned a new property <code>__gwt_ObjectId</code>.  This could break native code that looks
-          iterates through the properties of such an object.  To work around this issue, see this
-          <a href="http://code.google.com/p/google-web-toolkit/source/diff?old=4807&r=7063&format=side&path=/trunk/user/src/com/google/gwt/json/client/JSONObject.java">example</a>
-          of our changes to <code>JSONObject</code> (scroll to the bottom). 
-        </li>
-        <li>
-          Compile reports (formerly SOYC reports) are now generated with the <code>-compileReport</code> command
-          line flag to <code>Compiler</code>.  The generated reports are now written to the private <i>extra</i>
-          directory. If no <code>-extra</code> argument is specified, this directory defaults to <code>extras/</code>.
-          This eliminates an unlikely security risk of accidentally deploying compile reports to a publicly accessible location. 
-        </li>
-      </ul>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>
-          In UiBinder <code>&lt;ui:style&gt;</code> blocks, css class names may contain dashes.
-        </li>
-        <li>
-          Non-Java method safe characters in inline <ui:style> class names doesn't work
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4052">#4052</a>)
-        </li>
-        <li>
-          @external does not work reliably for inline styles in <ui:style>
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4053">#4053</a>)
-        </li>
-        <li>
-          Various false alarm warnings about invalid JSNI references have been fixed.
-        </li>
-        <li>
-          Various Swing UI improvements.
-        </li>
-        <li>
-          RPC calls leaking memory for IE
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4133">#4133</a>)
-        </li>
-        <li>
-          deRPC raise an Error 500 instead of propagating the correct RuntimeException in ProdMode
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=4237">#4237</a>)
-        </li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_2_0_0_rc1"></a>
-      <h2>Release Notes for 2.0.0-rc1</h2>
-      <p>
-        This release contains big changes to improve developer productivity, make cross-browser development easier, and produce faster web applications. 
-      </p>
-      
-      <h3>Things that are changing with GWT 2.0 that might otherwise be confusing without explanation</h3> 
-      <ul>
-        <li>
-          Terminology changes: We're going to start using the term "development mode" rather than the old term "hosted mode." 
-          The term "hosted mode" was sometimes confusing to people, so we'll be using the more descriptive term "development mode" from now on. 
-          For similar reasons, we'll be using the term "production mode" rather than "web mode" when referring to compiled script.
-        </li>
-        <li>
-          Changes to the distribution: Note that there's only one download, and it's no longer platform-specific. 
-          You download the same zip file for every development platform. 
-          This is made possible by the new plugin approach used to implement development mode (see below). 
-          The distribution file does not include the browser plugins themselves; those are downloaded separately the first time you use development mode in a browser that doesn't have the plugin installed. 
-        </li>
-      </ul>
-      
-      <h3>Major New Features</h3> 
-      <ul>
-        <li>
-          In-Browser Development Mode: Prior to 2.0, GWT hosted mode provided a special-purpose "hosted browser" to debug your GWT code. 
-          In 2.0, the web page being debugged is viewed within a regular-old browser. 
-          Development mode is supported through the use of a native-code plugin called the <i>Google Web Toolkit Developer Plugin</i> for many popular browsers. 
-          In other words, you can use development mode directly from Safari, Firefox, Internet Explorer, and Chrome. 
-        </li>
-        <li>
-          Code Splitting: Developer-guided code splitting with <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/core/client/GWT.html#runAsync(com.google.gwt.core.client.RunAsyncCallback)">GWT.runAsync()</a> allows you to chunk your GWT code into multiple fragments for faster startup. 
-          Imagine having to download a whole movie before being able to watch it. 
-          Well, that's what you have to do with most Ajax apps these days -- download the whole thing before using it. 
-          With code splitting, you can arrange to load just the minimum script needed to get the application running and the user interacting, while the rest of the app is downloaded as needed. 
-        </li>
-        <li>
-          Declarative User Interface: GWT's <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/uibinder/client/UiBinder.html">UiBinder</a> now allows you to create  user interfaces mostly declaratively. 
-          Previously, widgets had to be created and assembled programmatically, requiring lots of code. 
-          Now, you can use XML to declare your UI, making the code more readable, easier to maintain, and faster to develop. 
-          The Mail sample has been updated to show a practical example of using UiBinder.
-        </li> 
-        <li>
-          Bundling of resources via <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/resources/client/ClientBundle.html">ClientBundle</a>.
-          GWT introduced <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/ImageBundle.html">ImageBundle</a> in 1.4 to provide automatic spriting of images. 
-          ClientBundle generalizes this technique, bringing the power of combining and optimizing resources into one download to things like text files, CSS, and XML. 
-          This means fewer network round trips, which in turn can decrease application latency -- especially on mobile applications. 
-        </li>
-        <li>
-          Using HtmlUnit for running test cases based on <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/junit/client/GWTTestCase.html">GWTTestCase</a>: 
-          Prior to 2.0, <code>GWTTestCase</code> relied on SWT and native code versions of actual browsers to run unit tests.
-          As a result, running unit tests required starting an actual browser.          
-          As of 2.0, <code>GWTTestCase</code> no longer uses SWT or native code. 
-          Instead, it uses <i>HtmlUnit</i> as the built-in browser. 
-          Because HtmlUnit is written entirely in the Java language, there is no longer any native code involved in typical test-driven development.
-          Debugging GWT Tests in development mode can be done entirely in a Java debugger.
-        </li>
-      </ul> 
-    
-      <h3>Breaking changes and known issues/bugs/problems</h3> 
-      <ul>
-        <li>
-          Prior to 2.0, GWT tools such as the compiler were provide in a platform-specific jar (that is, with names like <code>gwt-dev-windows.jar</code>).
-          As of 2.0, GWT tools are no longer platform specific and they reside in generically-named <code>gwt-dev.jar</code>.
-          You are quite likely to have to update build scripts to remove the platform-specific suffix, but that's the extent of it. 
-        </li>
-        <li>
-          The development mode entry point has changed a few times since GWT 1.0.
-          It was originally called <code>GWTShell</code>, and in GWT 1.6 a replacement entry point called <code>HostedMode</code> was introduced.
-          As of GWT 2.0, to reflect the new "development mode" terminology, the new entry point for development mode is <code>com.google.gwt.dev.DevMode</code>.
-          Sorry to keep changing that on ya, but the good news is that the prior entry point still works. 
-          But, to really stay current, we recommend you switch to the new <code>DevMode</code> entry point.
-        </li>
-        <li>
-          Also due to the "development mode" terminology change, the name of the ant build target produced by <code>webAppCreator</code> has changed from <code>hosted</code> to <code>devmode</code>.
-          In other words, to start development mode from the command-line, type <code>ant devmode</code>.
-        </li>
-        <li>
-          HtmlUnit does not attempt to emulate authentic browser layout. 
-          Consequently, tests that are sensitive to browser layout are very likely to fail.
-          However, since <code>GWTTestCase</code> supports other methods of running tests, such as Selenium, that do support accurate layout testing, it can still make sense to keep layout-sensitive tests in the same test case as non-layout-sensitive tests.  
-          If you want such tests to be ignored by HtmlUnit, simply annotate the test methods with <code>@DoNotRunWith({Platform.Htmlunit})</code>. 
-        </li>
-        <li>
-          Versions of Google Plugin for Eclipse prior to 1.2 will only allow you to add GWT release directories that include a file with a name like <code>gwt-dev-windows.jar</code>. 
-          You can fool it by sym linking or copying gwt-dev.jar to the appropriate name. 
-        </li>
-        <li>
-          The way arguments are passed to the GWT testing infrastructure has been revamped. 
-          There is now a consistent syntax to support arbitrary "run styles", including user-written, with no changes to GWT itself.
-          For example, <code>-selenium FF3</code> has become <code>-runStyle selenium:FF3</code>. 
-          This change likely does not affect typical test invocation scripts, but if you do use <code>-Dgwt.args</code> to pass arguments to <code>GWTTestCase</code>, be aware that you may need to make some changes.
-        </li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_7_1"></a>
-      <h2>Release Notes for 1.7.1</h2>
-      <p>
-        This release adds support for Mac OS X version 10.6 (Snow Leopard) by allowing hosted mode to run with a 1.6 JRE in 32-bit
-        mode (using the -d32 flag).
-      </p>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>
-          Allow hosted mode using a 1.6 JRE with the -d32 flag
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3843">#3843</a>, 
-          <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3998">#3998</a>)
-        </li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_7_0"></a>
-      <h2>Release Notes for 1.7.0</h2>
-      <p>
-        This release adds explicit support for Internet Explorer 8, Firefox 3.5, and Safari 4 as well as a few high-priority bug fixes.
-        In all other respects, it is very similar to GWT 1.6.
-        Note, however, that this release is version 1.7.0 rather than version 1.6.5 to signify a potentially breaking change for libraries 
-        that use deferred binding to specialize code based on user agent (see the next section for technical details).
-      </p>
-      <h3>Potentially breaking changes and fixes</h3>
-      <ul>
-        <li>
-          This release includes explicit support for IE8, which has some significant behavioral changes from prior versions of IE.
-          These changes are great enough that the new value <code>ie8</code> has been added for the <code>user.agent</code> deferred binding client property.
-          If you have deferred binding rules (i.e. <code>&lt;replace-with&gt;</code> or <code>&lt;generate-with&gt;</code>) or property providers 
-          that are sensitive to <code>user.agent</code>, you may need to update them to account for the <code>ie8</code> value. 
-          For more information, see the <a href="http://code.google.com/p/google-web-toolkit/wiki/IE8Support">technical notes</a>.
-        </li>
-      </ul>
-
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>
-          Updated GWT libraries to support IE8 
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3558">#3558</a>, 
-          <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3329">#3329</a>)
-        </li>
-        <li>Native exception in Node.is() (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3644">#3644</a>)</li>
-        <li>
-          Incorrect firing of two click events from CheckBox and a related issue 
-          (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3508">#3508</a>,  
-          <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3679">#3679</a>)
-        </li>
-        <li>Compiler java.lang.StackOverflowError if you don't use -Xss to set a stack size (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3510">#3510</a>)</li>
-        <li>Mouse wheel in FF3 (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=2902">#2902</a>)</li>
-        <li>GWT outputs expressions too long for WebKit (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3455">#3455</a>)</li>
-        <li>java.sql.Date.valueOf error (<a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3731">#3731</a>)</li>
-        <li>Added a workaround for Firefox 3.5 regression (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=497780">bugzilla #497780</a>)</li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_6_4"></a>
-      <h2>Release Notes for 1.6.4</h2>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>The classpath in the scripts created by junitCreator was updated to refer to <code>/war/WEB-INF/classes</code> rather than <code>/bin</code>.</li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_6_3"></a>
-      <h2>Release Notes for 1.6.3 (RC2)</h2>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>Various <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3496">servlet classpath issues</a> introduced in 1.6.2 are resolved.</li>
-        <li>JSP compilation should work out of the box in hosted mode.</li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_6_2"></a>
-      <h2>Release Notes for 1.6.2 (RC)</h2>
-      <p>
-         Please see <a href="http://code.google.com/webtoolkit/doc/1.6/ReleaseNotes_1_6.html">What's new in GWT 1.6?</a> (online)
-      </p>
-
-      <hr/>
-      <a name="Release_Notes_1_5_3"></a>
-      <h2>Release Notes for 1.5.3</h2>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>RPC requests no longer fail on the embedded Android web browser</li>
-        <li>Leaf <code>TreeItems</code> now line up with their non-leaf siblings</li>
-        <li>Removing the last child node from a <code>TreeItem</code> no longer creates extra margins on the left</li>
-        <li><code>HTTPRequest</code> no longer uses POST instead of GET on some IE installs because of incorrect XHR selection</li>
-        <li>Compiler now uses a more reliable check to prevent methods with local variables from being inlined</li>
-        <li><code>getAbsoluteTop()/Left()</code> can no longer return non-integral values</li>
-        <li><code>Time.valueOf()</code> no longer fails to parse <code>"08:00:00"</code> or incorrectly accepts <code>"0xC:0xB:0xA"</code>.</li>
-      </ul>
-      <p>
-        See the GWT issue tracker for
-        <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%2CFixedNotReleased%20milestone%3A1_5_3&num=1000">
-        the complete list of bug fixes and enhancements</a> in this release.
-      </p>
-
-      <hr/>
-      <a name="Release_Notes_1_5_2"></a>
-      <h2>Release Notes for 1.5.2</h2>
-      <h3>Potentially breaking changes and fixes</h3>
-      <ul>
-        <li><code>History.onHistoryChanged()</code> has been added back (it was missing from 1.5 RC2) but is now deprecated.  Application startup should be handled by calling the new <code>History.fireCurrentHistoryState()</code>.</li>
-        <li>Fields marked <code>final</code> in serializable types will now generate a warning; the fact that they were not being serialized was a source of confusion.  Mark such fields both <code>final</code> and <code>transient</code> to avoid the warning.</li>
-        <li>Instance methods on overlay types cannot be accessed from JSNI.  (This used to work in hosted mode, but failed at runtime in web mode.)</li>
-        <li>The hosted mode server no longer serves <code>hosted.html</code> from a module's public path; instead the file is read directly from the classpath.  This file is tightly coupled with the hosted mode implementation and was not meant to be user overridable.</li>
-      </ul>
-      <h3>General Enhancements</h3>
-      <ul>
-        <li><code>Collections.unmodifiableSortedSet()</code> and <code>Collections.unmodifiableSortedMap()</code> are now implemented.</li>
-        <li>The new <code>Accessibility</code> class enables widget authors to add ARIA support to their widgets.  Many GWT widgets come with ARIA support by default.</li>
-        <li>Improved exception stack traces in hosted mode when JSNI stack frames are present.</li>
-      </ul>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>Fixed the relationship between the coordinates returned by <code>Element.getAbsoluteLeft/Top()</code> and <code>Event.getClientX/Y()</code>.  <code>Document.getBodyOffsetLeft/Top()</code> can be used to account for the difference between these two coordinate systems.</li>
-        <li><b>Ctrl-Z</b> should correctly perform an undo operation in RichTextArea on IE.</li>
-      </ul>
-      <p>
-        See the GWT issue tracker for
-        <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%2CFixedNotReleased%20milestone%3A1_5_Final&num=1000">
-        the complete list of bug fixes and enhancements</a> in this release.
-      </p>
-
-      <hr/>
-      <a name="Release_Notes_1_5_1"></a>
-      <h2>Release Notes for 1.5.1 (RC2)</h2>
-      <h3>Support for Standards Mode</h3>
-      <p>
-      GWT 1.5 adds significantly more support for standards mode applications, but some widgets (especially those with table based layouts) may not behave as expected.  The low level standards mode bugs (such as with <code>getAbsoluteLeft/Top()</code>) have been addressed, but some of the constructs that our widgets rely on do not work in standards mode.  For example, you cannot set the height and width of a widget relative to its parent if its parent is a table cell, and <code>StackPanel</code> takes up much more vertical space than it should in Internet Explorer.  All of our samples have been reverted back to quirks mode, and the <code>applicationCreator</code> defaults to quirks mode when creating a new GWT app.
-      </p>
-      <p>
-      You can still use standards mode for your GWT app, but please be aware that you may notice some layout issues.  If you are switching an app from quirks mode to standards mode, your CSS styles might be applied differently, which could also affect your application.  We will continue to address standards mode support in future GWT releases.
-      </p>
-      <h3>Potentially breaking changes and fixes</h3>
-      <ul>
-        <li><code>DOM.eventGetClientX/Y()</code> now takes into account the margin and border of the body element</li>
-        <li>In hosted mode, all <code>DOM.eventGetXXX()</code> methods now assert that the requested attribute is reliable across all supported browsers.  This means that attempting to retrieve an attribute for an event that does not support that attribute will now throw an assertion error instead of returning a coerced value.  Most notably, the click event throws an assertion error if you attempt to get the mouse button that was clicked.</li>
-        <li>The return value of <code>DOM.eventGetXXX()</code> methods are now coerced to 0 instead of -1 in web mode.  In hosted mode, an assertion error will be thrown if the attribute is not defined for the given event, as described in the previous bullet.</li>
-        <li>Opera specific code has been upgraded to work with Opera 9.5, but may not work with older versions of Opera as we only support the most recent release.  Specifically, some widgets may not be able to receive focus.</li>
-        <li>Calls to <code>History.newItem()</code> now trigger an <code>onHistoryChanged()</code> event synchronously instead of asynchronously</li>
-      </ul>
-      <h3>General Enhancements</h3>
-      <ul>
-        <li>Added support for the <code>contextmenu</code> event, which allows users to detect and override the browser's default context menu</li>
-        <li>Improved performance of <code>NumberFormat</code></li>
-        <li>Added support for altering the number of decimals in a currency in <code>NumberFormat</code></li>
-        <li>Improved performance of Animations</li>
-        <li>Improved the appearance of the default GWT style themes</li>
-        <li>Improved the Showcase sample with more robust examples and more language translations</li>
-        <li><code>FormPanel</code> can now wrap an existing form and still submit it to a hidden iframe</li>
-      </ul>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li><code>DOM.getAbsoluteLeft/Top()</code> and <code>DOM.eventGetClientX/Y()</code> no longer log an exception to the console in Firefox 3</li>
-        <li>Fixed a memory leak in Internet Explorer</li>
-        <li><code>DOM.getAbsoluteLeft/Top()</code> now takes into account the margin and border of the target element in Safari 3</li>
-        <li>Fixed some bugs associated with history support</li>
-      </ul>
-      <p>
-        See the GWT issue tracker for
-        <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_5_RC2%20type%3Adefect&num=1000">
-        the complete list of bug fixes and enhancements</a> in this release.
-      </p>
-
-      <hr/>
-      <a name="Release_Notes_1_5_0"></a>
-      <h2>Release Notes for 1.5.0 (RC)</h2>
-      <p>
-      This release candidate is, in a word, huge. Rather than including all the details here, please see <a href="http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&s=google-web-toolkit-doc-1-5&t=WhatsNewinGWT15">What's New in GWT 1.5?</a> for full details. The main thing you'll want to know is that GWT 1.5 supports the Java 5 language features (generics, enumerated types, annotations, etc.). But check out the full notes, because there's a lot of great stuff!
-      </p>
-
-      <hr/>
-      <a name="Release_Notes_1_4_60"></a>
-      <h2>Release Notes for 1.4.60</h2>
-      <p>
-      This release has only a couple of minor changes from <a href="#Release_Notes_1_4_59">1.4.59</a>.
-      </p>
-      <ul>
-        <li>Fixed a bug in the benchmarking that prevented source code from showing up in reports.</li>
-        <li>Fixed a bug in the hosted mode servlet context emulation where getResource() would fail to
-        find a file in a module's public path.</li>
-        <li>Compiler output files of the form <code><i>module</i>.cache.html</code> used to contain html
-        intended as a helpful note to a developer.  This message has now been removed because screen
-        readers and some browsers would display this content to end users.</li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_4_59"></a>
-      <h2>Release Notes for 1.4.59 (RC2)</h2>
-      <p>
-      This release includes numerous bugfixes and a few important changes.  If you are upgrading from GWT 1.3.3, you
-      are strongly encouraged to read the <a href="#Release_Notes_1_4_10">release notes for 1.4.10</a> first.
-      </p>
-
-      <h3>New Features</h3>
-      <ul>
-        <li><a href="doc/html/com.google.gwt.user.client.DOM.html#eventGetCurrentEvent()">DOM.eventGetCurrentEvent()</a> now provides
-        global access to the current Event object. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1309">#1309</a>)</li>
-        <li><a href="doc/html/com.google.gwt.user.client.ui.PopupPanel.html#setPopupPositionAndShow(com.google.gwt.user.client.ui.PopupPanel.PositionCallback)">PopupPanel.setPopupPositionAndShow(PopupCallback callback)</a>
-        now provides now provides a simpler and bulletproof way to control the layout of popups. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1120">#1120</a>, <a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1243">#1243</a>)</li>
-        <li>The <a href="doc/html/com.google.gwt.user.client.ui.SuggestionHandler.html">SuggestionHandler</a> interface
-        can be used to respond to the user selecting a suggstion in the 
-        <a href="doc/html/com.google.gwt.user.client.ui.SuggestBox.html">SuggestBox</a>. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1086">#1086</a>)</li>
-        <li><a
-          href="doc/html/java.util.Collection.html">Collection.toArray(Object[])</a>
-        is now implemented. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=695">#695</a>)</li>
-        <li>If you have it installed, <a href="http://gears.google.com/">Google Gears</a> is now accessible in hosted mode
-        (Windows only). (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1252">#1252</a>)</li>
-      </ul>
-
-      <h3>General Changes</h3>
-      <ul>
-        <li>Startup is now faster and more reliable. In particular,
-        <a href="doc/html/com.google.gwt.core.client.EntryPoint.html#onModuleLoad()">onModuleLoad()</a> is now called as soon
-        as the DOM is ready, which will generally be before the page's body.onload() event is fired. This allows your application
-        to startup before certain resources (such as images) are fully loaded.</li>
-        <li>Linux hosted mode should be less crashy. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1105">#1105</a>, <a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1281">#1281</a>, <a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1358">#1358</a>)</li>
-        <li>An important discussion of HTTP headers, caching, and HTTPS has been added to the 
-        <a
-          href="doc/html/com.google.gwt.user.client.ui.ImageBundle.html">ImageBundle</a>
-        documentation. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1172">#1172</a>)</li>
-        <li><a href="doc/html/com.google.gwt.user.client.ui.PopupPanel.html#center()">PopupPanel.center()</a> now causes
-        the popup to be shown as well as centered. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1120">#1120</a>)</li>
-        <li><a href="doc/html/com.google.gwt.user.client.ui.RichTextArea.html">RichTextArea</a> underwent number of
-        bugfixes and should be stable now. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1130">#1130</a>, <a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1214">#1214</a>, <a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1276">#1276</a>)</li>
-        <li>New <a href="doc/html/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html">RPC</a> warnings
-          <ul>
-            <li>Warn if a non-checked exception is used in the throws clause of a RemoteService method.</li>
-            <li>Warn if no concrete, serializable subclasses can be found for a given type declared in a
-            RemoteService interface.</li>
-          </ul>
-        </li>
-        <li><a href="doc/html/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html">RPC</a> now generates a serialization
-        policy file during compilation.  The serialization policy file contains a whitelist of allowed types which may be
-        serialized.  Its name is a strong hash name followed by <code>.gwt.rpc</code>.  This file must be deployed to your web
-        server as a public resource, accessible from a 
-        <a href="doc/html/com.google.gwt.user.server.rpc.RemoteServiceServlet.html">RemoteServiceServlet</a>
-        via <code>ServletContext.getResource()</code>.  If
-        it is not deployed properly, RPC will run in 1.3.3 compatibility mode and refuse to serialize types implementing
-        <a href="doc/html/java.io.Serializable.html">Serializable</a>. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1297">#1297</a>)</li>
-        <li><a href="doc/html/com.google.gwt.user.client.ui.Panel.html#adopt(com.google.gwt.user.client.ui.Widget,%20com.google.gwt.user.client.Element)">Panel.adopt(Widget, Element)</a>
-        and
-        <a href="doc/html/com.google.gwt.user.client.ui.Panel.html#disown(com.google.gwt.user.client.ui.Widget)">Panel.disown(Widget)</a>
-        have been deprecated.  If you have subclassed Panel, please carefully review the new documentation for
-        <a href="doc/html/com.google.gwt.user.client.ui.Panel.html#add(com.google.gwt.user.client.ui.Widget)">Panel.add(Widget)</a>
-        and
-        <a href="doc/html/com.google.gwt.user.client.ui.Panel.html#remove(com.google.gwt.user.client.ui.Widget)">Panel.remove(Widget)</a>
-        for details on the correct way to add and remove Widgets from Panels.
-        (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1121">#1121</a>)</li>
-        <li>The benchmark viewer application is now faster, prettier, and a bit
-        more user friendly.</li>
-      </ul>
-
-      <h3>Retractions from 1.4.10</h3>
-      <ul>
-        <li>Breaking changes to the semantics of
-        <a href="doc/html/com.google.gwt.user.client.ui.UIObject.html#setStyleName(java.lang.String)">UIObject.setStyleName()</a>
-        have been backed out.  All changes relative to 1.3.3 should now be
-        backwards-compatible. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1079">#1079</a>)</li>
-        <li>The linux distribution of 1.4.10 bundled Mozilla 1.7.13 instead of version 1.7.12, which is bundled in previous
-        releases.  This change caused problems on some systems, so it's been
-        reverted back to Mozilla 1.7.12 again. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1105">#1105</a>)</li>
-        <li>Numerous RPC warnings were added in 1.4.10.  One of these warnings would be issued when a class containing
-        native methods was found to be serializable.  This warning now only applies to automatically serialized types;
-        types with custom serializers will no longer trigger this warning. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1161">#1161</a>)</li>
-        <li>A change to RPC in 1.4.10 would cause an error to be issued if a serializable type had any subtypes that were
-        not serializable.  This change caused code that worked in 1.3.3 to fail in 1.4.10.  In this release, the error has
-        been downgraded to a warning. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1163">#1163</a>)</li>
-        <li>A potentially breaking change to event bubbling in 1.4.10 has been
-        backed out in favor of the 1.3.3 behavior. (<a
-          href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1159">#1159</a>)</li>
-      </ul>
-
-      <h3>Fixed Issues</h3>
-      <p>
-      See the GWT issue tracker for
-      <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_4_RC2%20type%3Adefect&num=1000">the
-      complete list of bug fixes</a> in this release.</p>
-
-      <hr/>
-      <a name="Release_Notes_1_4_10"></a>
-      <h2>Release Notes for 1.4.10 (RC)</h2>
-      <p>
-      This is the Release Candidate for GWT 1.4, the first GWT release developed with major participation
-      from GWT open source contributors.  It's been a long time coming, but we hope it's been worth the wait.
-      In addition to tons of new features, optimizations, and performance enhancements, we've fixed more than
-      150 bugs.  There are some important behavioral and potentially breaking API changes; if you read nothing
-      else, please read these following sections!
-      </p>
-
-      <h3>Behavioral Changes</h3>
-      <p>Important changes in the behavior of existing GWT features.</p>
-      <h4>Critical Changes to RPC</h4>
-      In previous versions, the RPC subsystem was too lenient and failed to warn at compile time about potential (though unusual)
-      edge cases that could in theory cause problems at runtime.  Beginning with version 1.4, the RPC subsystem emits additional warnings and errors to help 
-      you identify error-prone constructs.  While this new behavior may seem annoying at first, rest assured that fixing your code to avoid RPC warnings will result in a smaller, faster, and more reliable app.
-      <ul>
-        <li><b>Bad code that happened to work before might not now</b><br/>
-        Previously, if you declared one particular component type via @gwt.typeArgs at compile time, you could
-        often get away with passing a different type at runtime.  For example, placing a Date in an
-        ArrayList of String might work.  This type of code is less likely to work now and will likely become more
-        strict in the future.  Bottom line: don't do this. Make sure collections only contain the declared item type (or subtypes thereof).
-        </li>
-        <li><b><a href="doc/html/java.io.Serializable.html">Serializable</a> equivalent to
-        <a href="doc/html/com.google.gwt.user.client.rpc.IsSerializable.html">IsSerializable</a></b><br/>
-        Although GWT's RPC mechanism doesn't purport to honor the semantics of Java serialization, by popular demand, Serializable and
-        IsSerializable are now equivalent for the purposes of RPC.  This should improve server-side
-        interoperability and remove much of the need for DTOs.
-        </li>
-        <li><b>Warn about missing gwt.typeArgs</b><br/>
-        Every Collection or Map type should have an associated
-        <a href="doc/html/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.SerializableTypes.html">gwt.typeArgs
-        javadoc annotation</a>.  In the past, a missing @gwt.typeArgs would generally have no noticeable effect,
-        because a bug in the RPC system would generate code for all available serializable types, even if they
-        weren't used in your service interface.  Now that this bug has been fixed, you can achieve <b>significant</b>
-        reduction in the size of your compiled output by fixing these warnings.
-        </li>
-        <li><b>Warn about serializable subclasses that violate the serialization restrictions</b><br/>
-        An RPC warning is emitted for classes that are assignable to IsSerializable or Serializable but that lack a default
-        constructor or contain fields which cannot be serialized. 
-        It is important to resolve these warnings to avoid rare but confusing situations in which exceptions would be thrown at runtime.
-        </li>
-        <li><b>Warn about non-transient, final instance fields</b><br/>
-        RPC has never actually serialized <code>final</code> instance fields, but now it explicitly warns about the existence of such fields unless they are also <code>transient</code>.  
-        Thus, the warning can be addressed by making <code>final</code> instance fields <code>transient</code> as well, or it can be suppressed via a module property.
-        </li>
-        <li><b>Warn about local and non-static nested types that implement IsSerializable or Serializable</b><br/>
-        RPC has never serialized these kinds of classes and will now generate a warning.
-        </li>
-        <li><b>Warn about native methods in serializable classes</b><br/>
-        Attempting to serialize classes that contain <code>native</code> methods will cause UnsatisfiedLinkErrors if such methods are called in server-side code.
-        </li>
-      </ul>
-      <h4>Module Script Tags</h4>
-      <ul>
-        <li>In previous versions of GWT, including external JavaScript files via a module &lt;script&gt; tag required a nested JavaScript expression &mdash; called a <i>script-ready function</i> &mdash; that would
-        determine when the script had been successfully loaded.  Script load order is now handled automatically and
-        these expressions are ignored.  A warning will be issued in hosted mode.  For reference, see
-        <a href="doc/html/com.google.gwt.doc.DeveloperGuide.Fundamentals.Modules.AutomaticResourceInjection.html">here</a>.
-        </li>
-      </ul>
-      <h4>Additional Hosted Mode Checks Related to JSNI</h4>
-      <ul>
-        <li>Previously, when passing values from JavaScript into Java, hosted mode would silently coerce
-        a JavaScript value of an incorrect type into the declared Java type.  Unfortunately, this would
-        allow code to work in hosted mode that could fail in unexpected ways in web mode.  Hosted mode
-        will now throw a HostedModeException if you try to pass an incompatible type.  See
-        <a href="doc/html/com.google.gwt.doc.DeveloperGuide.JavaScriptNativeInterface.Marshaling.html">here</a>
-        for more details.
-        </li>
-      </ul>
-
-      <h3>Breaking API Changes</h3>
-      This release also includes API changes that may require minor tweaks to existing code.  Any such changes
-      that affect you should only take a few minutes to rectify.
-
-      <h4><a href="doc/html/com.google.gwt.core.client.JavaScriptObject.html">JavaScriptObject</a></h4>
-      <ul>
-        <li>Although subclassing JavaScriptObject is not supported, some people do so anyway at their own risk :) 
-        Please note that the existing (int) constructor has been removed in favor of a protected no-arg constructor.  Read the source code for
-        <a href="doc/html/com.google.gwt.user.client.Element.html">Element</a> for an example of how JavaScriptObject must
-        be subclassed now (that is, if subclassing were supported...which, of course, it isn't).
-        </li>
-      </ul>
-      <h4><a href="doc/html/com.google.gwt.user.client.DeferredCommand.html">DeferredCommand</a></h4>
-      <ul>
-        <li>The add() method is deprecated in favor of addCommand() in order to support the new
-        <a href="doc/html/com.google.gwt.user.client.IncrementalCommand.html">IncrementalCommand</a> interface.  Had we
-        simply added a new method overload, existing code that passed in a null literal would have failed to compile.</li>
-        <li>The new addPause() method should be used instead of add(null).</li>
-      </ul>
-      <h4><a href="doc/html/com.google.gwt.user.client.ui.UIObject.html">UIObject</a></h4>
-      <ul>
-        <li>The intended use and behavior of style names has been formalized in UIObject (and therefore in all widgets). All style
-        names are now classified as "primary", "secondary", and "dependent" styles, the meanings of which are detailed in the UIObject
-        documentation. The relevant method signatures remain unchanged (get/setStyleName(), add/removeStyleName()), and most
-        widgets should be unaffected. One potentially breaking change, however, is that an exception is thrown if an attempt is made to remove the primary style name of a widget using removeStyleName().
-        See the UIObject documentation for a full explanation.</li>
-      </ul>
-
-      <h3>New Features</h3>
-      Here are a few of the coolest new features and enhancements in GWT 1.4.
-      <ul>
-        <li><b>Size and Speed Optimizations</b><ul>
-           <li>New <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=610">size</a>
-           <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=599">improvements</a> in the GWT compiler
-           produce JavaScript that is 10-20% smaller; just recompile your app with 1.4.</li>
-           <li>An enhanced startup sequence reduces the size of your module's startup script by 80%. More importantly, the
-           new startup sequence removes an HTTP round-trip, making startup latency about 33% faster.</li>
-           <li>The above optimizations combined with <a href="#ImageBundle">ImageBundle</a>, make it possible for GWT-based applications
-           to load surprisingly quickly. To see for yourself, check out startup time of the
-           <a href="samples/Mail/www/com.google.gwt.sample.mail.Mail/Mail.html">Mail</a> sample.</li>
-        </ul></li>
-        <li><b>Deployment Enhancements</b><ul>
-           <li>GWT RPC is no longer tied to exclusively to servlets. New
-           <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=389">modularized RPC</a> server code makes
-           it easy to connect GWT RPC to your choice of Java back-ends.</li>
-           <li>Adding GWT modules to an HTML page has been simplified. Instead of adding a &lt;meta name='gwt:module'&gt; and
-           &lt;script src='gwt.js'&gt;, you just add a single script element for your module.</li>
-           <li>Cross-site script inclusion is now supported. The compiler produces a "-xs" (meaning "cross-site") version of
-           your module's startup script that can be included without being restricted by the same-origin policy. WARNING:
-           including scripts from other sites that you don't fully trust is a
-           <a href="http://groups.google.com/group/Google-Web-Toolkit/web/security-for-gwt-applications">big security risk</a>.</li>
-        </ul></li>
-        <li><b>Widget and Library Enhancements</b><ul>
-           <li><a href="doc/html/com.google.gwt.user.client.ui.RichTextArea.html">RichTextArea</a> allows "drop in"
-           functionality for rich text editing.</li>
-           <li><a href="doc/html/com.google.gwt.user.client.ui.SuggestBox.html">SuggestBox</a> makes it easy to add
-           auto-complete functionality.</li>
-           <li>Splitters! <a href="doc/html/com.google.gwt.user.client.ui.HorizontalSplitPanel.html">HorizontalSplitPanel</a>
-           and <a href="doc/html/com.google.gwt.user.client.ui.VerticalSplitPanel.html">VerticalSplitPanel</a> enable you to
-           resize portions of the user interface.</li>
-           <li><a href="doc/html/com.google.gwt.user.client.ui.PushButton.html">PushButton</a> and
-           <a href="doc/html/com.google.gwt.user.client.ui.ToggleButton.html">ToggleButton</a> are easy-to-customize button
-           widgets that can enhance the look-and-feel of your UI.</li>
-           <li><a href="doc/html/com.google.gwt.user.client.ui.DisclosurePanel.html">DisclosurePanel</a> is a simple,
-           nice-looking panel that lets users easily hide and show portions of your application UI.</li>
-           <li><a href="doc/html/com.google.gwt.i18n.client.DateTimeFormat.html">DateTimeFormat</a> and
-           <a href="doc/html/com.google.gwt.i18n.client.NumberFormat.html">NumberFormat</a> make it easy to format and parse
-           dates, times, and numbers for users all over the world.</li>
-           <li><a href="doc/html/com.google.gwt.user.client.IncrementalCommand.html">IncrementalCommand</a> helps you
-           implement long-running tasks in your client code without triggering "slow script" warnings.</li>
-           <li>A new <a href="http://docs.google.com/View?docid=d9s6nb7_1d723ft">benchmarking subsystem</a> integrates with
-           JUnit to let you record and compare the speed of code snippets across multiple browsers and multiple parameter
-           ranges. Benchmarking is a powerful way to identify bottlenecks and compare performance of alternative implementations.</li>
-           <li>The oft-requested <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=21">java.io.Serializable</a> is
-           now included in the JRE emulation library and is synonymous with IsSerializable for the purpose of GWT RPC.</li>
-           <li><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=844">Mouse wheel events</a> are now available
-           on a variety of widgets.</li>
-        </ul></li>
-        <a name="ImageBundle"></a>
-        <li><b><a href="doc/html/com.google.gwt.user.client.ui.ImageBundle.html">ImageBundle</a></b><ul>
-           <li>ImageBundle is the single biggest have-to-see-it-to-believe-it feature in this release. Image bundles make it trivially
-           easy to combine dozens of images into a single "image strip", collapsing what would have been dozens of HTTP requests into
-           one: a single, permanently-cacheable image file.</li>
-           <li>Image bundles manage everything for you automatically, from computing clipping rectangles to making transparent PNGs
-           work in IE6. You can even choose to get the clipped image as an Image widget or as pure HTML for inclusion in a larger HTML
-           template.</li>
-           <li>In addition to enabling a blazing-fast startup, image bundles help make the UI look better during startup, too. Typical
-           AJAX apps exhibit "bouncy relayout" as individual images are loaded one-at-a-time. Fixing this problem has historically
-           required laboriously pre-initializing the width and height of each individual image ahead of time. Image bundles do the
-           same thing automatically. The dimensions of each clipped image are computed at compile time while the bundled
-           image file is being created. Voila! The result is a fast, non-ugly user startup experience that requires no extra work on
-           the part of the GWT developer to keep up-to-date.</li>
-           <li>See the <a href="doc/html/com.google.gwt.doc.DeveloperGuide.UserInterface.ImageBundles.html">doc section</a> for more
-           details.</li>
-        </ul></li>
-      </ul>
-      
-      <p>
-      See the GWT issue tracker for
-      <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_4_RC%20type%3Aenhancement&num=1000">the
-      complete list of enhancements</a> in this release.</p>
- 
-      <h3>Fixed Issues</h3>
-      <p>
-      See the GWT issue tracker for
-      <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_4_RC%20type%3Adefect&num=1000">the
-      complete list of bug fixes</a> in this release.</p>
-
-      <hr/>
-      <a name="Release_Notes_1_3_3"></a>
-      <h2>Release Notes for 1.3.3</h2>
-      <p>
-      This version has only minor functional changes from 1.3.1, listed below.
-      </p>
-
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=319">Issue #319 - Calling native super method in implementation class results in infinite loop in web mode</a></li>
-        <li><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=496">Issue #496 - gwt.js in gwt-user.jar lacks Apache 2.0 license header</a></li>
-        <li><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=497">Issue #497 - Unexpected internal compiler error - Analyzing permutation #1</a></li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_3_1"></a>
-      <h2>Release Notes for 1.3.1 (RC)</h2>
-      <p>
-      This is the Release Candidate for GWT 1.3, the first completely open source version of GWT. 
-      This version has no new functionality, but we did make a lot of changes to get the source code and build scripts into presentable shape to prepare for ongoing open source development.
-      Although the changes were relatively harmless -- formatting, sorting, more documentation, and a new build system -- there's always a small chance of problems, so we plan to call this a Release Candidate until we've convinced ourselves it's reliable.
-      </p>
-
-      <h3>Useful Links</h3>
-      <ul>
-        <li><b><a href="http://code.google.com/webtoolkit/makinggwtbetter.html">Making GWT Better</a></b>
-        <br>This is our new GWT open source charter that describes how we plan to operate the project and how you can access the GWT source, compile it yourself, and contribute.</li>
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/list">The GWT Issue Tracker</a></b>
-        <br>Please report any bugs in 1.3 RC that weren't in 1.2.22 in the GWT issue tracker. These would be likely related to the new build, and we want to know ASAP so we can fix them.</li>
-        <li><b><a href="http://google-web-toolkit.googlecode.com/svn/">The GWT Subversion Repository</a></b>
-        <br>Visit the online repository to browse the GWT source without a Subversion client.</li>
-      </ul>
-      
-      <hr/>
-      <a name="Release_Notes_1_2_22"></a>
-      <h2>Release Notes for 1.2.22</h2>
-      <p>
-      This is the official GWT 1.2 release, the follow up to the <a href="#Release_Notes_1_2_11">GWT 1.2 Release Candidate</a>.
-      It includes all of the enhancements and bug fixes from GWT 1.2 RC as well as a few additional bug fixes that were reported against GWT 1.2 RC.</p>
-      
-      <h3>About OS X Hosted Mode Support</h3>
-      GWT's hosted mode support is available only on OS X 1.4 (Tiger) or later.
-
-      <h3>Useful Links</h3>
-      <ul>
-        
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_2_Final">Changes included in GWT 1.2 since the RC</a></b>
-        <br>Also see the GWT Blog for a discussion of the <a href="http://googlewebtoolkit.blogspot.com/2006/11/wrapping-up-gwt-12-soon.html">noteworthy issues related to 1.2 RC</a></li>
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_2_RC">New features and bug fixes in GWT 1.2 RC</a></b></li>
-      </ul>
-      
-      <h3>Breaking API Changes</h3>
-      There are no breaking changes to pre-1.2 APIs, but one method has been renamed in a class that was new in 1.2 RC.
-      
-      <h4>com.google.gwt.http.client.RequestBuilder</h4>
-      The method <code>addHeader()</code> was renamed to <code>setHeader()</code> to more clearly reflect its intent. 
-      You will only be affected by this change if you are using the new HTTP functionality available as of build 1.2.11.
-
-      <hr/>
-      <a name="Release_Notes_1_2_11"></a>
-      <h2>Release Notes for 1.2.11 (RC)</h2>
-      <p>
-      This is the Release Candidate for GWT 1.2. 
-      Between this build and the subsequent GWT 1.2 official release, changes are limited to issues unique to GWT 1.2 RC.
-      
-      <p>
-      See the GWT issue tracker for <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q=status%3AFixed%20milestone%3A1_2_RC">the complete list of enhancements and bug fixes</a> in this release.</p>
-      
-      <h3>New Features</h3>
-      <ul>
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=91">Full support for OS X development</a></b>
-        <br>Develop with GWT on OS X as easily as on Linux and Windows</li>
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=93">Much faster hosted mode</a></b>
-        <br>Hosted mode startup time has improved significantly, but, even better, refreshes are now lightning fast &mdash; even when your source changes</li>
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=52">New HTTP request module</a></b>
-        <br>The HTTP functionality that GWT users have been asking for (custom headers, status code, timeouts, and more), all wrapped up in an API that's easier to use than the JavaScript XMLHttpRequest object</li>
-        <li><b><a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=10">Widgets in TreeItems</a></b>
-        <br>Tree items can now contain arbitrary widgets...finally, you can easily create trees with checkboxes :-)</li>
-      </ul>
-      </p>
-      
-      <hr/>
-      <a name="Release_Notes_1_1_10"></a>
-      <h2>Release Notes for 1.1.10</h2>
-      <p/>
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li>Normalized behavior of GWT.getModuleBaseURL() with respect to hosted mode, web mode, RPC, and automatic resource injection
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/6c2b23e90008b6b9">post #1</a>,
-         <a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/1bb47f2cff671ef0">post #2</a>,
-         <a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/3408c38464c57d4a">post #3</a>]
-        </li>
-        <li>Clarified message in Grid class related to row/column out of bounds error
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/e5e130cba766d126">post</a>]
-        </li>
-        <li>i18nCreator fixed to work with Java 5.0
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/3b6452a068ebec63">post</a>]
-        </li>
-        <li>I18NSync (and therefore -i18n scripts) changed to replace dots with underscores when generating method names
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/6a4e05beb094a5a2">post</a>]
-        </li>
-        <li>Additional character escaping in JSON strings
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/5f437d12ba83fff0">post</a>]
-        </li>
-        <li>Fixed bug calling toString() on nested JSON objects
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/ee81aa5411dece71">post</a>]
-        </li>
-        <li>Fixed bug that caused the default font size of text in a FocusPanel to be zero
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/2f5abf147c5550c4">post</a>]
-        </li>
-        <li>Fixed TabPanel.insert() with asHTML argument
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/8f427dbe76ce2c49/">post</a>]
-        </li>
-        <li>Popups and DialogBoxes no longer underlap lists and combos in IE6
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/6815ec29d2c404e2">post</a>]
-        </li>
-        <li>DialogBoxes can no longer be dragged beoynd the upper left corner of the browser window
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/28390f32c42f7940">post</a>]
-        </li>
-        <li>Buttons inside of FormPanels no longer automatically submit on Firefox; this is still a problem some versions of Safari and Opera
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/72bea3a6d4feeaeb">post</a>]
-        </li>
-        <li>TabPanel now sets the height of the internal DeckPanel to 100% to ensure all available space is used
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/4cd09f04bc515696">post</a>]
-        </li>
-        <li>Fixed bug in Mozilla that was causing DialogBox.onKeyPressPreview() to see key as 0
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/8147b4b219a8fbc7">post</a>]
-        </li>
-        <li>DockPanel no longer lays out with a DeferredCommand; this makes it possible to correctly measure the size of PopupPanel
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/7bbb89e4c97ae1e6">post</a>]
-        </li>
-        <li>SimplePanel is no longer abstract
-        </li>
-        <li>Double click now fires correctly on IE6
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/2d16242dc7fb830f">post</a>]
-        </li>
-        <li>Fixed RPC bug that caused deserialization errors or infinite loops with self-referential object graphs
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/2a8658e93e2a8de3">post</a>]
-        </li>
-        <li>Fixed RPC bug that caused deserialization to fail on character arrays containing null characters
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/f60f5d5552a3d26b">post</a>]
-        </li>
-        <li>Serializable classes whose superclass is serialized by a custom field serializer are now correctly deserialized on the server
-        </li>
-        <li>Fixed bug related to FocusPanel that sometimes manifested during RPC async responses
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/edd16ede4f891db8">post</a>]
-        </li>
-        <li>Fixed bug in JUnit assertEquals() for floating point values (delta was not honored correctly)
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/b0e06cc253915b86">post</a>]
-        </li>
-        <li>Fixed internal compiler errors related to nested local subclasses, empty for loop expressions, and no-op unary plus operator.
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/d8ecf70acc4e5b0e">post #1</a>,
-         <a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/4da8dcbab9479a80">post #2</a>,
-         <a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/a9f17bf30d0116b">post #3</a>]
-        </li>
-        <li>Fixed infinite loop in Integer.toHexString()
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/3f9c3f4df08fb523">post</a>]
-        </li>
-        <li>Compiler now handling filesystem symbolic links in project structure
-        [<a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/1597c73888d1acd9">post</a>]
-        </li>
-        <li>Fixed rare JVM crash in Windows hosted mode related to JSNI function pointers
-        </li>
-      </ul>
-      
-      <hr/>
-      <a name="Release_Notes_1_1_0"></a>
-      <h2>Release Notes for 1.1.0 (RC)</h2>
-      <p/>
-      <h3>New Features</h3>
-      <ul>
-        <li><b><a href="doc/html/com.google.gwt.user.client.ui.FileUpload.html">FileUpload widget</a></b><br>The much-requested file upload widget
-        </li><li><b><a href="doc/html/com.google.gwt.user.client.ui.FormPanel.html">FormPanel widget</a></b><br>Easily submit traditional HTML forms from GWT apps
-        </li><li><b><a href="doc/html/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html">RPC optimizations</a></b><br>Client and server performance improvements and a more compact wire format
-        </li><li><b><a href="doc/html/com.google.gwt.doc.DeveloperGuide.Fundamentals.Modules.AutomaticResourceInjection.html">Automatic Resource Injection</a></b><br>Modules can contain references to external JavaScript and CSS files, causing them to be automatically loaded when the module itself is loaded
-        </li><li><b><a href="doc/html/com.google.gwt.doc.DeveloperGuide.Internationalization.html">Internationalization</a></b><br>Easily localize strings and formatted messages
-        </li><li><b><a href="doc/html/com.google.gwt.xml.client.html">XML classes</a></b><br>An XML library based on the W3C DOM
-        </li><li><b><a href="doc/html/com.google.gwt.json.client.html">JSON classes</a></b><br>JSON has moved into <code>gwt-user.jar</code>, and it's much faster than the sample that shipped with 1.0.21
-        </li><li><b><a href="doc/html/com.google.gwt.doc.DeveloperGuide.JUnitIntegration.html">JUnit enhancements</a></b><br>Unit tests are much, much faster than in 1.0.21, easier to configure, and you can now test asynchronous things like RPCs and timers
-        </li><li><b><a href="doc/javadoc/index.html">Javadoc</a></b><br>Now included for your convenience, with sample code fragments
-        </li><li><b><code>gwt-servlet.jar</code></b><br>Although you should continue to build against <code>gwt-user.jar</code> as always, 
-        you only need to deploy <code>gwt-servlet.jar</code> with your webapps; it contains the subset of <code>gwt-user.jar</code> you'll need to support RPC
-      </li></ul>
-         There are also a significant number of bug fixes from all the great feedback we've gotten from the developer forum. 
-         Please see the <a href="#Release_Notes">additional release notes</a> for detailed information about other important changes in
-         Google Web Toolkit since the previous release, including a few breaking API changes that we don't want to catch you off guard.
-      </p>
-      
-      <h3>Fixed Issues</h3>
-      <ul>
-        <li><a href="http://code.google.com/webtoolkit/issues/4794724.html">Issue #4794724 - Servlet container problems due to gwt-user.jar including javax.servlet classes</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/1676686.html">Issue #1676686 - Hosted mode problems in Windows 2000</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/6606675.html">Issue #6606675 - ListBox and Image widgets are missing CSS style names</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/5922226.html">Issue #5922226 - Casts from interface types to concrete class types can fail</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/4137736.html">Issue #4137736 - Referencing an outer local from a field initializer causes NullPointerException</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/2518888.html">Issue #2518888 - Problem with "return" statements in constructors</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/9984353.html">Issue #9984353 - Hosted Mode server throws IllegalArgumentException when system is set to non-english locale</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/3733199.html">Issue #3733199 - Shrinking Grid via resizeRows() leads to inconsistent state</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/7659250.html">Issue #7659250 - Hosted mode on default Fedora Core 5 complains of missing libstdc++.so.5</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/6531240.html">Issue #6531240 - Empty if, while, do, and for statements cause Compiler Error</a></li>
-        <li><a href="http://code.google.com/webtoolkit/issues/4927592.html">Issue #4927592 - Multiple initializations in for loop initializer causes internal compiler error.</a></li>
-      </ul>
-
-      <p>See the <a href="#Appendix">appendix of fixed issues</a> for the nitty-gritty list of things that we have fixed in this release, including smaller issues.</p>
-
-      <h3>Behavioral Changes</h3>
-      <p>Important changes in the behavior of existing GWT features.</p>
-      <h4>Module Source and Public Paths</h4>
-      <ul>
-        <li>In previous versions of GWT, source and public path inclusions were based on physical
-        directory structure; only files physically located with the module would be included. Going
-        forward, source and public path inclusions are based on logical package structure. Once a package
-        has been included, any files in that package become visible no matter where they are physically
-        located.
-        </li>
-      </ul>
-      <h4>JUnit Modules</h4>
-      <ul>
-        <li>GWT test modules (that is, modules intended to run GWTTestCase-derived JUnit test cases) no longer
-        need to inherit the <code>com.google.gwt.junit.JUnit</code> module. Additionally, it is no longer an
-        error to declare entry points within a test module (they will be ignored when running under JUnit).
-        Most test cases can now simply use the existing application module, which should simplify test case
-        configuration.
-        </li>
-      </ul>
-
-      <h3>Breaking API Changes</h3>
-      Based on user feedback, we've made a few API changes in this release that may require minor tweaks to your existing code when you upgrade.
-      Any such changes that affect you should only take a few minutes to rectify.
-
-      <h4>com.google.gwt.user.client.ui.HasWidgets</h4>
-      <ul>
-        <li>We've moved add(), remove(), and clear() into this interface, so that any widget that can contain other widgets will be bound to this contract.</li>
-        <li>The add() method no longer returns a boolean.  If a panel either cannot add a child widget without extra arguments, or cannot accept further widgets, it will throw an exception.  This is in keeping with the fact that this is usually the result of an error in the code.</li>
-        <li>Its iterator is now required to support the remove() method.</li>
-      </ul>
-      <h4>com.google.gwt.user.client.ui.Composite</h4>
-      <ul>
-        <li>Composites must now call initWidget() in their constructors, rather than setWidget().  This is more indicative of its actual purpose, and also serves to clear up any confusion with SimplePanel's setWidget() method.  Composite.setWidget() is now deprecated.</li>
-      </ul>
-      <h4>com.google.gwt.user.client.ui.SimplePanel and subclasses</h4>
-      <ul>
-        <li>
-        We have added setWidget() to SimplePanel, which has more appropriate semantics for a panel that can contain only one child.  
-        The add() method is still present through the HasWidgets interface, but will fail if a widget is already present.  
-        This change is most likely to affect you if you use DialogBox or PopupPanel. To fix it, simply change your call to add() to setWidget() instead. 
-        </li>
-      </ul>
-      <h4>com.google.gwt.user.client.Cookies</h4>
-      <ul>
-        <li>Cookies.getCookie() is now static, as it should have been from the beginning.  There is no need to instantiate this class now.</li>
-        <li>You can now set cookies as well!</li>
-      </ul>
-
-      <a name="Appendix"></a>
-      <h3>Appendix: Complete List of Fixed Issues</h3>
-
-      <p>
-        The list of issues below is a short synopsis of all of the major and minor issues fixed in this release.  
-        See the <a href="http://code.google.com/webtoolkit/issues/">online GWT issues database</a> for the important common issues.</p>
-      <ul>
-        <li>String.matches(regex) should exist and doesn't</li>
-        <li>Need a way to set individual List items selected/unselected (applies to multi-select listboxes)</li>
-        <li>DOM needs setBooleanAttribute, getBooleanAttribute.</li>
-        <li>HTMLTable.CellFormatter needs getStyleName() to match setStyleName().</li>
-        <li>FlexTable's internal widget map does not correctly adjust for the user inserting rows and cells.<br></li>
-        <li>Window.getTitle/setTitle should be static</li>
-        <li># characters in filenames cause compilation to fail.</li>
-        <li>DynaTable has incorrect HTML</li>
-        <li>Change Timer API to use int not long</li>
-        <li>In hosted mode JSNI, marshall Java longs as VT_R8 </li>
-        <li>Popups are not always positioned properly on Safari.</li>
-        <li>SWT source inclusion is wrong.</li>
-        <li>Safari crashes on exit under some circumstances.</li>
-        <li>TreeLogger throws away exception info in console mode.</li>
-        <li>Window needs a private ctor</li>
-        <li>Phone home version checking should actually compare ordering of version number</li>
-        <li>Hosted Mode server throws IllegalArgumentException when system is set to non-english locale</li>
-        <li>Trees have an unsightly 16-pixel left margin.</li>
-        <li>SimplePanel.remove() broken.</li>
-        <li>ScrollPanel doesn't implement SourcesScrollEvents.</li>
-        <li>Make junit-web output to www dir</li>
-        <li>Add "hidden" feature to ArgHandler system.</li>
-        <li>JUnitShell could hang forever.</li>
-        <li>1.5 VM fails to run junit because StackTraceElement 0-arg constructor disappeared.</li>
-        <li>Panel and ComplexPanel still have methods from old version of HasWidgets.</li>
-        <li>Nested tables can fire events from the wrong one.</li>
-        <li>Make sure JSNI refs to functions can be passed around and used as real function pointers.</li>
-        <li>AbsolutePanel doesn't position its children consistently.</li>
-        <li>JSONParser does not handle generic JSONValues in the encoded json string correctly; always assumes its a JSONObject</li>
-        <li>Remove -notHeadless from GWTShell (only applies to GWTUnitTestShell)</li>
-        <li>Number of results returned from split() differs in Java/JavaScript (see description)</li>
-        <li>Helper scripts don't work for base package.</li>
-        <li>Grid fails to update row count when removing.</li>
-        <li>JSONString, toString does not enclose its characters in double quotes</li>
-        <li>Selection issue when removing widgets from TabPanel.</li>
-        <li>JSONParser always assumes root type is JSONObject</li>
-        <li>ClassSourceFileComposer should not handle Class objects.</li>
-        <li>Modules cannot supercede files from inherited modules</li>
-        <li>Simple &amp; ComplexPanel shouldn't implement getChildCount(), getChild(), etc.</li>
-        <li>Negative byte values passed into JavaScript become positive</li>
-        <li>The rpc servlet needs a thread-local HttpServletResponse to match the thread-local request.</li>
-        <li>Appending char to a String behaves incorrectly.</li>
-        <li>Remove STL dependency from gwt-ll</li>
-        <li>Using xhtml doctype causes popups to be misplaced on Mozilla browsers.</li>
-        <li>JsniInjector fails to match lines when there are Javadoc comments.</li>
-        <li>Add whitelist bypass for hosted browser</li>
-        <li>PopupPanel example is wrong.</li>
-        <li>UIObject needs a title property.</li>
-        <li>JSNI methods in local classes don't work in hosted mode.</li>
-        <li>HashMap throws a JavaScript error under some circumstances.</li>
-        <li>Source and Public module tags should be logical instead of physical.</li>
-        <li>Document that module source and public tags are now logical rather than physical.<br></li>
-        <li>Default .launch file fails to use project's full classpath.</li>
-        <li>RemoteServiceServlet sends back HTTP 200 OK but no content under WebSphere.</li>
-        <li>Widget.onLoad() is called too early sometimes.</li>
-        <li>Is it really a good idea to have add(Widget) on Panel?</li>
-        <li>Web-mode JUnit that reports via RPC</li>
-        <li>Tree fires onTreeItemStateChanged twice.</li>
-        <li>Make JSON APIs part of gwt-user.jar</li>
-        <li>Async JUnit</li>
-        <li>String.equalsIgnoreCase(null) throws exception in web mode</li>
-        <li>Using a class literal for a pruned typed causes ICE</li>
-        <li>Make all built-in implementations of HasWidgets.iterator() support remove().</li>
-        <li>JSON is slow in Web mode</li>
-        <li>StringBuffer uses string concatenation, and is n-squared as a result</li>
-        <li>Identical Strings can compare false in web mode.</li>
-        <li>Tweaks to the property provider environment to support locale and improve code uniformity b/w hosted and web mode<br></li>
-        <li>Server-side serialization is unusably slow for large data sets</li>
-        <li>Client side serialization is unusably slow for large datasets</li>
-        <li>Format source for JUnitTestCaseStubGeneratorm, ServerSerializationStream</li>
-        <li>MethodDispatch not working correctly on IE.</li>
-        <li>JavaScriptObject rescuing is incomplete.</li>
-        <li>Reduce RPC wire size by not quoting non-strings.</li>
-        <li>Cyclic object graphs can be corrupted during deserialization on the server</li>
-        <li>Test methods that throw checked exceptions cause the generated code to fail to compile</li>
-        <li>Allow RemoteServiceResponse compression to be controlled by subclasses</li>
-        <li>Startup timing bug makes RootPanel.get(id) throw an NPE</li>
-        <li>Change whitelist/blacklist settings to be command-line switches rather than system properties</li>
-        <li>KeyCode is always 0 for keypress events on Mozilla.</li>
-        <li>Add Panel.remove(int) convenience method.</li>
-        <li>File Upload Widget</li>
-        <li>PopupPanel needs to deal better with being empty.</li>
-        <li>CheckBox.setEnabled() has reversed sense.</li>
-        <li>History tokens have problems with URL encoding.</li>
-        <li>Loosen restriction on when DockPanel.CENTER child may be added.</li>
-        <li>AbsolutePanel needs getWidgetLeft() and getWidgetTop().</li>
-        <li>Decision: how should FlowPanel behave?</li>
-        <li>Samples with composites need to call initWidget() instead of the deprecated setWidget().</li>
-        <li>RootPanel.get(String) should not be clearing the div's contents.</li>
-        <li>ListBox, Image, and Hyperlink are missing style names, despite doc</li>
-        <li>Hyperlink.removeClickListener is broken.</li>
-        <li>Don't allow tabs to word-wrap internally on TabPanel</li>
-        <li>Turkish locale problem with the RPC generated code - probably affects others too</li>
-        <li>StackPanel.add() totally screwy.</li>
-        <li>Referencing a field that could cause static initialization fails to cause a side effect.</li>
-      </ul>
-
-      <hr/>
-      <a name="Release_Notes_1_0_21"></a>
-      <h2>Release Notes for 1.0.21</h2>
-      <p/>
-      <h3>Fixed Issues</h3>
-      <ul>
-         <li><a href='http://code.google.com/webtoolkit/issues/5823700.html'>Issue #5823700 - GWT hosted mode does not work when IE 7 is installed</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/8840603.html'>Issue #8840603 - GWT applications do not run in IE 7</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/3844117.html'>Issue #3844117 - Cannot reference a final local variable from a deep inner class</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/9157420.html'>Issue #9157420 - Compiler reports errors for non-ASCII characters (UTF-8 not supported)</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/1524429.html'>Issue #1524429 - RPC exception due to empty strings</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/6000056.html'>Issue #6000056 - ArrayStoreException initializing multi-dimensional arrays</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/3490506.html'>Issue #3490506 - Tree widget remove() bug</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/8201889.html'>Issue #8201889 - Generated RPC proxy code fails to pull in String intrinsically</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/1600857.html'>Issue #1600857 - TabPanel getWidgetIndex() recursion</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/2705290.html'>Issue #2705290 - TabPanel widget does not remove tabs properly</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/9377889.html'>Issue #9377889 - TabBar method insertTab() not honoring 'asHTML' parameter</a>
-         <li><a href='http://code.google.com/webtoolkit/issues/4387606.html'>Issue #4387606 - FlexTable and Grid issues</a>
-      </ul>
-   </body></html>
+   </body>
+</html>
diff --git a/samples/expenses/README-MAVEN.txt b/samples/expenses/README-MAVEN.txt
index 909516b..40e8546 100644
--- a/samples/expenses/README-MAVEN.txt
+++ b/samples/expenses/README-MAVEN.txt
@@ -1,22 +1,15 @@
---- Generated by GWT WebAppCreator ---
-
-Congratulations, you've successfully generated a starter project!  What next?
-
 -- Option A: Import your project into Eclipse (recommended) --
 
-If you use Eclipse, you can simply import the generated project into Eclipse.
-We've tested against Eclipse 3.4 and 3.5.  Later versions will likely also
-work, earlier versions may not.
+If you use Eclipse, you can simply import the generated project into
+Eclipse. We've tested against Eclipse 3.5. Later versions will likely
+also work, earlier versions may not.
 
-If the directory containing this file does not have a .classpath or .project
-file, generate them by running 'ant eclipse.generate'
+Eclipse users will need to have the m2eclipse, or equivalent, pluigin
+installed. Instructions for how to install the m2eclipse plugin can
+be found here: http://m2eclipse.sonatype.org/installing-m2eclipse.html
 
-Eclipse users will need to have the m2eclipse, or equivalent, pluigin installed.
-Instructions for how to install the m2eclipse plugin can be found here:
-http://m2eclipse.sonatype.org/installing-m2eclipse.html
-
-Eclipse users will also want to run "mvn package" before importing into Eclipse.
-This will unpack the App Engine SDK to the local repository.
+Ensure Eclipse is configured to use Java 1.6 as this sample uses
+AppEngine.
 
 In Eclipse, go to the File menu and choose:
 
@@ -24,46 +17,41 @@
 
   Browse to the directory containing this file,
   select "Expenses".
-  
+
   Click Finish.
-  
+
 You can now browse the project in Eclipse.
 
-To launch your web app in GWT development mode, go to the Project -> Properties
-and expand the Google menu item. From there:
+To launch your web app in GWT development mode
 
-  Navigate to App Engine item, select  "Use App Engine", and specify which App Engine
-  SDK to use.
- 
-  Navigate to the Web Appliation item, select "This project has a WAR directory",
-  speicigy src/main/webapp, and uncheck "Launch and deploy...".
+  Go to the Run menu item and select Run -> Run as -> Web Application.
 
-  Navigate to Web Toolkit, select "use Google Web Toolkit", and specify which
-  GWT SDK you want to use.
+  - To load a set of initial data choose: LoadExpensesDB.html
 
-  Go to the Run menu item and select Run -> Debug as -> Web Application.
-  
+  - To run the Expenses Application choose: Expenses.html
+
+  - To run the Mobile version of the Expenses Application choose:
+    ExpensesMobile.html
+
   When prompted for which directory to run from, simply select the directory
   that Eclipse defaults to.
 
   You can now use the built-in debugger to debug your web app in development mode.
 
-If you supplied the junit path when invoking webAppCreator, you should see
-launch configurations for running your tests in development and production
-mode.
-
 -- Option B: Build from the command line with Maven --
 
-If you prefer to work from the command line, you can use Maven to build your
-project. (http://maven.apache.org/)  Maven uses the supplied 'pom.xml' file
-which describes exactly how to build your project.  This file has been tested
-to work against Maven 2.2.1  The following assumes 'mvn' is on your command
+If you prefer to work from the command line, you can use Maven to
+build your project (http://maven.apache.org/). You will also need Java
+1.6 JDK. Maven uses the supplied 'pom.xml' file which describes
+exactly how to build your project. This file has been tested to work
+against Maven 2.2.1. The following assumes 'mvn' is on your command
 line path.
 
-To run development mode, just type 'mvn gae:run'.
+To run development mode use the Maven GWT Plugin.
+
+  cd src/main/webapp; mvn -f ../../../pom.xml gwt:run
 
 To compile your project for deployment, just type 'mvn package'.
 
 For a full listing of other goals, visit:
 http://mojo.codehaus.org/gwt-maven-plugin/plugin-info.html
-
diff --git a/samples/expenses/pom.xml b/samples/expenses/pom.xml
index b45c4d4..5b1b174 100644
--- a/samples/expenses/pom.xml
+++ b/samples/expenses/pom.xml
@@ -7,6 +7,7 @@
 	<version>0.1.0.BUILD-SNAPSHOT</version>
 	<name>expenses</name>
 	<properties>
+                <gwt.version>2.1.0</gwt.version>
 		<roo.version>1.1.0.M2</roo.version>
 		<spring.version>3.0.3.RELEASE</spring.version>
 		<slf4j.version>1.6.1</slf4j.version>
@@ -54,13 +55,6 @@
             <url>https://repository.jboss.org/nexus/content/repositories/releases</url>
             <name>JBoss Repo</name>
         </repository>
-<!--
-    <repository>
-            <id>gwt-repo</id>
-            <url>http://google-web-toolkit.googlecode.com/svn/2.1.0.M3/gwt/maven</url>
-            <name>Google Web Toolkit Repository</name>
-        </repository>
--->
     </repositories>
     <pluginRepositories>
     <pluginRepository>
@@ -408,12 +402,13 @@
     <dependency>
             <groupId>com.google.gwt</groupId>
             <artifactId>gwt-servlet</artifactId>
-            <version>2.1-SNAPSHOT</version>
+            <version>${gwt.version}</version>
+            <scope>runtime</scope>
         </dependency>
     <dependency>
             <groupId>com.google.gwt</groupId>
             <artifactId>gwt-user</artifactId>
-            <version>2.1-SNAPSHOT</version>
+            <version>${gwt.version}</version>
             <scope>provided</scope>
         </dependency>
     <dependency>
@@ -625,7 +620,7 @@
                 <configuration>
 				<logLevel>INFO</logLevel>
 				<style>PRETTY</style>
-                <gwtVersion>2.1-SNAPSHOT</gwtVersion>
+                <gwtVersion>${gwt.version}</gwtVersion>
 				<runTarget>/Expenses.html</runTarget>
                 <hostedWebapp>${project.build.directory}/${project.build.finalName}</hostedWebapp>
 				<modules>
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml
index 3b81103..e70fe2e 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml
@@ -9,11 +9,20 @@
   <inherits name='com.google.gwt.user.cellview.CellView'/>
 
   <source path='client'/>
-  <source path='request'/>
-  <source path='place'/>
-  <source path='ui'/>
+  <source path='shared'/>
 
   <!-- Default Locale. -->
   <extend-property name="locale" values="en"/>
   <set-property-fallback name="locale" value="en"/>
+
+  <inherits name='com.google.gwt.logging.Logging'/>
+  <set-property name="gwt.logging.enabled" value="TRUE"/> 
+  <set-property name="gwt.logging.logLevel" value="SEVERE"/>
+  <set-property name="gwt.logging.consoleHandler" value="ENABLED" />
+  <set-property name="gwt.logging.developmentModeHandler" value="ENABLED" />
+  <set-property name="gwt.logging.firebugHandler" value="ENABLED" />
+  <set-property name="gwt.logging.hasWidgetsHandler" value="DISABLED" />
+  <set-property name="gwt.logging.popupHandler" value="DISABLED" />
+  <set-property name="gwt.logging.systemHandler" value="ENABLED" />
+  <set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED" />
 </module>
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Approval.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Approval.java
new file mode 100644
index 0000000..17a34f6
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Approval.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client;
+
+import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+import com.google.gwt.sample.expenses.client.style.Styles;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+
+/**
+ * An enum describing the approval status.
+ */
+public enum Approval {
+  BLANK("", "inherit", Styles.resources().blankIcon()), APPROVED("Approved",
+      "#00aa00", Styles.resources().approvedIcon()), DENIED("Denied",
+      "#ff0000", Styles.resources().deniedIcon());
+
+  /**
+   * Get the {@link Approval} from the specified string.
+   * 
+   * @param approval the approval string
+   * @return the {@link Approval}
+   */
+  public static Approval from(String approval) {
+    if (APPROVED.is(approval)) {
+      return APPROVED;
+    } else if (DENIED.is(approval)) {
+      return DENIED;
+    }
+    return BLANK;
+  }
+
+  private final String color;
+  private final SafeHtml iconHtml;
+  private final String text;
+
+  private Approval(String text, String color, ImageResource res) {
+    this.text = text;
+    this.color = color;
+    this.iconHtml = SafeHtmlUtils.fromTrustedString(AbstractImagePrototype.create(res).getHTML());
+  }
+
+  public String getColor() {
+    return color;
+  }
+
+  public SafeHtml getIconHtml() {
+    return iconHtml;
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public boolean is(String compare) {
+    return text.equals(compare);
+  }
+}
\ No newline at end of file
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/DenialPopup.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/DenialPopup.java
new file mode 100644
index 0000000..0ec6adf
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/DenialPopup.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client;
+
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.sample.expenses.client.style.Styles;
+import com.google.gwt.sample.expenses.shared.ExpenseProxy;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasVerticalAlignment;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.TextBox;
+
+/**
+ * The popup used to enter the rejection reason.
+ */
+  class DenialPopup extends PopupPanel {
+  private final Button cancelButton = new Button("Cancel",
+      new ClickHandler() {
+        public void onClick(ClickEvent event) {
+          reasonDenied = "";
+          hide();
+        }
+      });
+  private final Button confirmButton = new Button("Confirm",
+      new ClickHandler() {
+        public void onClick(ClickEvent event) {
+          reasonDenied = reasonBox.getText();
+          hide();
+        }
+      });
+
+  private ExpenseProxy expenseRecord;
+  private final TextBox reasonBox = new TextBox();
+  private String reasonDenied;
+
+  public DenialPopup() {
+    super(false, true);
+    setStyleName(Styles.common().popupPanel());
+    setGlassEnabled(true);
+    confirmButton.setWidth("11ex");
+    cancelButton.setWidth("11ex");
+    reasonBox.getElement().getStyle().setMarginLeft(10.0, Unit.PX);
+    reasonBox.getElement().getStyle().setMarginRight(10.0, Unit.PX);
+
+    HorizontalPanel hPanel = new HorizontalPanel();
+    hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
+    hPanel.add(new HTML("<b>Reason:</b>"));
+    hPanel.add(reasonBox);
+    hPanel.add(confirmButton);
+    hPanel.add(cancelButton);
+    setWidget(hPanel);
+    cancelButton.getElement().getParentElement().getStyle().setPaddingLeft(
+        5.0, Unit.PX);
+  }
+
+  public ExpenseProxy getExpenseRecord() {
+    return expenseRecord;
+  }
+
+  public String getReasonDenied() {
+    return reasonDenied;
+  }
+
+  public void popup() {
+    center();
+    reasonBox.setFocus(true);
+  }
+
+  public void setExpenseRecord(ExpenseProxy expenseRecord) {
+    this.expenseRecord = expenseRecord;
+  }
+
+  public void setReasonDenied(String reasonDenied) {
+    this.reasonDenied = reasonDenied;
+    reasonBox.setText(reasonDenied);
+  }
+}
\ No newline at end of file
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseDetails.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportDetails.java
similarity index 86%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseDetails.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportDetails.java
index a37c2fc..455e0cf 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseDetails.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportDetails.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2010 Google Inc.
- *
+ * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- *
+ * 
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.sample.expenses.client;
 
+import com.google.gwt.activity.shared.Activity;
 import com.google.gwt.cell.client.AbstractInputCell;
 import com.google.gwt.cell.client.Cell;
 import com.google.gwt.cell.client.DateCell;
@@ -27,7 +28,6 @@
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.dom.client.SelectElement;
-import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.event.dom.client.BlurEvent;
 import com.google.gwt.event.dom.client.BlurHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -43,31 +43,33 @@
 import com.google.gwt.requestfactory.shared.EntityProxyChange;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
 import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.ui.client.EntityProxyKeyProvider;
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
+import com.google.gwt.safehtml.client.SafeHtmlTemplates.Template;
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.safehtml.shared.SafeHtmlUtils;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
-import com.google.gwt.sample.expenses.client.request.ExpenseRequest;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
-import com.google.gwt.sample.expenses.client.request.ReportRequest;
+import com.google.gwt.sample.expenses.client.place.ReportListPlace;
+import com.google.gwt.sample.expenses.client.place.ReportPlace;
 import com.google.gwt.sample.expenses.client.style.Styles;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpenseProxy;
+import com.google.gwt.sample.expenses.shared.ExpenseRequest;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
+import com.google.gwt.sample.expenses.shared.ReportRequest;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.cellview.client.CellTable;
 import com.google.gwt.user.cellview.client.Column;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.user.client.ui.AcceptsOneWidget;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.HasVerticalAlignment;
-import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.TextBox;
@@ -87,9 +89,43 @@
  * Details about the current expense report on the right side of the app,
  * including the list of expenses.
  */
-public class ExpenseDetails extends Composite {
+public class ExpenseReportDetails extends Composite implements Activity {
 
-  interface ExpenseDetailsUiBinder extends UiBinder<Widget, ExpenseDetails> {
+  interface Binder extends UiBinder<Widget, ExpenseReportDetails> {
+  }
+
+  /**
+   * Fetches an employee and a report in parallel. A fine example of the kind of
+   * thing that will no longer be necessary when RequestFactory provides server
+   * side method chaining.
+   */
+  class EmployeeReportFetcher {
+    ReportProxy fetchedReport;
+    EmployeeProxy fetchedEmployee;
+
+    void Run(EntityProxyId<EmployeeProxy> employeeId,
+        EntityProxyId<ReportProxy> reportId,
+        final Receiver<EmployeeReportFetcher> callback) {
+      expensesRequestFactory.find(employeeId).fire(
+          new Receiver<EmployeeProxy>() {
+            @Override
+            public void onSuccess(EmployeeProxy response) {
+              fetchedEmployee = response;
+              if (fetchedReport != null) {
+                callback.onSuccess(EmployeeReportFetcher.this);
+              }
+            }
+          });
+      expensesRequestFactory.find(reportId).fire(new Receiver<ReportProxy>() {
+        @Override
+        public void onSuccess(ReportProxy response) {
+          fetchedReport = response;
+          if (fetchedEmployee != null) {
+            callback.onSuccess(EmployeeReportFetcher.this);
+          }
+        }
+      });
+    }
   }
 
   /**
@@ -124,8 +160,8 @@
   private class ApprovalCell extends
       AbstractInputCell<String, ApprovalViewData> {
 
-    private final String approvedText = Expenses.Approval.APPROVED.getText();
-    private final String deniedText = Expenses.Approval.DENIED.getText();
+    private final String approvedText = Approval.APPROVED.getText();
+    private final String deniedText = Approval.DENIED.getText();
     private final SafeHtml errorIconHtml;
     private final SafeHtml pendingIconHtml;
 
@@ -285,72 +321,6 @@
     }
   }
 
-  /**
-   * The popup used to enter the rejection reason.
-   */
-  private class DenialPopup extends PopupPanel {
-    private final Button cancelButton = new Button("Cancel",
-        new ClickHandler() {
-          public void onClick(ClickEvent event) {
-            reasonDenied = "";
-            hide();
-          }
-        });
-    private final Button confirmButton = new Button("Confirm",
-        new ClickHandler() {
-          public void onClick(ClickEvent event) {
-            reasonDenied = reasonBox.getText();
-            hide();
-          }
-        });
-
-    private ExpenseProxy expenseRecord;
-    private final TextBox reasonBox = new TextBox();
-    private String reasonDenied;
-
-    public DenialPopup() {
-      super(false, true);
-      setStyleName(Styles.common().popupPanel());
-      setGlassEnabled(true);
-      confirmButton.setWidth("11ex");
-      cancelButton.setWidth("11ex");
-      reasonBox.getElement().getStyle().setMarginLeft(10.0, Unit.PX);
-      reasonBox.getElement().getStyle().setMarginRight(10.0, Unit.PX);
-
-      HorizontalPanel hPanel = new HorizontalPanel();
-      hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
-      hPanel.add(new HTML("<b>Reason:</b>"));
-      hPanel.add(reasonBox);
-      hPanel.add(confirmButton);
-      hPanel.add(cancelButton);
-      setWidget(hPanel);
-      cancelButton.getElement().getParentElement().getStyle().setPaddingLeft(
-          5.0, Unit.PX);
-    }
-
-    public ExpenseProxy getExpenseRecord() {
-      return expenseRecord;
-    }
-
-    public String getReasonDenied() {
-      return reasonDenied;
-    }
-
-    public void popup() {
-      center();
-      reasonBox.setFocus(true);
-    }
-
-    public void setExpenseRecord(ExpenseProxy expenseRecord) {
-      this.expenseRecord = expenseRecord;
-    }
-
-    public void setReasonDenied(String reasonDenied) {
-      this.reasonDenied = reasonDenied;
-      reasonBox.setText(reasonDenied);
-    }
-  }
-
   private static Template template;
 
   /**
@@ -363,34 +333,25 @@
    */
   private static final int REFRESH_INTERVAL = 5000;
 
-  private static ExpenseDetailsUiBinder uiBinder = GWT.create(ExpenseDetailsUiBinder.class);
+  private static Binder uiBinder = GWT.create(Binder.class);
 
-  @UiField
-  Element approvedLabel;
+  @UiField Element approvedLabel;
 
-  @UiField
-  Element costLabel;
+  @UiField Element costLabel;
 
-  @UiField
-  Element notes;
+  @UiField Element notes;
 
-  @UiField
-  TextBox notesBox;
+  @UiField TextBox notesBox;
 
-  @UiField
-  Anchor notesEditLink;
+  @UiField Anchor notesEditLink;
 
-  @UiField
-  Element notesEditLinkWrapper;
+  @UiField Element notesEditLinkWrapper;
 
-  @UiField
-  Element notesPending;
+  @UiField Element notesPending;
 
-  @UiField
-  Element reportName;
+  @UiField Element reportName;
 
-  @UiField
-  Anchor reportsLink;
+  @UiField Anchor reportsLink;
 
   @UiField(provided = true)
   CellTable<ExpenseProxy> table;
@@ -422,7 +383,7 @@
    */
   private final Label errorPopupMessage = new Label();
 
-  private ExpensesRequestFactory expensesRequestFactory;
+  private final ExpensesRequestFactory expensesRequestFactory;
 
   /**
    * The data provider that provides expense items.
@@ -462,12 +423,15 @@
    */
   private double totalApproved;
 
-  public ExpenseDetails() {
+  private ReportPlace place;
+
+  public ExpenseReportDetails(ExpensesRequestFactory expensesRequestFactory) {
+    this.expensesRequestFactory = expensesRequestFactory;
     createErrorPopup();
     initTable();
     initWidget(uiBinder.createAndBindUi(this));
     items = new ListDataProvider<ExpenseProxy>(
-        Expenses.EXPENSE_RECORD_KEY_PROVIDER);
+        new EntityProxyKeyProvider<ExpenseProxy>());
     items.addDataDisplay(table);
 
     // Switch to edit notes.
@@ -503,23 +467,20 @@
     });
   }
 
+  public ReportListPlace getReportListPlace() {
+    ReportListPlace listPlace = place.getListPlace();
+    return listPlace == null ? ReportListPlace.ALL : listPlace;
+  }
+
   public Anchor getReportsLink() {
     return reportsLink;
   }
 
-  public void init(EventBus eventBus) {
-    EntityProxyChange.registerForProxyType(eventBus, ExpenseProxy.class,
-        new EntityProxyChange.Handler<ExpenseProxy>() {
-          public void onProxyChange(EntityProxyChange<ExpenseProxy> event) {
-            onExpenseRecordChanged(event);
-          }
-        });
-    EntityProxyChange.registerForProxyType(eventBus, ReportProxy.class,
-        new EntityProxyChange.Handler<ReportProxy>() {
-          public void onProxyChange(EntityProxyChange<ReportProxy> event) {
-            onReportChanged(event);
-          }
-        });
+  public String mayStop() {
+    return null;
+  }
+
+  public void onCancel() {
   }
 
   public void onExpenseRecordChanged(EntityProxyChange<ExpenseProxy> event) {
@@ -568,52 +529,62 @@
     }
   }
 
-  public void setExpensesRequestFactory(
-      ExpensesRequestFactory expensesRequestFactory) {
-    this.expensesRequestFactory = expensesRequestFactory;
+  public void onStop() {
+  }
+
+  public void start(AcceptsOneWidget panel, EventBus eventBus) {
+    final ReportListPlace listPlace = place.getListPlace();
+
+    if (listPlace.getEmployeeId() == null) {
+      expensesRequestFactory.find(place.getReportId()).fire(
+          new Receiver<ReportProxy>() {
+            @Override
+            public void onSuccess(ReportProxy response) {
+              setReportRecord(response, listPlace.getDepartment(), null);
+            }
+          });
+    } else {
+      new EmployeeReportFetcher().Run(listPlace.getEmployeeId(),
+          place.getReportId(),
+          new Receiver<ExpenseReportDetails.EmployeeReportFetcher>() {
+            @Override
+            public void onSuccess(EmployeeReportFetcher response) {
+              setReportRecord(response.fetchedReport,
+                  listPlace.getDepartment(), response.fetchedEmployee);
+            }
+          });
+    }
+
+    EntityProxyChange.registerForProxyType(eventBus, ExpenseProxy.class,
+        new EntityProxyChange.Handler<ExpenseProxy>() {
+          public void onProxyChange(EntityProxyChange<ExpenseProxy> event) {
+            onExpenseRecordChanged(event);
+          }
+        });
+
+    EntityProxyChange.registerForProxyType(eventBus, ReportProxy.class,
+        new EntityProxyChange.Handler<ReportProxy>() {
+          public void onProxyChange(EntityProxyChange<ReportProxy> event) {
+            onReportChanged(event);
+          }
+        });
+
+    panel.setWidget(this);
   }
 
   /**
-   * Set the {@link ReportProxy} to show.
-   *
-   * @param report the {@link ReportProxy}
-   * @param department the selected department
-   * @param employee the selected employee
+   * In this application, called by {@link ExpensesActivityMapper} each time a
+   * ReportListPlace is posted. In a more typical set up, this would be a
+   * constructor argument to a one shot activity, perhaps managing a shared
+   * widget view instance.
    */
-  public void setReportRecord(ReportProxy report, String department,
-      EmployeeProxy employee) {
-    this.report = report;
-    knownExpenseKeys = null;
-    reportName.setInnerText(report.getPurpose());
-    costLabel.setInnerText("");
-    approvedLabel.setInnerText("");
-    unreconciledLabel.setInnerText("");
-    setNotesEditState(false, false, report.getNotes());
-    items.getList().clear();
-    totalApproved = 0;
-
-    // Update the breadcrumb.
-    reportsLink.setText(ExpenseList.getBreadcrumb(department, employee));
-
-    // Reset sorting state of table
-    lastComparator = defaultComparator;
-    if (allHeaders.size() > 0) {
-      for (SortableHeader header : allHeaders) {
-        header.setSorted(false);
-        header.setReverseSort(true);
-      }
-      allHeaders.get(0).setSorted(true);
-      allHeaders.get(0).setReverseSort(false);
-      table.redrawHeaders();
-    }
-
-    // Request the expenses.
-    requestExpenses();
+  public void updateForPlace(final ReportPlace place) {
+    this.place = place;
   }
 
   /**
    * Add a column of a {@link Comparable} type using default comparators.
-   *
+   * 
    * @param <C> the column type
    * @param table the table
    * @param text the header text
@@ -631,7 +602,7 @@
 
   /**
    * Add a column with the specified comparators.
-   *
+   * 
    * @param <C> the column type
    * @param table the table
    * @param text the header text
@@ -681,7 +652,7 @@
 
   /**
    * Create a comparator for the column.
-   *
+   * 
    * @param <C> the column type
    * @param getter the {@link GetValue} used to get the cell value
    * @param descending true if descending, false if ascending
@@ -740,7 +711,7 @@
 
   /**
    * Return a formatted currency string.
-   *
+   * 
    * @param amount the amount in dollars
    * @return a formatted string
    */
@@ -770,7 +741,7 @@
    * Get the columns displayed in the expense table.
    */
   private String[] getExpenseColumns() {
-    return new String[]{
+    return new String[] {
         "amount", "approval", "category", "created", "description",
         "reasonDenied"};
   }
@@ -778,7 +749,7 @@
   private CellTable<ExpenseProxy> initTable() {
     CellTable.Resources resources = GWT.create(TableResources.class);
     table = new CellTable<ExpenseProxy>(100, resources,
-        Expenses.EXPENSE_RECORD_KEY_PROVIDER);
+        new EntityProxyKeyProvider<ExpenseProxy>());
     Styles.Common common = Styles.common();
 
     table.addColumnStyleName(0, common.spacerColumn());
@@ -896,7 +867,7 @@
     for (ExpenseProxy record : records) {
       double cost = record.getAmount();
       totalCost += cost;
-      if (Expenses.Approval.APPROVED.is(record.getApproval())) {
+      if (Approval.APPROVED.is(record.getApproval())) {
         totalApproved += cost;
       }
     }
@@ -980,7 +951,7 @@
 
   /**
    * Set the state of the notes section.
-   *
+   * 
    * @param editable true for edit state, false for view state
    * @param pending true if changes are pending, false if not
    * @param notesText the current notes
@@ -998,8 +969,46 @@
   }
 
   /**
+   * Set the {@link ReportProxy} to show.
+   * 
+   * @param report the {@link ReportProxy}
+   * @param department the selected department, or ""
+   * @param employee the selected employee, or null
+   */
+  private void setReportRecord(ReportProxy report, String department,
+      EmployeeProxy employee) {
+    this.report = report;
+    knownExpenseKeys = null;
+    reportName.setInnerText(report.getPurpose());
+    costLabel.setInnerText("");
+    approvedLabel.setInnerText("");
+    unreconciledLabel.setInnerText("");
+    setNotesEditState(false, false, report.getNotes());
+    items.getList().clear();
+    totalApproved = 0;
+
+    // Update the breadcrumb.
+    reportsLink.setText(ExpenseReportList.getBreadcrumb(department, employee));
+
+    // Reset sorting state of table
+    lastComparator = defaultComparator;
+    if (allHeaders.size() > 0) {
+      for (SortableHeader header : allHeaders) {
+        header.setSorted(false);
+        header.setReverseSort(true);
+      }
+      allHeaders.get(0).setSorted(true);
+      allHeaders.get(0).setReverseSort(false);
+      table.redrawHeaders();
+    }
+
+    // Request the expenses.
+    requestExpenses();
+  }
+
+  /**
    * Show the error popup.
-   *
+   * 
    * @param errorMessage the error message
    */
   private void showErrorPopup(String errorMessage) {
@@ -1015,7 +1024,7 @@
 
   /**
    * Update the state of a pending approval change.
-   *
+   * 
    * @param record the {@link ExpenseProxy} to sync
    * @param message the error message if rejected, or null if accepted
    */
@@ -1035,8 +1044,8 @@
   private void updateExpenseRecord(final ExpenseProxy record, String approval,
       String reasonDenied) {
     // Verify that the total is under the cap.
-    if (Expenses.Approval.APPROVED.is(approval)
-        && !Expenses.Approval.APPROVED.is(record.getApproval())) {
+    if (Approval.APPROVED.is(approval)
+        && !Approval.APPROVED.is(record.getApproval())) {
       double amount = record.getAmount();
       if (amount + totalApproved > MAX_COST) {
         syncCommit(record,
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseDetails.ui.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportDetails.ui.xml
similarity index 100%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseDetails.ui.xml
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportDetails.ui.xml
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseList.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportList.java
similarity index 85%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseList.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportList.java
index 99e7b00..bb40add 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseList.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportList.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2010 Google Inc.
- *
+ * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- *
+ * 
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.sample.expenses.client;
 
+import com.google.gwt.activity.shared.Activity;
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
 import com.google.gwt.cell.client.DateCell;
@@ -37,30 +38,32 @@
 import com.google.gwt.requestfactory.shared.EntityProxyChange;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
 import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.ui.client.EntityProxyKeyProvider;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
 import com.google.gwt.safehtml.shared.SafeHtmlUtils;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
+import com.google.gwt.sample.expenses.client.place.ReportListPlace;
 import com.google.gwt.sample.expenses.client.style.Styles;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiFactory;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.cellview.client.CellTable;
 import com.google.gwt.user.cellview.client.Column;
-import com.google.gwt.user.cellview.client.SimplePager;
 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
+import com.google.gwt.user.cellview.client.SimplePager;
 import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
 import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.AcceptsOneWidget;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.view.client.AsyncDataProvider;
-import com.google.gwt.view.client.HasData;
 import com.google.gwt.view.client.NoSelectionModel;
 import com.google.gwt.view.client.ProvidesKey;
 import com.google.gwt.view.client.Range;
+import com.google.gwt.view.client.RangeChangeEvent;
 import com.google.gwt.view.client.SelectionChangeEvent;
 
 import java.util.ArrayList;
@@ -72,10 +75,10 @@
 /**
  * The list of expense reports on the right side of the app.
  */
-public class ExpenseList extends Composite implements
-    EntityProxyChange.Handler<ReportProxy> {
+public class ExpenseReportList extends Composite implements
+    EntityProxyChange.Handler<ReportProxy>, Activity {
 
-  interface ExpenseListUiBinder extends UiBinder<Widget, ExpenseList> {
+  interface Binder extends UiBinder<Widget, ExpenseReportList> {
   }
 
   /**
@@ -85,7 +88,7 @@
 
     /**
      * Called when the user selects a report.
-     *
+     * 
      * @param report the selected report
      */
     void onReportSelected(ReportProxy report);
@@ -173,40 +176,29 @@
       }
     }
   }
-  /**
-   * The data provider used to retrieve reports.
-   */
-  private class ReportDataProvider extends AsyncDataProvider<ReportProxy> {
 
-    ReportDataProvider(ProvidesKey<ReportProxy> keyProvider) {
-      super(keyProvider);
-    }
-
-    @Override
-    protected void onRangeChanged(HasData<ReportProxy> display) {
-      requestReports(false);
-    }
-  }
+  private static final ProvidesKey<ReportProxy> keyProvider = new EntityProxyKeyProvider<ReportProxy>();
 
   /**
    * The auto refresh interval in milliseconds.
    */
   private static final int REFRESH_INTERVAL = 5000;
 
-  private static ExpenseListUiBinder uiBinder = GWT.create(ExpenseListUiBinder.class);
+  private static Binder uiBinder = GWT.create(Binder.class);
 
   /**
    * Utility method to get the first part of the breadcrumb based on the
    * department and employee.
-   *
+   * 
    * @param department the selected department
    * @param employee the selected employee
    * @return the breadcrumb
    */
   public static String getBreadcrumb(String department, EmployeeProxy employee) {
+    assert null != department;
     if (employee != null) {
       return "Reports for " + employee.getDisplayName();
-    } else if (department != null) {
+    } else if (!"".equals(department)) {
       return "Reports for " + department;
     } else {
       return "All Reports";
@@ -215,13 +207,14 @@
 
   @UiField
   Element breadcrumb;
-
   @UiField
   SimplePager pager;
-  @UiField(provided = true)
-  DefaultTextBox searchBox;
   @UiField
   Image searchButton;
+
+  @UiField(provided = true)
+  DefaultTextBox searchBox;
+
   /**
    * The main table. We provide this in the constructor before calling
    * {@link UiBinder#createAndBindUi(Object)} because the pager depends on it.
@@ -287,14 +280,9 @@
       "created", "purpose", "notes"};
 
   /**
-   * The data provider that provides reports.
-   */
-  private final ReportDataProvider reports = new ReportDataProvider(Expenses.REPORT_RECORD_KEY_PROVIDER);
-
-  /**
    * The factory used to send requests.
    */
-  private ExpensesRequestFactory requestFactory;
+  private final ExpensesRequestFactory requestFactory;
 
   /**
    * The string that the user searched for.
@@ -306,15 +294,23 @@
    */
   private String startsWithSearch;
 
-  public ExpenseList() {
+  private ReportListPlace place;
+
+  private boolean running;
+
+  public ExpenseReportList(ExpensesRequestFactory requestFactory) {
+    this.requestFactory = requestFactory;
+
     // Initialize the widget.
     createTable();
+    table.addRangeChangeHandler(new RangeChangeEvent.Handler() {
+      public void onRangeChange(RangeChangeEvent event) {
+        requestReports(false);
+      }
+    });
     searchBox = new DefaultTextBox("search");
     initWidget(uiBinder.createAndBindUi(this));
 
-    // Add the view to the data provider.
-    reports.addDataDisplay(table);
-
     // Listen for key events from the text boxes.
     searchBox.addKeyUpHandler(new KeyUpHandler() {
       public void onKeyUp(KeyUpEvent event) {
@@ -341,10 +337,12 @@
     });
   }
 
-  public void init(ExpensesRequestFactory factory, EventBus eventBus) {
-    EntityProxyChange.registerForProxyType(eventBus, ReportProxy.class, this);
-    this.requestFactory = factory;
-    requestReports(false);
+  public String mayStop() {
+    return null;
+  }
+
+  public void onCancel() {
+    onStop();
   }
 
   public void onProxyChange(EntityProxyChange<ReportProxy> event) {
@@ -355,36 +353,43 @@
       if (record != null && changedId.equals(record.stableId())) {
         List<ReportProxy> changedList = new ArrayList<ReportProxy>();
         changedList.add(record);
-        reports.updateRowData(i + table.getPageStart(), changedList);
+        table.setRowData(i + table.getPageStart(), changedList);
       }
       i++;
     }
   }
 
-  /**
-   * Set the current department and employee to filter on.
-   *
-   * @param department the department, or null if none selected
-   * @param employee the employee, or null if none selected
-   */
-  public void setEmployee(String department, EmployeeProxy employee) {
-    this.department = department;
-    this.employee = employee;
-    isCountStale = true;
-    searchBox.resetDefaultText();
-    startsWithSearch = null;
-    breadcrumb.setInnerText(getBreadcrumb(department, employee));
-    searchRegExp = null;
-
-    // Refresh the table.
-    pager.setPageStart(0);
-    requestReports(false);
+  public void onStop() {
+    running = false;
+    refreshTimer.cancel();
   }
 
   public void setListener(Listener listener) {
     this.listener = listener;
   }
 
+  public void start(AcceptsOneWidget panel, EventBus eventBus) {
+    running = true;
+    doUpdateForPlace();
+
+    EntityProxyChange.registerForProxyType(eventBus, ReportProxy.class, this);
+    requestReports(false);
+    panel.setWidget(this);
+  }
+
+  /**
+   * In this application, called by {@link ExpensesActivityMapper} each time a
+   * ReportListPlace is posted. In a more typical set up, this would be a
+   * constructor argument to a one shot activity, perhaps managing a shared
+   * widget view instance.
+   */
+  public void updateForPlace(final ReportListPlace place) {
+    this.place = place;
+    if (running) {
+      doUpdateForPlace();
+    }
+  }
+
   @UiFactory
   SimplePager createPager() {
     SimplePager p = new SimplePager(TextLocation.RIGHT);
@@ -395,7 +400,7 @@
 
   /**
    * Add a sortable column to the table.
-   *
+   * 
    * @param <C> the data type for the column
    * @param text the header text
    * @param cell the cell used to render the column
@@ -517,9 +522,42 @@
     table.addColumn(new SpacerColumn<ReportProxy>());
   }
 
+  private void doUpdateForPlace() {
+    if (place.getEmployeeId() == null) {
+      findDepartmentOrEmployee(place.getDepartment(), null);
+    } else {
+      requestFactory.find(place.getEmployeeId()).fire(
+          new Receiver<EmployeeProxy>() {
+            @Override
+            public void onSuccess(EmployeeProxy response) {
+              findDepartmentOrEmployee("", response);
+            }
+          });
+    }
+  }
+
+  /**
+   * Set the current department and employee to filter on.
+   * 
+   * @param department the department, or null if none selected
+   * @param employee the employee, or null if none selected
+   */
+  private void findDepartmentOrEmployee(String department,
+      EmployeeProxy employee) {
+    this.department = department;
+    this.employee = employee;
+    isCountStale = true;
+    searchBox.resetDefaultText();
+    startsWithSearch = null;
+    breadcrumb.setInnerText(getBreadcrumb(department, employee));
+    searchRegExp = null;
+    pager.setPageStart(0);
+    requestReports(false);
+  }
+
   /**
    * Send a request for reports in the current range.
-   *
+   * 
    * @param isPolling true if this request is caused by polling
    */
   private void requestReports(boolean isPolling) {
@@ -566,7 +604,7 @@
           if (this == lastDataSizeReceiver) {
             int count = response.intValue();
             // Treat count == 1000 as inexact due to AppEngine limitation
-            reports.updateRowCount(count, count != 1000);
+            table.setRowCount(count, count != 1000);
           }
         }
       };
@@ -582,10 +620,10 @@
           int size = newValues.size();
           if (size < table.getPageSize()) {
             // Now we know the exact data size
-            reports.updateRowCount(table.getPageStart() + size, true);
+            table.setRowCount(table.getPageStart() + size, true);
           }
           if (size > 0) {
-            reports.updateRowData(table.getPageStart(), newValues);
+            table.setRowData(table.getPageStart(), newValues);
           }
 
           // Add the new keys to the known keys.
@@ -594,10 +632,10 @@
             knownReportKeys = new HashSet<Object>();
           }
           for (ReportProxy value : newValues) {
-            Object key = reports.getKey(value);
+            Object key = keyProvider.getKey(value);
             if (!isInitialData && !knownReportKeys.contains(key)) {
-              (new PhaseAnimation.CellTablePhaseAnimation<ReportProxy>(table,
-                  value, reports)).run();
+              new PhaseAnimation.CellTablePhaseAnimation<ReportProxy>(table,
+                  value, keyProvider).run();
             }
             knownReportKeys.add(key);
           }
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseList.ui.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportList.ui.xml
similarity index 100%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseList.ui.xml
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseReportList.ui.xml
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseTree.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseTree.java
index d7af1533..49d29be 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseTree.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpenseTree.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2010 Google Inc.
- *
+ * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- *
+ * 
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -21,13 +21,16 @@
 import com.google.gwt.cell.client.TextCell;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Style.Overflow;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
 import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.ui.client.EntityProxyKeyProvider;
 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
+import com.google.gwt.safehtml.client.SafeHtmlTemplates.Template;
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
 import com.google.gwt.sample.expenses.client.style.Styles;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
 import com.google.gwt.user.cellview.client.CellTree;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.view.client.AsyncDataProvider;
@@ -53,11 +56,11 @@
 
     /**
      * Called when the user selects a tree item.
-     *
+     * 
      * @param department the selected department name
      * @param employee the selected employee
      */
-    void onSelection(String department, EmployeeProxy employee);
+    void onSelection(String department, EntityProxyId<EmployeeProxy> employeeId);
   }
 
   interface Template extends SafeHtmlTemplates {
@@ -74,8 +77,7 @@
       super(Styles.resources().userIcon(), new AbstractCell<EmployeeProxy>() {
 
         private final String usernameStyle = Styles.common().usernameTreeItem();
-        private final String usernameStyleSelected =
-            Styles.common().usernameTreeItemSelected();
+        private final String usernameStyleSelected = Styles.common().usernameTreeItemSelected();
 
         @Override
         public boolean dependsOnSelection() {
@@ -83,8 +85,8 @@
         }
 
         @Override
-        public void render(
-            EmployeeProxy value, Object viewData, SafeHtmlBuilder sb) {
+        public void render(EmployeeProxy value, Object viewData,
+            SafeHtmlBuilder sb) {
           if (value != null) {
             StringBuilder classesBuilder = new StringBuilder(usernameStyle);
             if (lastEmployee != null
@@ -94,7 +96,8 @@
 
             sb.appendEscaped(value.getDisplayName());
             sb.appendHtmlConstant("<br>");
-            sb.append(template.span(classesBuilder.toString(), value.getUserName()));
+            sb.append(template.span(classesBuilder.toString(),
+                value.getUserName()));
           }
         }
       });
@@ -107,7 +110,8 @@
   /**
    * The {@link ListDataProvider} used for Employee lists.
    */
-  private class EmployeeListDataProvider extends AsyncDataProvider<EmployeeProxy> {
+  private class EmployeeListDataProvider extends
+      AsyncDataProvider<EmployeeProxy> {
 
     private final String department;
 
@@ -121,13 +125,13 @@
       super.addDataDisplay(display);
 
       // Request the count anytime a view is added.
-      requestFactory.employeeRequest().countEmployeesByDepartment(
-          department).fire(new Receiver<Long>() {
-        @Override
-        public void onSuccess(Long response) {
-          updateRowCount(response.intValue(), true);
-        }
-      });
+      requestFactory.employeeRequest().countEmployeesByDepartment(department).fire(
+          new Receiver<Long>() {
+            @Override
+            public void onSuccess(Long response) {
+              updateRowCount(response.intValue(), true);
+            }
+          });
     }
 
     @Override
@@ -135,11 +139,13 @@
       Range range = view.getVisibleRange();
       requestFactory.employeeRequest().findEmployeeEntriesByDepartment(
           department, range.getStart(), range.getLength()).with(
-          getEmployeeMenuProperties()).fire(new Receiver<List<EmployeeProxy>>(){
+          getEmployeeMenuProperties()).fire(
+          new Receiver<List<EmployeeProxy>>() {
             @Override
             public void onSuccess(List<EmployeeProxy> response) {
               updateRowData(0, response);
-            }});
+            }
+          });
     }
   }
 
@@ -161,8 +167,8 @@
     public <T> NodeInfo<?> getNodeInfo(T value) {
       if (value == null) {
         // Top level.
-        return new DefaultNodeInfo<String>(
-            departments, departmentCell, selectionModel, null);
+        return new DefaultNodeInfo<String>(departments, departmentCell,
+            selectionModel, null);
       } else if (isAllDepartment(value)) {
         // Employees are not displayed under the 'All' Department.
         return null;
@@ -170,8 +176,8 @@
         // Second level.
         EmployeeListDataProvider dataProvider = new EmployeeListDataProvider(
             (String) value);
-        return new DefaultNodeInfo<EmployeeProxy>(
-            dataProvider, employeeCell, selectionModel, null);
+        return new DefaultNodeInfo<EmployeeProxy>(dataProvider, employeeCell,
+            selectionModel, null);
       }
 
       return null;
@@ -223,16 +229,18 @@
   /**
    * The factory used to send requests.
    */
-  private ExpensesRequestFactory requestFactory;
+  private final ExpensesRequestFactory requestFactory;
 
   /**
    * The shared {@link SingleSelectionModel}.
    */
   private final SingleSelectionModel<Object> selectionModel = new SingleSelectionModel<Object>(
       new ProvidesKey<Object>() {
+        EntityProxyKeyProvider<EmployeeProxy> keyProvider = new EntityProxyKeyProvider<EmployeeProxy>();
+
         public Object getKey(Object item) {
           if (item instanceof EmployeeProxy) {
-            return Expenses.EMPLOYEE_RECORD_KEY_PROVIDER.getKey((EmployeeProxy) item);
+            return keyProvider.getKey((EmployeeProxy) item);
           }
           return item;
         }
@@ -243,11 +251,13 @@
    */
   private CellTree tree;
 
-  public ExpenseTree() {
+  public ExpenseTree(ExpensesRequestFactory requestFactory) {
+    this.requestFactory = requestFactory;
+
     // Initialize the departments.
     List<String> departmentList = departments.getList();
     departmentList.add("All");
-    for (String department : Expenses.DEPARTMENTS) {
+    for (String department : ExpensesApp.DEPARTMENTS) {
       departmentList.add(department);
     }
 
@@ -261,10 +271,6 @@
     this.listener = listener;
   }
 
-  public void setRequestFactory(ExpensesRequestFactory factory) {
-    this.requestFactory = factory;
-  }
-
   /**
    * Create the {@link CellTree}.
    */
@@ -273,29 +279,29 @@
 
     // Listen for selection. We need to add this handler before the CellBrowser
     // adds its own handler.
-    selectionModel.addSelectionChangeHandler(
-        new SelectionChangeEvent.Handler() {
-          public void onSelectionChange(SelectionChangeEvent event) {
-            Object selected = selectionModel.getSelectedObject();
-            if (selected == null) {
-              lastEmployee = null;
-              lastDepartment = null;
-            } else if (selected instanceof EmployeeProxy) {
-              lastEmployee = (EmployeeProxy) selected;
-            } else if (selected instanceof String) {
-              lastEmployee = null;
-              if (model.isAllDepartment(selected)) {
-                lastDepartment = null;
-              } else {
-                lastDepartment = (String) selected;
-              }
-            }
-
-            if (listener != null) {
-              listener.onSelection(lastDepartment, lastEmployee);
-            }
+    selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+      public void onSelectionChange(SelectionChangeEvent event) {
+        Object selected = selectionModel.getSelectedObject();
+        if (selected == null) {
+          lastEmployee = null;
+          lastDepartment = "";
+        } else if (selected instanceof EmployeeProxy) {
+          lastEmployee = (EmployeeProxy) selected;
+        } else if (selected instanceof String) {
+          lastEmployee = null;
+          if (model.isAllDepartment(selected)) {
+            lastDepartment = "";
+          } else {
+            lastDepartment = (String) selected;
           }
-        });
+        }
+
+        if (listener != null) {
+          listener.onSelection(lastDepartment, lastEmployee == null ? null
+              : lastEmployee.stableId());
+        }
+      }
+    });
 
     // Create a CellBrowser.
     tree = new CellTree(model, null);
@@ -303,6 +309,6 @@
   }
 
   private String[] getEmployeeMenuProperties() {
-    return new String[]{"displayName", "userName"};
+    return new String[] {"displayName", "userName"};
   }
 }
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java
index a7bc579..c04cca8 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java
@@ -16,176 +16,15 @@
 package com.google.gwt.sample.expenses.client;
 
 import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.SimpleEventBus;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestEvent;
-import com.google.gwt.requestfactory.shared.UserInformationProxy;
-import com.google.gwt.requestfactory.ui.client.AuthenticationFailureHandler;
-import com.google.gwt.requestfactory.ui.client.LoginWidget;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.safehtml.shared.SafeHtml;
-import com.google.gwt.safehtml.shared.SafeHtmlUtils;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
-import com.google.gwt.sample.expenses.client.style.Styles;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.Window.Location;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.sample.expenses.client.ioc.ExpensesFactory;
 import com.google.gwt.user.client.ui.RootLayoutPanel;
-import com.google.gwt.view.client.ProvidesKey;
 
 /**
  * Entry point for the Expenses app.
  */
 public class Expenses implements EntryPoint {
 
-  /**
-   * An enum describing the approval status.
-   */
-  public static enum Approval {
-    BLANK("", "inherit", Styles.resources().blankIcon()), APPROVED("Approved",
-        "#00aa00", Styles.resources().approvedIcon()), DENIED("Denied",
-        "#ff0000", Styles.resources().deniedIcon());
-
-    /**
-     * Get the {@link Approval} from the specified string.
-     * 
-     * @param approval the approval string
-     * @return the {@link Approval}
-     */
-    public static Approval from(String approval) {
-      if (APPROVED.is(approval)) {
-        return APPROVED;
-      } else if (DENIED.is(approval)) {
-        return DENIED;
-      }
-      return BLANK;
-    }
-
-    private final String color;
-    private final SafeHtml iconHtml;
-    private final String text;
-
-    private Approval(String text, String color, ImageResource res) {
-      this.text = text;
-      this.color = color;
-      this.iconHtml = SafeHtmlUtils.fromTrustedString(AbstractImagePrototype.create(res).getHTML());
-    }
-
-    public String getColor() {
-      return color;
-    }
-
-    public SafeHtml getIconHtml() {
-      return iconHtml;
-    }
-
-    public String getText() {
-      return text;
-    }
-
-    public boolean is(String compare) {
-      return text.equals(compare);
-    }
-  }
-
-  public static final String[] DEPARTMENTS = {
-      "Engineering", "Finance", "Marketing", "Operations", "Sales"};
-
-  /**
-   * The key provider for {@link EmployeeProxy}s.
-   */
-  public static final ProvidesKey<EmployeeProxy> EMPLOYEE_RECORD_KEY_PROVIDER =
-    new ProvidesKey<EmployeeProxy>() {
-    public Object getKey(EmployeeProxy item) {
-      return item == null ? null : item.getId();
-    }
-  };
-
-  /**
-   * The key provider for {@link ExpenseProxy}s.
-   */
-  public static final ProvidesKey<ExpenseProxy> EXPENSE_RECORD_KEY_PROVIDER =
-    new ProvidesKey<ExpenseProxy>() {
-    public Object getKey(ExpenseProxy item) {
-      return item == null ? null : item.getId();
-    }
-  };
-
-  /**
-   * The key provider for {@link ReportProxy}s.
-   */
-  public static final ProvidesKey<ReportProxy> REPORT_RECORD_KEY_PROVIDER =
-    new ProvidesKey<ReportProxy>() {
-    public Object getKey(ReportProxy item) {
-      return (item == null) ? null : item.getId();
-    }
-  };
-
-  private String lastDepartment;
-  private EmployeeProxy lastEmployee;
-  private ExpensesRequestFactory requestFactory;
-  private ExpensesShell shell;
-
   public void onModuleLoad() {
-    GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
-      public void onUncaughtException(Throwable e) {
-        Window.alert("Error: " + e.getMessage());
-//        placeController.goTo(Place.NOWHERE);
-      }
-    });
-    
-    final EventBus eventBus = new SimpleEventBus();
-    requestFactory = GWT.create(ExpensesRequestFactory.class);
-    requestFactory.initialize(eventBus);
-
-    RootLayoutPanel root = RootLayoutPanel.get();
-
-    shell = new ExpensesShell();
-    final ExpenseTree expenseTree = shell.getExpenseTree();
-    final ExpenseList expenseList = shell.getExpenseList();
-    final ExpenseDetails expenseDetails = shell.getExpenseDetails();
-
-    root.add(shell);
-    
-    // Check for Authentication failures or mismatches
-    RequestEvent.register(eventBus, new AuthenticationFailureHandler());
-
-    // Add a login widget to the page
-    final LoginWidget login = shell.getLoginWidget();
-    Receiver<UserInformationProxy> receiver = new Receiver<UserInformationProxy>() {
-      @Override
-      public void onSuccess(UserInformationProxy userInformationRecord) {
-        login.setUserInformation(userInformationRecord);
-      }       
-     };
-     requestFactory.userInformationRequest().getCurrentUserInformation(
-         Location.getHref()).fire(receiver);
-
-    // Listen for requests from ExpenseTree.
-    expenseTree.setListener(new ExpenseTree.Listener() {
-      public void onSelection(String department, EmployeeProxy employee) {
-        lastDepartment = department;
-        lastEmployee = employee;
-        expenseList.setEmployee(department, employee);
-        shell.showExpenseDetails(false);
-      }
-    });
-    expenseTree.setRequestFactory(requestFactory);
-
-    // Listen for requests from the ExpenseList.
-    expenseList.setListener(new ExpenseList.Listener() {
-      public void onReportSelected(ReportProxy report) {
-        expenseDetails.setExpensesRequestFactory(requestFactory);
-        expenseDetails.setReportRecord(report, lastDepartment, lastEmployee);
-        shell.showExpenseDetails(true);
-      }
-    });
-    expenseList.init(requestFactory, eventBus);
-    expenseDetails.init(eventBus);
+    new ExpensesFactory().getExpensesApp().run(RootLayoutPanel.get());
   }
 }
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesActivityMapper.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesActivityMapper.java
new file mode 100644
index 0000000..ed58976
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesActivityMapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client;
+
+import com.google.gwt.activity.shared.Activity;
+import com.google.gwt.activity.shared.ActivityMapper;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.sample.expenses.client.place.ReportListPlace;
+import com.google.gwt.sample.expenses.client.place.ReportPlace;
+
+/**
+ * ActivityMapper for the Expenses app.
+ */
+public class ExpensesActivityMapper implements ActivityMapper {
+
+  private final ExpenseReportDetails expenseDetails;
+  private final ExpenseReportList expenseList;
+
+  public ExpensesActivityMapper(ExpenseReportDetails expenseDetails,
+      ExpenseReportList expenseList) {
+    this.expenseDetails = expenseDetails;
+    this.expenseList = expenseList;
+  }
+
+  public Activity getActivity(Place place) {
+    if (place instanceof ReportListPlace) {
+      expenseList.updateForPlace((ReportListPlace) place);
+      return expenseList;
+    }
+
+    if (place instanceof ReportPlace) {
+      expenseDetails.updateForPlace((ReportPlace) place);
+      return expenseDetails;
+    }
+
+    return null;
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesApp.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesApp.java
new file mode 100644
index 0000000..0975f0a
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesApp.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client;
+
+import com.google.gwt.activity.shared.ActivityManager;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.place.shared.PlaceController;
+import com.google.gwt.place.shared.PlaceHistoryHandler;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.RequestEvent;
+import com.google.gwt.requestfactory.shared.UserInformationProxy;
+import com.google.gwt.requestfactory.ui.client.AuthenticationFailureHandler;
+import com.google.gwt.requestfactory.ui.client.LoginWidget;
+import com.google.gwt.sample.expenses.client.place.ReportListPlace;
+import com.google.gwt.sample.expenses.client.place.ReportPlace;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
+import com.google.gwt.user.client.Window.Location;
+import com.google.gwt.user.client.ui.HasWidgets;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Entry point for the Expenses app.
+ */
+public class ExpensesApp {
+  /**
+   * TODO: This belongs on the server, probably as an entity
+   */
+  public static final String[] DEPARTMENTS = {
+      "Engineering", "Finance", "Marketing", "Operations", "Sales"};
+
+  private static final Logger log = Logger.getLogger(ExpensesShell.class.getName());
+
+  private final ActivityManager activityManager;
+  private final EventBus eventBus;
+  private final PlaceController placeController;
+  private final PlaceHistoryHandler placeHistoryHandler;
+  private final ExpensesRequestFactory requestFactory;
+  private final ExpensesShell shell;
+
+  private EntityProxyId<EmployeeProxy> lastEmployee;
+  private String lastDepartment = "";
+
+  public ExpensesApp(ActivityManager activityManager, EventBus eventBus,
+      PlaceController placeController, PlaceHistoryHandler placeHistoryHandler,
+      ExpensesRequestFactory requestFactory, ExpensesShell shell) {
+    this.activityManager = activityManager;
+    this.eventBus = eventBus;
+    this.placeController = placeController;
+    this.placeHistoryHandler = placeHistoryHandler;
+    this.requestFactory = requestFactory;
+    this.shell = shell;
+  }
+
+  /**
+   * Start the app, and add its main widget to the given panel.
+   */
+  public void run(HasWidgets root) {
+    GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
+      public void onUncaughtException(Throwable e) {
+        log.log(Level.SEVERE, e.getMessage(), e);
+      }
+    });
+
+    final ExpenseTree expenseTree = shell.getExpenseTree();
+    final ExpenseReportList expenseList = shell.getExpenseList();
+    final ExpenseReportDetails expenseDetails = shell.getExpenseDetails();
+
+    // Handle breadcrumb events from Expense Details.
+    expenseDetails.getReportsLink().addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        placeController.goTo(expenseDetails.getReportListPlace());
+      }
+    });
+
+    // Check for Authentication failures or mismatches
+    RequestEvent.register(eventBus, new AuthenticationFailureHandler());
+
+    // Kick off the login widget
+    final LoginWidget login = shell.getLoginWidget();
+    Receiver<UserInformationProxy> receiver = new Receiver<UserInformationProxy>() {
+      @Override
+      public void onSuccess(UserInformationProxy userInformationRecord) {
+        login.setUserInformation(userInformationRecord);
+      }
+    };
+    requestFactory.userInformationRequest().getCurrentUserInformation(
+        Location.getHref()).fire(receiver);
+
+    // Listen for requests from ExpenseTree.
+    expenseTree.setListener(new ExpenseTree.Listener() {
+
+      public void onSelection(String department, EntityProxyId<EmployeeProxy> employee) {
+        lastEmployee = employee;
+        lastDepartment = department;
+        placeController.goTo(new ReportListPlace(employee, department));
+      }
+    });
+
+    // Listen for requests from the ExpenseList.
+    expenseList.setListener(new ExpenseReportList.Listener() {
+      public void onReportSelected(ReportProxy report) {
+        placeController.goTo(new ReportPlace( //
+            new ReportListPlace(lastEmployee, lastDepartment), //
+            report.stableId() //
+        ));
+      }
+    });
+
+    // Give the ActivityManager a panel to run
+    activityManager.setDisplay(shell.getPanel());
+
+    // Browser history integration
+    placeHistoryHandler.register(placeController, eventBus, ReportListPlace.ALL);
+    placeHistoryHandler.handleCurrentHistory();
+
+    root.add(shell);
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java
index 24ec2f4..e7ef3f4 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java
@@ -24,8 +24,8 @@
 import com.google.gwt.requestfactory.shared.UserInformationProxy;
 import com.google.gwt.requestfactory.ui.client.AuthenticationFailureHandler;
 import com.google.gwt.requestfactory.ui.client.LoginWidget;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.Window.Location;
 import com.google.gwt.user.client.ui.Label;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java
index f436c50..f35cf1d 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java
@@ -20,10 +20,10 @@
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.shared.EventBus;
 import com.google.gwt.requestfactory.ui.client.LoginWidget;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpenseProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.uibinder.client.UiHandler;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java
index 9d80fa8..bee5035 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java
@@ -16,58 +16,48 @@
 package com.google.gwt.sample.expenses.client;
 
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.layout.client.Layout;
-import com.google.gwt.layout.client.Layout.Layer;
 import com.google.gwt.requestfactory.ui.client.LoginWidget;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DockLayoutPanel;
-import com.google.gwt.user.client.ui.LayoutPanel;
+import com.google.gwt.user.client.ui.HasOneWidget;
 import com.google.gwt.user.client.ui.Widget;
 
 /**
  * UI shell for expenses sample app.
  */
 public class ExpensesShell extends Composite {
-
   interface ShellUiBinder extends UiBinder<Widget, ExpensesShell> {
   }
 
   private static ShellUiBinder uiBinder = GWT.create(ShellUiBinder.class);
 
-  @UiField
-  ExpenseList expenseList;
-  @UiField
-  ExpenseTree expenseTree;
-  @UiField
-  LayoutPanel layoutPanel;
-  @UiField
-  LoginWidget loginWidget;
-  @UiField
-  DockLayoutPanel dockLayout;
+  @UiField(provided = true)
+  final ExpenseReportList expenseList;
+  
+  @UiField(provided = true)
+  final ExpenseReportDetails expenseDetails;
 
-  private final ExpenseDetails expenseDetails = new ExpenseDetails();
+  @UiField(provided = true)
+  final ExpenseTree expenseTree;
+  
+  @UiField SlidingPanel slidingPanel;
+  @UiField LoginWidget loginWidget;
+  @UiField DockLayoutPanel dockLayout;
 
-  public ExpensesShell() {
+  public ExpensesShell(ExpenseTree expenseTree, ExpenseReportList expenseList, ExpenseReportDetails expenseDetails) {
+    this.expenseTree = expenseTree;
+    this.expenseList = expenseList;
+    this.expenseDetails = expenseDetails;
     initWidget(uiBinder.createAndBindUi(this));
-
-    // Handle breadcrumb events from Expense Details.
-    expenseDetails.getReportsLink().addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        showExpenseDetails(false);
-      }
-    });
   }
 
-  public ExpenseDetails getExpenseDetails() {
+  public ExpenseReportDetails getExpenseDetails() {
     return expenseDetails;
   }
 
-  public ExpenseList getExpenseList() {
+  public ExpenseReportList getExpenseList() {
     return expenseList;
   }
 
@@ -75,64 +65,11 @@
     return expenseTree;
   }
 
-  /**
-   * @return the login widget
-   */
   public LoginWidget getLoginWidget() {
     return loginWidget;
   }
   
-  /**
-   * Show or hide the expense details. When showing, the expense list is hidden.
-   * 
-   * @param isShowing true to show details, false to show reports list
-   */
-  public void showExpenseDetails(boolean isShowing) {
-    if (isShowing) {
-      showWidget(expenseDetails, false);
-    } else {
-      showWidget(expenseList, true);
-    }
-  }
-
-  /**
-   * Slide a widget into view.
-   * 
-   * @param widget the widget to show
-   * @param fromLeft true to slide from left, false to slide from right
-   */
-  private void showWidget(Widget widget, boolean fromLeft) {
-    // Early out if the widget is already in the layout panel.
-    final Widget current = layoutPanel.getWidget(0);
-    if (current == widget) {
-      return;
-    }
-
-    // Initialize the layout.
-    layoutPanel.add(widget);
-    layoutPanel.setWidgetLeftWidth(current, 0, Unit.PCT, 100, Unit.PCT);
-    if (fromLeft) {
-      layoutPanel.setWidgetLeftWidth(widget, -100, Unit.PCT, 100, Unit.PCT);
-    } else {
-      layoutPanel.setWidgetLeftWidth(widget, 100, Unit.PCT, 100, Unit.PCT);
-    }
-    layoutPanel.forceLayout();
-
-    // Slide into view.
-    if (fromLeft) {
-      layoutPanel.setWidgetLeftWidth(current, 100, Unit.PCT, 100, Unit.PCT);
-    } else {
-      layoutPanel.setWidgetLeftWidth(current, -100, Unit.PCT, 100, Unit.PCT);
-    }
-    layoutPanel.setWidgetLeftWidth(widget, 0, Unit.PCT, 100, Unit.PCT);
-    layoutPanel.animate(500, new Layout.AnimationCallback() {
-      public void onAnimationComplete() {
-        // Remove the old widget when the animation completes.
-        layoutPanel.remove(current);
-      }
-
-      public void onLayout(Layer layer, double progress) {
-      }
-    });
+  public HasOneWidget getPanel() {
+    return slidingPanel;
   }
 }
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml
index 0ec4a00..a146dbd 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml
@@ -66,11 +66,11 @@
         </m:MobileScrollPanel>
       </g:west>
       <g:center>
-        <g:LayoutPanel ui:field='layoutPanel'>
-          <g:layer>
-            <e:ExpenseList ui:field='expenseList' />
-          </g:layer>
-        </g:LayoutPanel>
+        <e:SlidingPanel ui:field='slidingPanel'>
+          <!-- The order of the children determines which way they slide -->
+          <e:ExpenseReportList ui:field='expenseList' />
+          <e:ExpenseReportDetails ui:field='expenseDetails' />
+        </e:SlidingPanel>
       </g:center>
     </g:DockLayoutPanel>
   </g:center>
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseDetails.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseDetails.java
index 0ba748d..971701a 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseDetails.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseDetails.java
@@ -23,8 +23,8 @@
 import com.google.gwt.requestfactory.shared.EntityProxyChange;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
 import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ExpenseProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.client.ui.Composite;
@@ -114,17 +114,17 @@
     @SuppressWarnings("deprecation")
     DateTimeFormat formatter = DateTimeFormat.getMediumDateFormat();
 
-    Expenses.Approval approval = Expenses.Approval.from(expense.getApproval());
+    Approval approval = Approval.from(expense.getApproval());
     nameText.setInnerText(expense.getDescription());
     dateText.setInnerText(formatter.format(expense.getCreated()));
     categoryText.setInnerText(expense.getCategory());
     priceText.setInnerText(ExpensesMobile.formatCurrency(expense.getAmount()));
-    approvalText.setInnerHTML(Expenses.Approval.BLANK.equals(approval)
+    approvalText.setInnerHTML(Approval.BLANK.equals(approval)
         ? "Awaiting Review" : approval.getText());
     approvalText.getStyle().setColor(approval.getColor());
 
     reasonText.setInnerText(expense.getReasonDenied());
-    if (Expenses.Approval.DENIED.equals(approval)) {
+    if (Approval.DENIED.equals(approval)) {
       // Show the reason denied.
       reasonRow.getStyle().clearDisplay();
     } else {
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseEntry.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseEntry.java
index 5aeddba..88df8d7 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseEntry.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseEntry.java
@@ -18,10 +18,10 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
-import com.google.gwt.sample.expenses.client.request.ExpenseRequest;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
+import com.google.gwt.sample.expenses.shared.ExpenseProxy;
+import com.google.gwt.sample.expenses.shared.ExpenseRequest;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.client.ui.Composite;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseList.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseList.java
index 1b4f8f5..df44ef9 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseList.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileExpenseList.java
@@ -18,12 +18,13 @@
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.ui.client.EntityProxyKeyProvider;
 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
-import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
+import com.google.gwt.sample.expenses.shared.ExpenseProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
 import com.google.gwt.user.cellview.client.CellList;
 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
 import com.google.gwt.user.client.Timer;
@@ -65,18 +66,18 @@
   private class ExpenseCell extends AbstractCell<ExpenseProxy> {
 
     private final SafeHtml approvedHtml;
-    private final String approvedText = Expenses.Approval.APPROVED.getText();
+    private final String approvedText = Approval.APPROVED.getText();
     private final SafeHtml blankHtml;
     private final SafeHtml deniedHtml;
-    private final String deniedText = Expenses.Approval.DENIED.getText();
+    private final String deniedText = Approval.DENIED.getText();
 
     public ExpenseCell() {
       if (template == null) {
         template = GWT.create(Template.class);
       }
-      approvedHtml = Expenses.Approval.APPROVED.getIconHtml();
-      blankHtml = Expenses.Approval.BLANK.getIconHtml();
-      deniedHtml = Expenses.Approval.DENIED.getIconHtml();
+      approvedHtml = Approval.APPROVED.getIconHtml();
+      blankHtml = Approval.BLANK.getIconHtml();
+      deniedHtml = Approval.DENIED.getIconHtml();
     }
 
     @Override
@@ -135,7 +136,7 @@
       final Listener listener, final ExpensesRequestFactory requestFactory) {
     this.listener = listener;
     this.requestFactory = requestFactory;
-    expenseDataProvider = new AsyncDataProvider<ExpenseProxy>(Expenses.EXPENSE_RECORD_KEY_PROVIDER) {
+    expenseDataProvider = new AsyncDataProvider<ExpenseProxy>(new EntityProxyKeyProvider<ExpenseProxy>()) {
       @Override
       protected void onRangeChanged(HasData<ExpenseProxy> view) {
         requestExpenses();
@@ -230,7 +231,7 @@
           for (ExpenseProxy value : newValues) {
             Object key = expenseDataProvider.getKey(value);
             String approval = value.getApproval();
-            if (Expenses.Approval.DENIED.getText().equals(approval)) {
+            if (Approval.DENIED.getText().equals(approval)) {
               if (!isInitialData && !knownDeniedKeys.contains(key)) {
                 (new PhaseAnimation.CellListPhaseAnimation<ExpenseProxy>(
                     expenseList, value, expenseDataProvider)).run();
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportEntry.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportEntry.java
index 96194e5..8d541a1 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportEntry.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportEntry.java
@@ -18,10 +18,10 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
-import com.google.gwt.sample.expenses.client.request.ReportRequest;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
+import com.google.gwt.sample.expenses.shared.ReportRequest;
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.client.ui.Composite;
@@ -67,7 +67,7 @@
     this.requestFactory = requestFactory;
     initWidget(BINDER.createAndBindUi(this));
 
-    for (String department : Expenses.DEPARTMENTS) {
+    for (String department : ExpensesApp.DEPARTMENTS) {
       departmentList.addItem(department);
     }
 
@@ -144,8 +144,8 @@
     notesText.setText(report.getNotes());
     String department = report.getDepartment();
     departmentList.setSelectedIndex(0);
-    for (int i = 0; i < Expenses.DEPARTMENTS.length; i++) {
-      if (Expenses.DEPARTMENTS[i].equals(department)) {
+    for (int i = 0; i < ExpensesApp.DEPARTMENTS.length; i++) {
+      if (ExpensesApp.DEPARTMENTS[i].equals(department)) {
         departmentList.setSelectedIndex(i);
       }
     }
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportList.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportList.java
index dc50155..4ef274c 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportList.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/MobileReportList.java
@@ -17,10 +17,11 @@
 
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.ui.client.EntityProxyKeyProvider;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
-import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
-import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.client.request.ReportProxy;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
 import com.google.gwt.user.cellview.client.CellList;
 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
 import com.google.gwt.user.client.ui.Composite;
@@ -63,8 +64,10 @@
     this.listener = listener;
     this.requestFactory = requestFactory;
     this.employee = employee;
+    
+    EntityProxyKeyProvider<ReportProxy> keyProvider = new EntityProxyKeyProvider<ReportProxy>();
 
-    reportDataProvider = new AsyncDataProvider<ReportProxy>(Expenses.REPORT_RECORD_KEY_PROVIDER) {
+    reportDataProvider = new AsyncDataProvider<ReportProxy>(keyProvider) {
       @Override
       protected void onRangeChanged(HasData<ReportProxy> view) {
         requestReports();
@@ -82,7 +85,7 @@
     });
     reportList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED);
 
-    reportSelection = new NoSelectionModel<ReportProxy>(Expenses.REPORT_RECORD_KEY_PROVIDER);
+    reportSelection = new NoSelectionModel<ReportProxy>(keyProvider);
     reportSelection.addSelectionChangeHandler(
         new SelectionChangeEvent.Handler() {
           public void onSelectionChange(SelectionChangeEvent event) {
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/SlidingPanel.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/SlidingPanel.java
new file mode 100644
index 0000000..95a422c
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/SlidingPanel.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client;
+
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.layout.client.Layout;
+import com.google.gwt.layout.client.Layout.Layer;
+import com.google.gwt.user.client.ui.HasOneWidget;
+import com.google.gwt.user.client.ui.HasWidgets;
+import com.google.gwt.user.client.ui.IsWidget;
+import com.google.gwt.user.client.ui.LayoutPanel;
+import com.google.gwt.user.client.ui.ResizeComposite;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Shows one panel at a time, sliding them left or right based on the order they
+ * were added. A full fledged version might implement
+ * {@link com.google.gwt.user.client.ui.InsertPanel.ForIsWidget}.
+ * <p>
+ * Note that we implement HasWidgets so that SlidingPanel will work nicely in
+ * ui.xml files.
+ */
+public class SlidingPanel extends ResizeComposite implements HasWidgets,
+    HasOneWidget {
+
+  private final List<Widget> widgets = new ArrayList<Widget>();
+  private final LayoutPanel layoutPanel = new LayoutPanel();
+  private int currentIndex = -1;
+
+  public SlidingPanel() {
+    initWidget(layoutPanel);
+  }
+
+  public void add(IsWidget w) {
+    add(asWidgetOrNull(w.asWidget()));
+  }
+
+  public void add(Widget w) {
+    widgets.remove(w);
+    widgets.add(w);
+
+    // Display the first widget added by default
+    if (currentIndex < 0) {
+      layoutPanel.add(w);
+      currentIndex = 0;
+    }
+  }
+
+  public void clear() {
+    setWidget(null);
+    widgets.clear();
+  }
+
+  public Widget getWidget() {
+    return widgets.get(currentIndex);
+  }
+
+  public Iterator<Widget> iterator() {
+    return Collections.unmodifiableList(widgets).iterator();
+  }
+
+  public boolean remove(Widget w) {
+    return widgets.remove(w);
+  }
+
+  public void setWidget(IsWidget w) {
+    setWidget(asWidgetOrNull(w));
+  }
+
+  /**
+   * Set the widget to show, adding it to the end of our sliding set if we
+   * haven't seen it before. Nulls are ignored.
+   */
+  // Conflict btw deprecated Composite#setWidget and HasOneWidget#setWidget
+  @SuppressWarnings("deprecation")
+  public void setWidget(Widget widget) {
+    if (widget == null) {
+      return;
+    }
+    
+    int newIndex = widgets.indexOf(widget);
+
+    if (newIndex < 0) {
+      newIndex = widgets.size();
+      add(widget);
+    }
+
+    show(newIndex);
+  }
+
+  private void show(int newIndex) {
+    if (newIndex == currentIndex) {
+      return;
+    }
+
+    boolean fromLeft = newIndex < currentIndex;
+    currentIndex = newIndex;
+
+    Widget widget = widgets.get(newIndex);
+    final Widget current = layoutPanel.getWidget(0);
+
+    // Initialize the layout.
+    layoutPanel.add(widget);
+    layoutPanel.setWidgetLeftWidth(current, 0, Unit.PCT, 100, Unit.PCT);
+    if (fromLeft) {
+      layoutPanel.setWidgetLeftWidth(widget, -100, Unit.PCT, 100, Unit.PCT);
+    } else {
+      layoutPanel.setWidgetLeftWidth(widget, 100, Unit.PCT, 100, Unit.PCT);
+    }
+    layoutPanel.forceLayout();
+
+    // Slide into view.
+    if (fromLeft) {
+      layoutPanel.setWidgetLeftWidth(current, 100, Unit.PCT, 100, Unit.PCT);
+    } else {
+      layoutPanel.setWidgetLeftWidth(current, -100, Unit.PCT, 100, Unit.PCT);
+    }
+    layoutPanel.setWidgetLeftWidth(widget, 0, Unit.PCT, 100, Unit.PCT);
+    layoutPanel.animate(500, new Layout.AnimationCallback() {
+      public void onAnimationComplete() {
+        // Remove the old widget when the animation completes.
+        layoutPanel.remove(current);
+      }
+
+      public void onLayout(Layer layer, double progress) {
+      }
+    });
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ioc/ExpensesFactory.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ioc/ExpensesFactory.java
new file mode 100644
index 0000000..aa5ec92
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ioc/ExpensesFactory.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client.ioc;
+
+import com.google.gwt.activity.shared.ActivityManager;
+import com.google.gwt.activity.shared.ActivityMapper;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.event.shared.SimpleEventBus;
+import com.google.gwt.place.shared.PlaceController;
+import com.google.gwt.place.shared.PlaceHistoryHandler;
+import com.google.gwt.sample.expenses.client.ExpenseReportDetails;
+import com.google.gwt.sample.expenses.client.ExpenseReportList;
+import com.google.gwt.sample.expenses.client.ExpenseTree;
+import com.google.gwt.sample.expenses.client.ExpensesActivityMapper;
+import com.google.gwt.sample.expenses.client.ExpensesApp;
+import com.google.gwt.sample.expenses.client.ExpensesShell;
+import com.google.gwt.sample.expenses.client.place.ExpensesPlaceHistoryMapper;
+import com.google.gwt.sample.expenses.client.place.ReportListPlace;
+import com.google.gwt.sample.expenses.client.place.ReportPlace;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+
+/**
+ * In charge of instantiation.
+ * <p>
+ * TODO: Use {@link http ://code.google.com/p/google-gin/} to generate this
+ */
+public class ExpensesFactory {
+
+  private final EventBus eventBus = new SimpleEventBus();
+  private final ExpensesRequestFactory requestFactory = GWT.create(ExpensesRequestFactory.class);
+  private final ExpensesPlaceHistoryMapper historyMapper = GWT.create(ExpensesPlaceHistoryMapper.class);
+  private final PlaceHistoryHandler placeHistoryHandler;
+  private final PlaceController placeController = new PlaceController(eventBus);
+  private final ExpenseTree expenseTree = new ExpenseTree(requestFactory);
+  private final ExpenseReportList expenseList = new ExpenseReportList(requestFactory);
+  private final ExpenseReportDetails expenseDetails = new ExpenseReportDetails(
+      requestFactory);
+  private final ActivityMapper activityMapper = new ExpensesActivityMapper(
+      expenseDetails, expenseList);
+  private final ActivityManager activityManager = new ActivityManager(
+      activityMapper, eventBus);
+
+  public ExpensesFactory() {
+    requestFactory.initialize(eventBus);
+    historyMapper.setFactory(this);
+    placeHistoryHandler = new PlaceHistoryHandler(historyMapper);
+  }
+
+  public ExpensesApp getExpensesApp() {
+    return new ExpensesApp(activityManager, eventBus, placeController,
+        placeHistoryHandler, requestFactory, new ExpensesShell(expenseTree,
+            expenseList, expenseDetails));
+  }
+
+  /**
+   * Exposed for generated {@link ExpensesPlaceHistoryMapper}, which creates a
+   * bookmarkable place in the app for each type of
+   * {@link com.google.gwt.place.shared.PlaceTokenizer} it can find in the
+   * factory.
+   */
+  public ReportListPlace.Tokenizer getListTokenizer() {
+    return new ReportListPlace.Tokenizer(requestFactory);
+  }
+
+  /**
+   * Exposed for generated {@link ExpensesPlaceHistoryMapper}, which creates a
+   * bookmarkable place in the app for each type of
+   * {@link com.google.gwt.place.shared.PlaceTokenizer} it can find in the
+   * factory.
+   */
+  public ReportPlace.Tokenizer getReportTokenizer() {
+    return new ReportPlace.Tokenizer(getListTokenizer(), requestFactory);
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ioc/Factory.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ioc/Factory.java
new file mode 100644
index 0000000..f2dfc9e
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ioc/Factory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client.ioc;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.event.shared.SimpleEventBus;
+import com.google.gwt.place.shared.PlaceController;
+import com.google.gwt.place.shared.PlaceHistoryHandler;
+import com.google.gwt.sample.expenses.client.ExpenseDetails;
+import com.google.gwt.sample.expenses.client.ExpenseTree;
+import com.google.gwt.sample.expenses.client.ExpensesApp;
+import com.google.gwt.sample.expenses.client.ExpensesShell;
+import com.google.gwt.sample.expenses.client.place.ExpensesPlaceHistoryMapper;
+import com.google.gwt.sample.expenses.client.place.ReportListPlace;
+import com.google.gwt.sample.expenses.client.place.ReportPlace;
+import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
+
+/**
+ * In charge of instantiation.
+ * <p>
+ * TODO: Use {@link http ://code.google.com/p/google-gin/} to generate this
+ */
+public class Factory {
+
+  private final EventBus eventBus = new SimpleEventBus();
+  private final ExpensesRequestFactory requestFactory = GWT.create(ExpensesRequestFactory.class);
+  private final ExpensesPlaceHistoryMapper historyMapper = GWT.create(ExpensesPlaceHistoryMapper.class);
+  private final PlaceHistoryHandler placeHistoryHandler;
+  private final PlaceController placeController = new PlaceController(eventBus);
+
+  public Factory() {
+    requestFactory.initialize(eventBus);
+    historyMapper.setFactory(this);
+    placeHistoryHandler = new PlaceHistoryHandler(historyMapper);
+  }
+
+  public ExpensesApp getExpensesApp() {
+    return new ExpensesApp(requestFactory, eventBus, new ExpensesShell(
+        new ExpenseTree(requestFactory), new ExpenseDetails(requestFactory)),
+        placeHistoryHandler, placeController);
+  }
+
+  public ReportListPlace.Tokenizer getListTokenizer() {
+    return new ReportListPlace.Tokenizer(requestFactory);
+  }
+
+  public ReportPlace.Tokenizer getReportTokenizer() {
+    return new ReportPlace.Tokenizer(getListTokenizer(), requestFactory);
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyEditActivity.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyEditActivity.java
deleted file mode 100644
index a2c8ada..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyEditActivity.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.activity.shared.Activity;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.requestfactory.shared.EntityProxyId;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestContext;
-import com.google.gwt.requestfactory.shared.ServerFailure;
-import com.google.gwt.requestfactory.shared.Violation;
-import com.google.gwt.sample.expenses.client.place.ProxyPlace.Operation;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-
-import java.util.Set;
-
-/**
- * Abstract activity for editing a record. Subclasses must provide access to the
- * request that will be fired when Save is clicked.
- * <p>
- * Instances are not reusable. Once an activity is stoped, it cannot be
- * restarted.
- * 
- * @param <P> the type of Proxy being edited
- */
-public abstract class AbstractProxyEditActivity<P extends EntityProxy> implements Activity,
-    ProxyEditView.Delegate {
-
-  private final ProxyEditView<P, ?> view;
-  private final PlaceController placeController;
-
-  private RequestFactoryEditorDriver<P, ?> editorDriver;
-  private boolean waiting;
-
-  public AbstractProxyEditActivity(ProxyEditView<P, ?> view, PlaceController placeController) {
-    this.view = view;
-    this.placeController = placeController;
-  }
-
-  public void cancelClicked() {
-    String unsavedChangesWarning = mayStop();
-    if ((unsavedChangesWarning == null)
-        || Window.confirm(unsavedChangesWarning)) {
-      editorDriver = null;
-      exit(false);
-    }
-  }
-
-  public String mayStop() {
-    if (isWaiting() || changed()) {
-      return "Are you sure you want to abandon your changes?";
-    }
-
-    return null;
-  }
-
-  public void onCancel() {
-    onStop();
-  }
-
-  public void onStop() {
-    view.setDelegate(null);
-    editorDriver = null;
-  }
-
-  public void saveClicked() {
-    if (!changed()) {
-      return;
-    }
-    
-    setWaiting(true);
-    editorDriver.flush().fire(new Receiver<Void>() {
-      /*
-       * Callbacks do nothing if editorDriver is null, we were stopped in
-       * midflight
-       */
-      @Override
-      public void onFailure(ServerFailure error) {
-        if (editorDriver != null) {
-          setWaiting(false);
-          super.onFailure(error);
-        }
-      }
-
-      @Override
-      public void onSuccess(Void ignore) {
-        if (editorDriver != null) {
-          // We want no warnings from mayStop, so:
-
-          // Defeat isChanged check
-          editorDriver = null;
-
-          // Defeat call-in-flight check
-          setWaiting(false);
-
-          exit(true);
-        }
-      }
-
-      @Override
-      public void onViolation(Set<Violation> errors) {
-        if (editorDriver != null) {
-          setWaiting(false);
-          editorDriver.setViolations(errors);
-        }
-      }
-    });
-  }
-
-  public void start(AcceptsOneWidget display, EventBus eventBus) {
-    editorDriver = view.createEditorDriver();
-    view.setDelegate(this);
-    editorDriver.edit(getProxy(), createSaveRequest(getProxy()));
-    display.setWidget(view);
-  }
-
-  /**
-   * Called once to create the appropriate request to save
-   * changes.
-   * 
-   * @return the request context to fire when the save button is clicked
-   */
-  protected abstract RequestContext createSaveRequest(P proxy);
-
-  /**
-   * Called when the user cancels or has successfully saved. This default
-   * implementation tells the {@link PlaceController} to show the details of the
-   * edited record.
-   * 
-   * @param saved true if changes were comitted, false if user canceled
-   */
-  protected void exit(@SuppressWarnings("unused") boolean saved) {
-    placeController.goTo(new ProxyPlace(getProxyId(), Operation.DETAILS));
-  }
-
-  /**
-   * Get the proxy to be edited. Must be mutable, typically via a call to
-   * {@link RequestContext#edit(EntityProxy)}, or
-   * {@link RequestContext#create(Class)}.
-   */
-  protected abstract P getProxy();
-
-  @SuppressWarnings("unchecked")
-  // id type always matches proxy type
-  protected EntityProxyId<P> getProxyId() {
-    return (EntityProxyId<P>) getProxy().stableId();
-  }
-
-  private boolean changed() {
-    return editorDriver != null && editorDriver.flush().isChanged();
-  }
-
-  /**
-   * @return true if we're waiting for an rpc response.
-   */
-  private boolean isWaiting() {
-    return waiting;
-  }
-
-  /**
-   * While we are waiting for a response, we cannot poke setters on the proxy
-   * (that is, we cannot call editorDriver.flush). So we set the waiting flag to
-   * warn ourselves not to, and to disable the view.
-   */
-  private void setWaiting(boolean wait) {
-    this.waiting = wait;
-    view.setEnabled(!wait);
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListActivity.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListActivity.java
deleted file mode 100644
index 5058fa1..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListActivity.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.activity.shared.Activity;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.place.shared.Place;
-import com.google.gwt.place.shared.PlaceChangeEvent;
-import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.requestfactory.shared.EntityProxyChange;
-import com.google.gwt.requestfactory.shared.EntityProxyId;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.Request;
-import com.google.gwt.requestfactory.shared.WriteOperation;
-import com.google.gwt.sample.expenses.client.place.ProxyPlace.Operation;
-import com.google.gwt.user.cellview.client.AbstractHasData;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-import com.google.gwt.view.client.HasData;
-import com.google.gwt.view.client.ProvidesKey;
-import com.google.gwt.view.client.Range;
-import com.google.gwt.view.client.RangeChangeEvent;
-import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SingleSelectionModel;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Abstract activity for displaying a list of {@link EntityProxy}. These
- * activities are not re-usable. Once they are stopped, they cannot be
- * restarted.
- * <p>
- * Subclasses must:
- * 
- * <ul>
- * <li>provide a {@link ProxyListView}
- * <li>implement method to request a full count
- * <li>implement method to find a range of entities
- * <li>respond to "show details" commands
- * </ul>
- * <p>
- * Only the properties required by the view will be requested.
- * 
- * @param <P> the type of {@link EntityProxy} listed
- */
-public abstract class AbstractProxyListActivity<P extends EntityProxy>
-    implements Activity, ProxyListView.Delegate<P> {
-
-  /**
-   * This mapping allows us to update individual rows as records change.
-   */
-  private final Map<EntityProxyId<P>, Integer> idToRow = new HashMap<EntityProxyId<P>, Integer>();
-  private final Map<EntityProxyId<P>, P> idToProxy = new HashMap<EntityProxyId<P>, P>();
-
-  private final PlaceController placeController;
-  private final SingleSelectionModel<P> selectionModel;
-  private final Class<P> proxyClass;
-
-  private HandlerRegistration rangeChangeHandler;
-  private ProxyListView<P> view;
-  private AcceptsOneWidget display;
-
-  public AbstractProxyListActivity(PlaceController placeController,
-      ProxyListView<P> view, Class<P> proxyType) {
-    this.view = view;
-    this.placeController = placeController;
-    this.proxyClass = proxyType;
-    view.setDelegate(this);
-
-    final HasData<P> hasData = view.asHasData();
-    rangeChangeHandler = hasData.addRangeChangeHandler(new RangeChangeEvent.Handler() {
-      public void onRangeChange(RangeChangeEvent event) {
-        AbstractProxyListActivity.this.onRangeChanged(hasData);
-      }
-    });
-
-    // Inherit the view's key provider
-    ProvidesKey<P> keyProvider = ((AbstractHasData<P>) hasData).getKeyProvider();
-    selectionModel = new SingleSelectionModel<P>(keyProvider);
-    hasData.setSelectionModel(selectionModel);
-
-    selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
-      public void onSelectionChange(SelectionChangeEvent event) {
-        P selectedObject = selectionModel.getSelectedObject();
-        if (selectedObject != null) {
-          showDetails(selectedObject);
-        }
-      }
-    });
-  }
-
-  public void createClicked() {
-    placeController.goTo(new ProxyPlace(proxyClass));
-  }
-
-  public ProxyListView<P> getView() {
-    return view;
-  }
-
-  public String mayStop() {
-    return null;
-  }
-
-  public void onCancel() {
-    onStop();
-  }
-
-  /**
-   * Called by the table as it needs data.
-   */
-  public void onRangeChanged(HasData<P> listView) {
-    final Range range = listView.getVisibleRange();
-
-    final Receiver<List<P>> callback = new Receiver<List<P>>() {
-      @Override
-      public void onSuccess(List<P> values) {
-        if (view == null) {
-          // This activity is dead
-          return;
-        }
-        idToRow.clear();
-        idToProxy.clear();
-        for (int i = 0, row = range.getStart(); i < values.size(); i++, row++) {
-          P proxy = values.get(i);
-          @SuppressWarnings("unchecked")
-          // Why is this cast needed?
-          EntityProxyId<P> proxyId = (EntityProxyId<P>) proxy.stableId();
-          idToRow.put(proxyId, row);
-          idToProxy.put(proxyId, proxy);
-        }
-        getView().asHasData().setRowData(range.getStart(), values);
-        if (display != null) {
-          display.setWidget(getView());
-        }
-      }
-    };
-
-    fireRangeRequest(range, callback);
-  }
-
-  public void onStop() {
-    view.setDelegate(null);
-    view = null;
-    rangeChangeHandler.removeHandler();
-    rangeChangeHandler = null;
-  }
-
-  /**
-   * Select the given record, or clear the selection if called with null or an
-   * id we don't know.
-   */
-  public void select(EntityProxyId<P> proxyId) {
-    /*
-     * The selectionModel will not flash if we put it back to the same state it
-     * is already in, so we can keep this code simple.
-     */
-
-    // Clear the selection
-    P selected = selectionModel.getSelectedObject();
-    if (selected != null) {
-      selectionModel.setSelected(selected, false);
-    }
-
-    // Select the new proxy, if it's relevant
-    if (proxyId != null) {
-      P selectMe = idToProxy.get(proxyId);
-      selectionModel.setSelected(selectMe, true);
-    }
-  }
-
-  public void start(AcceptsOneWidget display, EventBus eventBus) {
-    view.setDelegate(this);
-    EntityProxyChange.registerForProxyType(eventBus, proxyClass,
-        new EntityProxyChange.Handler<P>() {
-          public void onProxyChange(EntityProxyChange<P> event) {
-            update(event.getWriteOperation(), event.getProxyId());
-          }
-        });
-    eventBus.addHandler(PlaceChangeEvent.TYPE, new PlaceChangeEvent.Handler() {
-      public void onPlaceChange(PlaceChangeEvent event) {
-        updateSelection(event.getNewPlace());
-      }
-    });
-    this.display = display;
-    init();
-    updateSelection(placeController.getWhere());
-  }
-
-  public void update(WriteOperation writeOperation, EntityProxyId<P> proxyId) {
-    switch (writeOperation) {
-      case UPDATE:
-        update(proxyId);
-        break;
-
-      case DELETE:
-        init();
-        break;
-
-      case PERSIST:
-        /*
-         * On create, we presume the new record is at the end of the list, so
-         * fetch the last page of items.
-         */
-        getLastPage();
-        break;
-    }
-  }
-
-  protected abstract Request<List<P>> createRangeRequest(Range range);
-
-  protected abstract void fireCountRequest(Receiver<Long> callback);
-
-  /**
-   * Called when the user chooses a record to view. This default implementation
-   * sends the {@link PlaceController} to an appropriate {@link ProxyPlace}.
-   * 
-   * @param record the chosen record
-   */
-  protected void showDetails(P record) {
-    placeController.goTo(new ProxyPlace(record.stableId(), Operation.DETAILS));
-  }
-
-  @SuppressWarnings("unchecked")
-  private EntityProxyId<P> cast(ProxyPlace proxyPlace) {
-    return (EntityProxyId<P>) proxyPlace.getProxyId();
-  }
-
-  private void fireRangeRequest(final Range range,
-      final Receiver<List<P>> callback) {
-    createRangeRequest(range).with(getView().getPaths()).fire(callback);
-  }
-
-  private void getLastPage() {
-    fireCountRequest(new Receiver<Long>() {
-      @Override
-      public void onSuccess(Long response) {
-        if (view == null) {
-          // This activity is dead
-          return;
-        }
-        HasData<P> table = getView().asHasData();
-        int rows = response.intValue();
-        table.setRowCount(rows, true);
-        if (rows > 0) {
-          int pageSize = table.getVisibleRange().getLength();
-          int remnant = rows % pageSize;
-          if (remnant == 0) {
-            table.setVisibleRange(rows - pageSize, pageSize);
-          } else {
-            table.setVisibleRange(rows - remnant, pageSize);
-          }
-        }
-        onRangeChanged(table);
-      }
-    });
-  }
-
-  private void init() {
-    fireCountRequest(new Receiver<Long>() {
-      @Override
-      public void onSuccess(Long response) {
-        if (view == null) {
-          // This activity is dead
-          return;
-        }
-        getView().asHasData().setRowCount(response.intValue(), true);
-        onRangeChanged(view.asHasData());
-      }
-    });
-  }
-
-  private void update(EntityProxyId<P> proxyId) {
-    final Integer row = idToRow.get(proxyId);
-    if (row == null) {
-      return;
-    }
-    fireRangeRequest(new Range(row, 1), new Receiver<List<P>>() {
-      @Override
-      public void onSuccess(List<P> response) {
-        getView().asHasData().setRowData(row,
-            Collections.singletonList(response.get(0)));
-      }
-    });
-  }
-
-  private void updateSelection(Place newPlace) {
-    if (newPlace instanceof ProxyPlace) {
-      ProxyPlace proxyPlace = (ProxyPlace) newPlace;
-      if (proxyPlace.getOperation() != Operation.CREATE
-          && proxyPlace.getProxyClass().equals(proxyClass)) {
-        select(cast(proxyPlace));
-        return;
-      }
-    }
-
-    select(null);
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListView.java
deleted file mode 100644
index c05fdd8..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListView.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.view.client.HasData;
-
-/**
- * Abstract implementation of ProxyListView.
- *
- * @param <P> the type of the proxy
- */
-public abstract class AbstractProxyListView<P extends EntityProxy> extends
-    Composite implements ProxyListView<P> {
-
-  private HasData<P> display;
-  private Delegate<P> delegate;
-
-  public HasData<P> asHasData() {
-    return display;
-  }
-
-  @Override
-  public AbstractProxyListView<P> asWidget() {
-    return this;
-  }
-
-  public void setDelegate(final Delegate<P> delegate) {
-    this.delegate = delegate;
-  }
-
-  protected void init(Widget root, HasData<P> display, Button newButton) {
-    super.initWidget(root);
-    this.display = display;
-
-    newButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        delegate.createClicked();
-      }
-    });
-  }
-
-  @Override
-  protected void initWidget(Widget widget) {
-    throw new UnsupportedOperationException(
-        "AbstractRecordListView must be initialized via "
-            + "init(Widget, HasData<P>, Button) ");
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/CreateAndEditProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/CreateAndEditProxy.java
deleted file mode 100644
index e8fed9b..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/CreateAndEditProxy.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.requestfactory.shared.RequestContext;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-
-/**
- * Extends {@link AbstractProxyEditActivity} to first create an instance to
- * edit.
- * 
- * @param <P> the type of proxy to create and edit
- */
-public abstract class CreateAndEditProxy<P extends EntityProxy> extends AbstractProxyEditActivity<P> {
-
-  private final P proxy;
-  private final PlaceController placeController;
-  private Class<P> proxyClass;
-
-  public CreateAndEditProxy(Class<P> proxyClass, RequestContext request,
-      ProxyEditView<P, ?> view, PlaceController placeController) {
-    super(view, placeController);
-    this.proxy = request.create(proxyClass);
-    this.placeController = placeController;
-    this.proxyClass = proxyClass;
-  }
-
-  @Override
-  public void start(AcceptsOneWidget display, EventBus eventBus) {
-    super.start(display, eventBus);
-  }
-
-  /**
-   * Called when the user cancels or has successfully saved. Refines the default
-   * implementation to clear the display given at {@link #start} on cancel.
-   * 
-   * @param saved true if changes were comitted, false if user canceled
-   */
-  @Override
-  protected void exit(boolean saved) {
-    if (!saved) {
-      placeController.goTo(new ProxyListPlace(proxyClass));
-    } else {
-      super.exit(saved);
-    }
-  }
-
-  @Override
-  protected P getProxy() {
-    return proxy;
-  }  
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ExpensesPlaceHistoryMapper.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ExpensesPlaceHistoryMapper.java
new file mode 100644
index 0000000..eae962a
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ExpensesPlaceHistoryMapper.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client.place;
+
+import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;
+import com.google.gwt.sample.expenses.client.ioc.ExpensesFactory;
+
+/**
+ * This interface is the hub of your application's navigation system. It links
+ * the {@link com.google.gwt.place.shared.Place Place}s your user navigates to
+ * with the browser history system &mdash; that is, it makes the browser's back
+ * and forth buttons work for you, and also makes each spot in your app
+ * bookmarkable.
+ * 
+ * <p>
+ * The simplest way to make new {@link com.google.gwt.place.shared.Place Place}
+ * types available to your app is to uncomment the {@literal @}WithTokenizers
+ * annotation below and list their corresponding
+ * {@link com.google.gwt.place.shared.PlaceTokenizer PlaceTokenizer}s. Or if a
+ * tokenizer needs more than a default constructor can provide, add a method to
+ * the apps {@link ExpensesFactory}.
+ * 
+ * <p>
+ * This code generated object looks to both the {@literal @}WithTokenizers
+ * annotation and the factory to infer the types of
+ * {@link com.google.gwt.place.Place Place}s your app can navigate to. In this
+ * case it will find the {@link ExpensesFactory#getListTokenizer()} and
+ * {@link ExpensesFactory#getReportTokenizer()} methods, and so be able to handle
+ * {@link ReportListPlace}s and {@link ReportPlace}s.
+ */
+// @WithTokenizers({MyNewPlace.Tokenizer, MyOtherNewPlace.Tokenizer})
+public interface ExpensesPlaceHistoryMapper extends
+    PlaceHistoryMapperWithFactory<ExpensesFactory> {
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/FindAndEditProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/FindAndEditProxy.java
deleted file mode 100644
index a86ba0c..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/FindAndEditProxy.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.requestfactory.shared.EntityProxyId;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestFactory;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-
-/**
- * Extends {@link AbstractProxyEditActivity} to work from a
- * {@link EntityProxyId}.
- * 
- * @param <P> the type of proxy to find and edit
- */
-public abstract class FindAndEditProxy<P extends EntityProxy> extends
-    AbstractProxyEditActivity<P> {
-
-  private final RequestFactory factory;
-  private final EntityProxyId<P> proxyId;
-  private P proxy;
-
-  public FindAndEditProxy(EntityProxyId<P> proxyId, RequestFactory factory,
-      ProxyEditView<P, ?> view, PlaceController placeController) {
-    super(view, placeController);
-    this.proxyId = proxyId;
-    this.factory = factory;
-  }
-
-  @Override
-  public void start(final AcceptsOneWidget display, final EventBus eventBus) {
-    factory.find(proxyId).fire(new Receiver<P>() {
-      @Override
-      public void onSuccess(P response) {
-        proxy = response;
-        FindAndEditProxy.super.start(display, eventBus);
-      }
-    });
-  }
-
-  @Override
-  protected P getProxy() {
-    return proxy;
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyDetailsView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyDetailsView.java
deleted file mode 100644
index 2b660d4..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyDetailsView.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.user.client.TakesValue;
-import com.google.gwt.user.client.ui.IsWidget;
-
-/**
- * Implemented by views that show the details of an object.
- *
- * @param <P> the type of object to show
- */
-public interface ProxyDetailsView<P> extends TakesValue<P>, IsWidget {
-
-  /**
-   * Implemented by the owner of the view.
-   */
-  interface Delegate {
-    void deleteClicked();
-    void editClicked();
-  }
-  
-  boolean confirm(String msg);
-  
-  void setDelegate(Delegate delegate);
-}
\ No newline at end of file
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyEditView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyEditView.java
deleted file mode 100644
index 70e9c6d..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyEditView.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.editor.client.HasEditorErrors;
-import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.user.client.ui.IsWidget;
-
-/**
- * Implemented by views that edit {@link EntityProxy}s.
- * 
- * @param <P> the type of the proxy
- * @param <V> the type of this ProxyEditView, required to allow
- *          {@link #createEditorDriver()} to be correctly typed
- */
-public interface ProxyEditView<P extends EntityProxy, V extends ProxyEditView<P, V>>
-    extends IsWidget, HasEditorErrors<P> {
-
-  /**
-   * @return a new {@link RequestFactoryEditorDriver} initialized to run this
-   *         editor
-   */
-  RequestFactoryEditorDriver<P, V> createEditorDriver();
-
-  /**
-   * Implemented by the owner of the view.
-   */
-  interface Delegate {
-    void cancelClicked();
-
-    void saveClicked();
-  }
-
-  void setDelegate(Delegate delegate);
-
-  void setEnabled(boolean b);
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlace.java
deleted file mode 100644
index 8167386..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlace.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.place.shared.Place;
-import com.google.gwt.place.shared.PlaceTokenizer;
-import com.google.gwt.place.shared.Prefix;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.requestfactory.shared.RequestFactory;
-
-/**
- * A place in the app that deals with lists of {@link EntityProxy}.
- */
-public class ProxyListPlace extends Place {
-
-  /**
-   * Tokenizer.
-   */
-  @Prefix("l")
-  public static class Tokenizer implements PlaceTokenizer<ProxyListPlace> {
-    private final RequestFactory requests;
-
-    public Tokenizer(RequestFactory requests) {
-      this.requests = requests;
-    }
-
-    public ProxyListPlace getPlace(String token) {
-      return new ProxyListPlace(requests.getProxyClass(token));
-    }
-
-    public String getToken(ProxyListPlace place) {
-      return requests.getHistoryToken(place.getProxyClass());
-    }
-  }
-
-  private final Class<? extends EntityProxy> proxyType;
-
-  public ProxyListPlace(Class<? extends EntityProxy> proxyType) {
-    this.proxyType = proxyType;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj) {
-      return true;
-    }
-    if (obj == null) {
-      return false;
-    }
-    if (getClass() != obj.getClass()) {
-      return false;
-    }
-    ProxyListPlace other = (ProxyListPlace) obj;
-    if (!proxyType.equals(other.proxyType)) {
-      return false;
-    }
-    return true;
-  }
-
-  public Class<? extends EntityProxy> getProxyClass() {
-    return proxyType;
-  }
-
-  @Override
-  public int hashCode() {
-    final int prime = 31;
-    int result = 1;
-    result = prime * result + proxyType.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "ProxyListPlace [proxyType=" + proxyType + "]";
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlacePicker.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlacePicker.java
deleted file mode 100644
index 0f1d3c6..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlacePicker.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.place.shared.PlaceChangeEvent;
-import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.user.client.ui.HasConstrainedValue;
-
-/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
- * Drives a {@link ValueChangeHandler} populated with {@link ProxyListPlace}
- * instances, keeping it in sync with the {@link PlaceController}'s notion of
- * the current place, and firing place change events as selections are made.
- */
-public class ProxyListPlacePicker implements ValueChangeHandler<ProxyListPlace>,
-    PlaceChangeEvent.Handler {
-
-  private HasConstrainedValue<ProxyListPlace> view;
-
-  private final PlaceController placeController;
-  private final ProxyPlaceToListPlace proxyPlaceToListPlace;
-
-  public ProxyListPlacePicker(PlaceController placeController,
-      ProxyPlaceToListPlace proxyPlaceToListPlace) {
-    this.placeController = placeController;
-    this.proxyPlaceToListPlace = proxyPlaceToListPlace;
-  }
-
-  public void onPlaceChange(PlaceChangeEvent event) {
-    view.setValue(proxyPlaceToListPlace.proxyListPlaceFor(event.getNewPlace()),
-        false);
-  }
-
-  public void onValueChange(ValueChangeEvent<ProxyListPlace> event) {
-    placeController.goTo(event.getValue());
-  }
-
-  public HandlerRegistration register(EventBus eventBus,
-      HasConstrainedValue<ProxyListPlace> view) {
-
-    this.view = view;
-
-    final HandlerRegistration placeRegistration = eventBus.addHandler(
-        PlaceChangeEvent.TYPE, this);
-
-    final HandlerRegistration viewRegistration = view.addValueChangeHandler(this);
-
-    return new HandlerRegistration() {
-      public void removeHandler() {
-        placeRegistration.removeHandler();
-        viewRegistration.removeHandler();
-        ProxyListPlacePicker.this.view = null;
-      }
-    };
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListView.java
deleted file mode 100644
index 6156ff3..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListView.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.user.client.ui.IsWidget;
-import com.google.gwt.view.client.HasData;
-
-/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
- * A view of a list of {@link EntityProxy}s, which declares which properties it
- * is able to display.
- * <p>
- * It is expected that such views will typically (eventually) be defined largely
- * in ui.xml files which declare the properties of interest, which is why the
- * view is a source of a property set rather than a receiver of one.
- * 
- * @param <P> the type of the records to display
- */
-public interface ProxyListView<P extends EntityProxy> extends IsWidget {
-  /**
-   * Implemented by the owner of a RecordTableView.
-   * 
-   * @param <R> the type of the records to display
-   */
-  interface Delegate<R extends EntityProxy> {
-    void createClicked();
-  }
-
-  HasData<P> asHasData();
-
-  /**
-   * @return the set of properties this view displays
-   */
-  String[] getPaths();
-
-  /**
-   * Sets the delegate.
-   */
-  void setDelegate(Delegate<P> delegate);
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlace.java
deleted file mode 100644
index fdb0af8..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlace.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.place.shared.Place;
-import com.google.gwt.place.shared.PlaceTokenizer;
-import com.google.gwt.place.shared.Prefix;
-import com.google.gwt.requestfactory.shared.EntityProxy;
-import com.google.gwt.requestfactory.shared.EntityProxyId;
-import com.google.gwt.requestfactory.shared.RequestFactory;
-
-/**
- * A place in the app that deals with a specific {@link RequestFactory} proxy.
- */
-public class ProxyPlace extends Place {
-  /**
-   * The things you do with a record, each of which is a different bookmarkable
-   * location in the scaffold app.
-   */
-  public enum Operation {
-    CREATE, EDIT, DETAILS
-  }
-
-  /**
-   * Tokenizer.
-   */
-  @Prefix("r")
-  public static class Tokenizer implements PlaceTokenizer<ProxyPlace> {
-    /**
-     * 
-     */
-    private static final String SEPARATOR = "!";
-    private final RequestFactory requests;
-
-    public Tokenizer(RequestFactory requests) {
-      this.requests = requests;
-    }
-
-    public ProxyPlace getPlace(String token) {
-      String bits[] = token.split(SEPARATOR);
-      Operation operation = Operation.valueOf(bits[1]);
-      if (Operation.CREATE == operation) {
-        return new ProxyPlace(requests.getProxyClass(bits[0]));
-      }
-      return new ProxyPlace(requests.getProxyId(bits[0]), operation);
-    }
-
-    public String getToken(ProxyPlace place) {
-      if (Operation.CREATE == place.getOperation()) {
-        return requests.getHistoryToken(place.getProxyClass()) + SEPARATOR
-            + place.getOperation();
-      }
-      return requests.getHistoryToken(place.getProxyId()) + SEPARATOR
-          + place.getOperation();
-    }
-  }
-
-  private final EntityProxyId<?> proxyId;
-  private final Class<? extends EntityProxy> proxyClass;
-  private final Operation operation;
-
-  public ProxyPlace(Class<? extends EntityProxy> proxyClass) {
-    this.operation = Operation.CREATE;
-    this.proxyId = null;
-    this.proxyClass = proxyClass;
-  }
-
-  public ProxyPlace(EntityProxyId<?> record) {
-    this(record, Operation.DETAILS);
-  }
-
-  public ProxyPlace(EntityProxyId<?> proxyId, Operation operation) {
-    this.operation = operation;
-    this.proxyId = proxyId;
-    this.proxyClass = null;
-    assert Operation.CREATE != operation;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj) {
-      return true;
-    }
-    if (obj == null) {
-      return false;
-    }
-    if (getClass() != obj.getClass()) {
-      return false;
-    }
-    ProxyPlace other = (ProxyPlace) obj;
-    if (operation != other.operation) {
-      return false;
-    }
-    if (proxyClass == null) {
-      if (other.proxyClass != null) {
-        return false;
-      }
-    } else if (!proxyClass.equals(other.proxyClass)) {
-      return false;
-    }
-    if (proxyId == null) {
-      if (other.proxyId != null) {
-        return false;
-      }
-    } else if (!proxyId.equals(other.proxyId)) {
-      return false;
-    }
-    return true;
-  }
-
-  public Operation getOperation() {
-    return operation;
-  }
-
-  public Class<? extends EntityProxy> getProxyClass() {
-    return proxyId != null ? proxyId.getProxyClass() : proxyClass;
-  }
-
-  /**
-   * @return the proxyId, or null if the operation is {@link Operation#CREATE}
-   */
-  public EntityProxyId<?> getProxyId() {
-    return proxyId;
-  }
-
-  @Override
-  public int hashCode() {
-    final int prime = 31;
-    int result = 1;
-    result = prime * result + ((operation == null) ? 0 : operation.hashCode());
-    result = prime * result
-        + ((proxyClass == null) ? 0 : proxyClass.hashCode());
-    result = prime * result + ((proxyId == null) ? 0 : proxyId.hashCode());
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "ProxyPlace [operation=" + operation + ", proxy=" + proxyId
-        + ", proxyClass=" + proxyClass + "]";
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlaceToListPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlaceToListPlace.java
deleted file mode 100644
index 7b15f3c..0000000
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlaceToListPlace.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.expenses.client.place;
-
-import com.google.gwt.activity.shared.FilteredActivityMapper;
-import com.google.gwt.place.shared.Place;
-
-/**
- * Converts a {@link ProxyPlace} to a {@link ProxyListPlace}.
- */
-public class ProxyPlaceToListPlace implements FilteredActivityMapper.Filter {
-
-  /**
-   * Required by {@link com.google.gwt.app.place.FilteredActivityMapper.Filter}, calls
-   * {@link #proxyListPlaceFor}.
-   */
-  public Place filter(Place place) {
-    return proxyListPlaceFor(place);
-  }
-
-  /**
-   * @param place a place to process
-   * @return an appropriate ProxyListPlace, or null if the given place has
-   *         nothing to do with proxies
-   */
-  public ProxyListPlace proxyListPlaceFor(Place place) {
-    if (place instanceof ProxyListPlace) {
-      return (ProxyListPlace) place;
-    }
-
-    if (!(place instanceof ProxyPlace)) {
-      return null;
-    }
-
-    ProxyPlace proxyPlace = (ProxyPlace) place;
-    return new ProxyListPlace(proxyPlace.getProxyClass());
-  }
-}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ReportListPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ReportListPlace.java
new file mode 100644
index 0000000..b260de2
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ReportListPlace.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client.place;
+
+import com.google.gwt.http.client.URL;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.RequestFactory;
+import com.google.gwt.sample.expenses.shared.EmployeeProxy;
+
+/**
+ * A place in the app that shows a list of reports.
+ */
+public class ReportListPlace extends Place {
+
+  /**
+   * Tokenizer, which by all rights should have been code generated. Stay tuned.
+   */
+  @Prefix("l")
+  public static class Tokenizer implements PlaceTokenizer<ReportListPlace> {
+    static final String SEPARATOR = "!";
+    private static final String NO_ID = "n";
+
+    private final RequestFactory requests;
+
+    public Tokenizer(RequestFactory requests) {
+      this.requests = requests;
+    }
+
+    public ReportListPlace getPlace(String token) {
+      String bits[] = token.split(SEPARATOR);
+
+      if (bits.length != 2) {
+        return null;
+      }
+
+      String department = URL.decodePathSegment(bits[0]);
+      String reporterIdToken = bits[1];
+
+      EntityProxyId<EmployeeProxy> proxyId = NO_ID.equals(reporterIdToken)
+          ? null : requests.<EmployeeProxy> getProxyId(reporterIdToken);
+      return new ReportListPlace(proxyId, department);
+    }
+
+    public String getToken(ReportListPlace place) {
+      EntityProxyId<EmployeeProxy> id = place.getEmployeeId();
+      String idToken = id == null ? NO_ID : requests.getHistoryToken(id);
+      return URL.encodePathSegment(place.getDepartment()) + SEPARATOR + idToken;
+    }
+  }
+
+  public static final ReportListPlace ALL = new ReportListPlace(null, "");
+
+  private final EntityProxyId<EmployeeProxy> employeeId;
+  private final String department;
+
+  public ReportListPlace(EntityProxyId<EmployeeProxy> employeeId,
+      String department) {
+    this.employeeId = employeeId;
+    this.department = department;
+  }
+
+  /**
+   * @return the department searched for, or null for none
+   */
+  public String getDepartment() {
+    return department;
+  }
+
+  /**
+   * @return the employee to focus on, or null for none
+   */
+  public EntityProxyId<EmployeeProxy> getEmployeeId() {
+    return employeeId;
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ReportPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ReportPlace.java
new file mode 100644
index 0000000..243d7f2
--- /dev/null
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ReportPlace.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.expenses.client.place;
+
+import static com.google.gwt.sample.expenses.client.place.ReportListPlace.Tokenizer.SEPARATOR;
+
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.RequestFactory;
+import com.google.gwt.sample.expenses.shared.ReportProxy;
+
+/**
+ * A place in the app that shows a list of reports.
+ */
+public class ReportPlace extends Place {
+
+  /**
+   * Tokenizer.
+   */
+  @Prefix("r")
+  public static class Tokenizer implements PlaceTokenizer<ReportPlace> {
+    private final RequestFactory requests;
+    private final ReportListPlace.Tokenizer listTokenizer;
+
+    public Tokenizer(ReportListPlace.Tokenizer listTokenizer,
+        RequestFactory requests) {
+      this.requests = requests;
+      this.listTokenizer = listTokenizer;
+    }
+
+    public ReportPlace getPlace(String token) {
+      int i = token.indexOf(SEPARATOR);
+      if (i < 0) {
+        return null;
+      }
+
+      String reporterToken = token.substring(0, i);
+      String listPlaceToken = token.substring(i + SEPARATOR.length());
+
+      return new ReportPlace(listTokenizer.getPlace(listPlaceToken),
+          requests.<ReportProxy> getProxyId(reporterToken));
+    }
+
+    public String getToken(ReportPlace place) {
+      return requests.getHistoryToken(place.getReportId()) + SEPARATOR
+          + listTokenizer.getToken(place.getListPlace());
+    }
+  }
+
+  private final ReportListPlace listPlace;
+  private final EntityProxyId<ReportProxy> reportId;
+
+  public ReportPlace(ReportListPlace listPlace,
+      EntityProxyId<ReportProxy> reportId) {
+    this.listPlace = listPlace;
+    this.reportId = reportId;
+  }
+
+  public ReportListPlace getListPlace() {
+    return listPlace;
+  }
+
+  public EntityProxyId<ReportProxy> getReportId() {
+    return reportId;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((listPlace == null) ? 0 : listPlace.hashCode());
+    result = prime * result + ((reportId == null) ? 0 : reportId.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    ReportPlace other = (ReportPlace) obj;
+    if (listPlace == null) {
+      if (other.listPlace != null)
+        return false;
+    } else if (!listPlace.equals(other.listPlace))
+      return false;
+    if (reportId == null) {
+      if (other.reportId != null)
+        return false;
+    } else if (!reportId.equals(other.reportId))
+      return false;
+    return true;
+  }
+}
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/EmployeeProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/EmployeeProxy.java
similarity index 96%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/EmployeeProxy.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/EmployeeProxy.java
index 8cb3a09..fffc9f1 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/EmployeeProxy.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/EmployeeProxy.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.EntityProxy;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/EmployeeRequest.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/EmployeeRequest.java
similarity index 97%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/EmployeeRequest.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/EmployeeRequest.java
index 8fe44d8..0391a48 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/EmployeeRequest.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/EmployeeRequest.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.InstanceRequest;
 import com.google.gwt.requestfactory.shared.Request;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpenseProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpenseProxy.java
similarity index 96%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpenseProxy.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpenseProxy.java
index cd72cf3..eabf78e 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpenseProxy.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpenseProxy.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.EntityProxy;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpenseRequest.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpenseRequest.java
similarity index 96%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpenseRequest.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpenseRequest.java
index e7b1b8d..38a279c 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpenseRequest.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpenseRequest.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.InstanceRequest;
 import com.google.gwt.requestfactory.shared.Request;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpensesEntityTypesProcessor.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpensesEntityTypesProcessor.java
similarity index 98%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpensesEntityTypesProcessor.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpensesEntityTypesProcessor.java
index 081bb60..23b7003 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpensesEntityTypesProcessor.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpensesEntityTypesProcessor.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.EntityProxy;
 
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpensesRequestFactory.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpensesRequestFactory.java
similarity index 96%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpensesRequestFactory.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpensesRequestFactory.java
index d31bb6c..201abcb 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ExpensesRequestFactory.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ExpensesRequestFactory.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.RequestFactory;
 import com.google.gwt.requestfactory.shared.UserInformationRequest;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ReportProxy.java
similarity index 96%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportProxy.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ReportProxy.java
index e048609..0bf0c48 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportProxy.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ReportProxy.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.EntityProxy;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ReportRequest.java
similarity index 97%
rename from samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ReportRequest.java
index 160f277..40af51e 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/shared/ReportRequest.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.sample.expenses.client.request;
+package com.google.gwt.sample.expenses.shared;
 
 import com.google.gwt.requestfactory.shared.InstanceRequest;
 import com.google.gwt.requestfactory.shared.Request;
diff --git a/user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java b/user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java
index 274fd55..51aa52f 100644
--- a/user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java
+++ b/user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java
@@ -25,7 +25,8 @@
 import java.util.logging.Logger;
 
 /**
- * Monitors {@link PlaceChangeEvent}s and {@link com.google.gwt.user.client.History} events and keep them in sync.
+ * Monitors {@link PlaceChangeEvent}s and
+ * {@link com.google.gwt.user.client.History} events and keep them in sync.
  */
 public class PlaceHistoryHandler {
   private static final Logger log = Logger.getLogger(PlaceHistoryHandler.class.getName());
@@ -51,13 +52,29 @@
   /**
    * Optional delegate in charge of History related events. Provides nice
    * isolation for unit testing, and allows pre- or post-processing of tokens.
+   * Methods correspond to the like named methods on {@link History}.
    */
   public interface Historian {
+    /**
+     * Adds a {@link com.google.gwt.event.logical.shared.ValueChangeEvent}
+     * handler to be informed of changes to the browser's history stack.
+     * 
+     * @param handler the handler
+     * @return the registration used to remove this value change handler
+     */
     HandlerRegistration addValueChangeHandler(
         ValueChangeHandler<String> valueChangeHandler);
 
+    /**
+     * @return the current history token.
+     */
     String getToken();
 
+    /**
+     * Adds a new browser history entry. Calling this method will cause
+     * {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+     * to be called as well.
+     */
     void newItem(String token, boolean issueEvent);
   }
 
@@ -70,10 +87,12 @@
   private Place defaultPlace = Place.NOWHERE;
 
   /**
-   * Create a new PlaceHistoryHandler with a {@link DefaultHistorian}.
-   * The DefaultHistorian is created via a call to GWT.create(), so an
-   * alternative default implementation can be provided through
-   * &lt;replace-with> rules in a gwt.xml file.
+   * Create a new PlaceHistoryHandler with a {@link DefaultHistorian}. The
+   * DefaultHistorian is created via a call to GWT.create(), so an alternative
+   * default implementation can be provided through &lt;replace-with&gt; rules
+   * in a {@code gwt.xml} file.
+   * 
+   * @param mapper a {@link PlaceHistoryMapper} instance
    */
   public PlaceHistoryHandler(PlaceHistoryMapper mapper) {
     this(mapper, (Historian) GWT.create(DefaultHistorian.class));
@@ -81,16 +100,28 @@
 
   /**
    * Create a new PlaceHistoryHandler.
+   * 
+   * @param mapper a {@link PlaceHistoryMapper} instance
+   * @param historian a {@link Historian} instance
    */
   public PlaceHistoryHandler(PlaceHistoryMapper mapper, Historian historian) {
     this.mapper = mapper;
     this.historian = historian;
   }
 
+  /**
+   * Handle the current history token. Typically called at application start, to
+   * ensure bookmark launches work.
+   */
   public void handleCurrentHistory() {
     handleHistoryToken(historian.getToken());
   }
 
+  /**
+   * Initialize this place history handler.
+   * 
+   * @return a registration object to de-register the handler
+   */
   public HandlerRegistration register(PlaceController placeController,
       EventBus eventBus, Place defaultPlace) {
     this.placeController = placeController;
diff --git a/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java b/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java
index dc88565..c969908 100644
--- a/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java
+++ b/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java
@@ -20,44 +20,45 @@
 /**
  * Marker interface for the RequestFactory code generator.
  * <p>
- * A RequestFactory implementation will post {@link EntityProxyChange} events to
- * the {@link EventBus} passed into the {@link #initialize} method. The events
- * will have the following {@link WriteOperation} associated with them in the
- * following circumstances:
- * <ul>
- * <li>{@link WriteOperation#PERSIST} when an {@link EntityProxy}
- * {@link RequestContext#create(Class) created} on the client is successfully
- * persisted in the server's backing store.</li>
- * <li>{@link WriteOperation#UPDATE} when changes due to an {@link EntityProxy}
- * being {@link RequestContext#edit(EntityProxy) edited} on the client are
- * successfully persisted in the server's backing store.</li>
- * <li>{@link WriteOperation#UPDATE} when a previously-unseen
- * {@link EntityProxy} is reachable from the return value for a
- * successfully-executed {@link Request}.</li>
- * <li>{@link WriteOperation#UPDATE} when any property of an {@link EntityProxy}
- * reachable from a {@link Request Request's} arguments is seen to have changed
- * after executing the service method on the server.</li>
- * <li>{@link WriteOperation#DELETE} when an {@link EntityProxy} reachable from
- * a {@link Request Request's} arguments becomes irretrievable after executing
- * the service method on the server.</li>
- * </ul>
+ * <b>Limitations on the transferrability of types.</b> <br>
+ * RequestFactory currently supports the transfer of basic value types, entity
+ * types, and collections, with limitations. The basic value types supported
+ * are {@link String}, {@link Enum}, {@link Boolean}, {@link Character},
+ * subtypes of {@link Number}, and {@link java.util.Date}. Any value type not
+ * included in this list may not be declared in the type signature of a service
+ * method, or {@link EntityProxy}. {@link java.util.Collection} types supported
+ * are {@link java.util.List} and {@link java.util.Set} with the restriction
+ * that a collection must be homogeneous and only hold one type of value.
+ * </p>
  * <p>
- * Other types of events may be posted to the {@link EventBus} by other services
- * used by the RequestFactory.
- * 
- * @see {@link com.google.gwt.requestfactory.client.DefaultRequestTransport}
+ * Polymorphism is not supported at this time. RequestFactory encoding and
+ * decoding requires exact knowledge of the concrete type. If a method declares
+ * a given type <code>T</code> as a parameter or return type, only
+ * <code>T</code>'s transferrable properties will be sent over the wire if it is
+ * a proxy, even if the underlying domain value contains extra fields, in
+ * effect, treating it as an instance of the supertype. Returning abstract
+ * supertypes of value types is not supported (e.g. Object, Enum, Number).
+ * </p>
  */
 public interface RequestFactory {
+  /**
+   * The JSON content type String.
+   */
   String JSON_CONTENT_TYPE_UTF8 = "application/json; charset=utf-8";
 
   /**
    * Return a request to find a fresh instance of the referenced proxy.
+   *
+   * @param proxyId an {@link EntityProxyId} instance of type P
+   * @return a {@link Request} object
    */
   <P extends EntityProxy> Request<P> find(EntityProxyId<P> proxyId);
 
   /**
-   * Returns the eventbus this factory's events are posted on, which was set via
+   * Returns the event bus this factory's events are posted on, which was set via
    * {@link #initialize}.
+   *
+   * @return the {@link EventBus} associated with this instance
    */
   EventBus getEventBus();
 
@@ -66,6 +67,7 @@
    * represents the given class. It can be processed by
    * {@link #getProxyClass(String)}
    * 
+   * @param clazz a Class object for an {@link EntityProxy} subclass
    * @return a {@link com.google.gwt.user.client.History} compatible token
    */
   String getHistoryToken(Class<? extends EntityProxy> clazz);
@@ -84,6 +86,7 @@
    * as-yet-unpersisted EntityProxy is only valid for the duration of the
    * RequestFactory's lifespan.
    * 
+   * @param proxy an {@link EntityProxyId} instance
    * @return a {@link com.google.gwt.user.client.History} compatible token
    */
   String getHistoryToken(EntityProxyId<?> proxy);
@@ -93,23 +96,34 @@
    * type of this token, via {@link RequestContext#create}. The token may
    * represent either a proxy instance (see {@link #getHistoryToken}) or a proxy
    * class (see {@link #getProxyClass}).
+   *
+   * @param historyToken a String token
+   * @return a Class object for an {@link EntityProxy} subclass
    */
   Class<? extends EntityProxy> getProxyClass(String historyToken);
 
   /**
    * Return the appropriate {@link EntityProxyId} using a string returned from
    * {@link #getHistoryToken(EntityProxyId)}.
+   *
+   * @param historyToken a String token
+   * @return an {@link EntityProxyId}
    */
   <T extends EntityProxy> EntityProxyId<T> getProxyId(String historyToken);
 
   /**
    * Start this request factory with a
    * {@link com.google.gwt.requestfactory.client.DefaultRequestTransport}.
+   *
+   * @param eventBus an {@link EventBus}
    */
   void initialize(EventBus eventBus);
 
   /**
    * Start this request factory with a user-provided transport.
+   *
+   * @param eventBus an {@link EventBus}
+   * @param transport aÊ{@link RequestTransport} instance
    */
   void initialize(EventBus eventBus, RequestTransport transport);
 }