<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="http://my.rsscache.com/rsc/rss2.xsl"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:rsscache="http://ns.rsscache.com/1.0"><channel><title>Raible Designs</title><link>http://raibledesigns.com/rd/</link><atom:link rel="self" type="application/rss+xml" href="http://raibledesigns.com/rd/feed/entries/rss" /><description>&lt;a href="http://www.linkedin.com/in/mraible"&gt;Matt Raible&lt;/a&gt; is a UI Architect specializing in open source web frameworks. &lt;a href="http://raibledesigns.com/contact.jsp"&gt;Contact me&lt;/a&gt; for rates.</description><language>en-us</language><copyright>Copyright 2009</copyright><lastBuildDate>Wed, 1 Jul 2009 09:06:52 -0600</lastBuildDate><generator>Apache Roller (incubating) 4.0 (20071120033321:dave)</generator><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/raible_road_trip_13</guid><title>Raible Road Trip #13</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/raible_road_trip_13</link><pubDate>Mon, 29 Jun 2009 06:46:04 -0600</pubDate><category>General</category><category>fairmont</category><category>montana</category><category>cabin</category><category>mountrushmore</category><category>thecabin</category><category>camping</category><category>roadtrip</category><description>Another year has passed and it's time for the annual trek to &lt;a href="http://raibledesigns.com/rd/entry/the_cabin"&gt;The Cabin&lt;/a&gt; for the 4th of July. &lt;a href="http://raibledesigns.com/rd/entry/raible_road_trip_12"&gt;Last year&lt;/a&gt;, we took the  route through Yellowstone. This year, we're going to shake things up a bit and head through &lt;a href="http://www.nps.gov/moru/"&gt;Mount Rushmore&lt;/a&gt;. &lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://tinyurl.com/kwuza4"&gt;&lt;img src="http://static.raibledesigns.com/repository/images/raibleroadtrip13_map.png" width="484" height="360" style="border: 1px solid silver" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;One of the highlights of this trip is sure to be &lt;a href="http://www.fairmontmontana.com/"&gt;Fairmont Hot Springs&lt;/a&gt;. We're staying their tomorrow night and I'm sure Abbie and Jack will love it. 
&lt;/p&gt;
&lt;p&gt;
After 3 weeks at The Cabin, we'll be heading to &lt;a href="http://raibledesigns.com/rd/entry/costa_rica_was_awesome"&gt;Clint and Autumn's&lt;/a&gt; wedding reception in Idaho. Having so much time off from work is sure to be strange, but I'm sure I'll get used to it.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Happy 4th everyone!&lt;/em&gt;
&lt;/p&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64845406 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/the_good_ol_job_hunt1</guid><title>The good ol' Job Hunt</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/the_good_ol_job_hunt1</link><pubDate>Fri, 26 Jun 2009 15:30:42 -0600</pubDate><category>Java</category><category>linkedin</category><category>career</category><category>job</category><category>recruiters</category><category>jobhunt</category><category>evite</category><description>Just over two years ago, I wrote about the &lt;a href="http://raibledesigns.com/rd/entry/the_good_ol_job_hunt"&gt;good ol' job hunt&lt;/a&gt;. Today, I find myself in a very similar situation. My Evite gig ends in a couple hours and I'm heading to &lt;a href="http://raibledesigns.com/rd/entry/the_cabin"&gt;The Cabin&lt;/a&gt; on Monday for a month of vacation. Similar to last time, there are opportunities out there, but most of them come through recruiters. 
&lt;/p&gt;
&lt;p&gt;I have to admit - it seems like I got lucky the last couple times I tried to find a gig. I simply blogged I was looking and found myself negotiating with companies a few days later. Getting &lt;a href="http://raibledesigns.com/rd/entry/linkedin_cuts_10_a_k"&gt;laid off from LinkedIn&lt;/a&gt; was awesome in that a few companies contacted me about hiring the whole team the next day. The ability to blog-and-get-a-gig was a great way to cut out the middle-man.&lt;/p&gt;
&lt;p&gt;Unfortunately, I think I got spoiled by my blog-and-get-a-gig success. I figured it would happen again this time... 
&lt;/p&gt;
&lt;p&gt;Not so much. 
&lt;/p&gt;
&lt;p&gt;
I don't know if it's because of the down economy or because I took the year off from speaking at conferences. Regardless, I'm in an interesting situation since I &lt;a href="http://raibledesigns.com/rd/entry/new_office_and_new_bike"&gt;signed a 1-year lease&lt;/a&gt; on an office in downtown Denver.  It's easy to market to companies in Denver, but if I land a gig here, there's a good chance the client is going to want me in the office everyday. That leaves me wondering: what's the best way to market to companies outside of Colorado? My ideal contract is one that 1) allows me to work remotely and 2) only requires me to travel once or twice a month. 
&lt;/p&gt;
&lt;p&gt;
I believe my ideal gigs are out there, but I think it's difficult to convince companies I'm a good remote worker. In an attempt to convince them otherwise, I'd like to offer recommendations from my last two clients.&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
"Matt contributed dramatically to the engineering practice at Evite, both directly and indirectly.  Directly, he lead the effort to define and prove a successful new web UI architecture for us.  Indirectly, he brought senior engineering talent into the organization, and energized the existing team.  We are significantly better positioned to deliver on our Product goals as a result of having worked with Matt.  I'd love to work with him again someday."
&lt;span style="text-align: right; color: #666; display: block"&gt;
&lt;em&gt;&lt;a href="http://www.linkedin.com/profile?viewProfile=&amp;amp;key=494619&amp;amp;authToken=iMtW&amp;amp;authType=name" title="View David's Profile"&gt;David Thomas&lt;/a&gt;, VP of Technology, Evite&lt;/em&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
"Matt has unique abilities in the realm of software engineering. He brings great energy, an amazing breadth of knowledge in UI technologies, along with a can-do attitude that's refreshing to interact with. He is a great leader and communicator. In addition, Matt can apply his deep understanding of the technologies in question pragmatically to the engineering problem at hand, leading his team in execution and delivery. He's an excellent technical visionary to complement any team."
&lt;span style="text-align: right; color: #666; display: block; margin-top: 5px"&gt;
&lt;em&gt;&lt;a href="http://www.linkedin.com/profile?viewProfile=&amp;amp;key=3115840&amp;amp;authToken=xnlz&amp;amp;authType=name" title="View Arnold's Profile"&gt;Arnold Goldberg&lt;/a&gt;, Vice President  Platform Engineering, LinkedIn&lt;/em&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
If you're looking to hire someone with &lt;a href="http://www.linkedin.com/in/mraible"&gt;my skills&lt;/a&gt;, &lt;a href="http://raibledesigns.com/contact.jsp"&gt;let me know&lt;/a&gt; - there's a good chance you'll be glad you did. &lt;img src="http://raibledesigns.com/images/smileys/wink.gif" class="smiley" alt=";-)" title=";-)" /&gt;&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=64743661&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=64743661&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64743661 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/how_to_use_gwt_2</guid><title>How to use GWT 2.0 with Maven and Generate SOYC Reports</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/how_to_use_gwt_2</link><pubDate>Thu, 25 Jun 2009 23:45:04 -0600</pubDate><category>Java</category><category>maven</category><category>gwt</category><category>gwt-maven-plugin</category><category>runasync</category><category>soyc</category><description>One of the most interesting features coming in GWT 2.0 is &lt;a href="http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting"&gt;code splitting&lt;/a&gt; and the ability to use GWT.runAsync() to reduce the size of your application's initial download. This week, I learned how to use GWT 2.0 with my GWT 1.6/Maven project. Below are instructions on how to build and use the latest GWT with Maven.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/webtoolkit/makinggwtbetter.html#compiling"&gt;Checkout GWT and setup GWT_TOOLS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Set a GWT_VERSION environment variable to &lt;em&gt;2.0.0-SNAPSHOT&lt;/em&gt; (export GWT_VERSION=2.0.0-SNAPSHOT).&lt;/li&gt;
&lt;li&gt;Build GWT with the &lt;em&gt;ant&lt;/em&gt; command.&lt;/li&gt;
&lt;li&gt;After building completes, install the GWT artifacts into your local Maven repository using the following commands: 
&lt;pre style="margin-top: 5px"&gt;mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-user -Dversion=2.0.0-SNAPSHOT \
-Dpackaging=jar -Dfile=build/lib/gwt-user.jar

mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-servlet -Dversion=2.0.0-SNAPSHOT \
-Dpackaging=jar -Dfile=build/lib/gwt-servlet.jar

mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-dev -Dversion=2.0.0-SNAPSHOT \
-Dclassifier=mac -Dpackaging=jar -Dfile=build/lib/gwt-dev-mac.jar

mkdir temp
tar -zxf build/dist/gwt-mac-2.0.0-SNAPSHOT.tar.gz -C temp
cd temp/gwt-mac-2.0.0-SNAPSHOT
zip -0 gwt-mac-2.0.0-SNAPSHOT.zip lib*.jnilib
cd ../..

mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-dev -Dversion=2.0.0-SNAPSHOT \
-Dclassifier=mac-libs -Dpackaging=zip \
-Dfile=temp/gwt-mac-2.0.0-SNAPSHOT/gwt-mac-2.0.0-SNAPSHOT.zip
&lt;/pre&gt;
&lt;div style="margin-bottom: 5px; text-align: right"&gt;&lt;em&gt;Thanks to &lt;a href="http://groups.google.com/group/codehaus-mojo-gwt-maven-plugin-users/browse_thread/thread/83e860b1de4565f5"&gt;Jason&lt;/a&gt; for his help with this script.&lt;/em&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Modify the pom.xml of your GWT project to use the the &lt;a href="http://mojo.codehaus.org/gwt-maven-plugin/"&gt;gwt-maven-plugin&lt;/a&gt; from Codehaus. Of course, you'll need to modify the &amp;lt;runTarget&amp;gt; to fit your project.
&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;runTarget&amp;gt;org.appfuse.gwt.mvc.${entry.point}/${entry.point}.html&amp;lt;/runTarget&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;
                &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Modify your dependencies to match the ones below. With the Codehaus plugin, dependencies are much more concise.
&lt;pre class="brush: xml"&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.gwt&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-servlet&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${gwt.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.gwt&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-user&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${gwt.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Add &lt;em&gt;&amp;lt;gwt.version&gt;2.0.0-SNAPSHOT&amp;lt;/gwt.version&gt;&lt;/em&gt; to the properties section of your pom.xml.&lt;/li&gt;
&lt;li&gt;At this point, you should be able to compile your project with &lt;strong&gt;mvn gwt:compile&lt;/strong&gt; and run it in hosted mode using &lt;strong&gt;mvn gwt:run&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generate SOYC Reports&lt;/strong&gt;&lt;br/&gt;
In Google's code splitting documentation, it mentions &lt;a href="http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting#The_Story_of_Your_Compile_(SOYC)"&gt;The Story of Your Compile (SOYC)&lt;/a&gt;. From the documentation:&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
To obtain a SOYC report for your application, there are two steps necessary. First, add -soyc to the compilation options that are passed to the GWT compiler. This will cause the compiler to emit raw information about the compile to XML files in an -aux directory beside the rest of the compiled output. In that directory, you will see an XML file for each permutation and a manifest.xml file that describes the contents of all the others.
&lt;br/&gt;&lt;br/&gt;
The second step is to convert that raw information into viewable HTML. This is done with the SoycDashboard tool.
&lt;/p&gt;
&lt;p&gt;The first step is not currently possible with the gwt-maven-plugin, so I &lt;a href="http://jira.codehaus.org/browse/MGWT-92"&gt;created a patch for it&lt;/a&gt;. 
&lt;/p&gt;
&lt;p style="margin-left: 20px; color: #666"&gt;&lt;em&gt;
If you patch the gwt-maven-plugin and install it locally, make sure and change the version in your pom.xml to &lt;strong&gt;1.2-SNAPSHOT&lt;/strong&gt;.
&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To use the SoycDashboard tool, you'll need to install the gwt-soyc-vis.jar.
&lt;pre&gt;
mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-soyc-vis -Dversion=2.0.0-SNAPSHOT \
-Dpackaging=jar -Dfile=build/lib/gwt-soyc-vis.jar
&lt;/pre&gt;
&lt;p&gt;Now you can generate SOYC reports with &lt;strong&gt;mvn gwt:compile -Dgwt.compiler.soyc=true&lt;/strong&gt;. You can also add &amp;lt;soyc&amp;gt;true&amp;lt;/soyc&amp;gt; to the &amp;lt;configuration&amp;gt; section of the gwt-maven-plugin.&lt;/p&gt;
&lt;p&gt;The second step (converting the raw information into viewable HTML) is possible using &lt;em&gt;java&lt;/em&gt; from the command-line, or by using the &lt;a href="http://mojo.codehaus.org/exec-maven-plugin/"&gt;exec-maven-plugin&lt;/a&gt;. Here's the (lengthy) command-line version:&lt;/p&gt;
&lt;pre&gt;java -Xmx1024m -cp /Users/mraible/.m2/repository/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar:/Users/mraible/.m2/repository/com/google/gwt/gwt-dev/2.0.0-SNAPSHOT/gwt-dev-2.0.0-SNAPSHOT-mac.jar com.google.gwt.soyc.SoycDashboard -resources ~/.m2/repository/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar -out target/soyc-report target/extra/org.appfuse.gwt.mvc.MVC/soycReport/stories0.xml.gz target/extra/org.appfuse.gwt.mvc.MVC/soycReport/dependencies0.xml.gz target/extra/org.appfuse.gwt.mvc.MVC/soycReport/splitPoints0.xml.gz&lt;/pre&gt;
&lt;p&gt;In this example, I'm using the files from &lt;em&gt;stories0.xml.gz&lt;/em&gt;, &lt;em&gt;dependencies0.xml.gz&lt;/em&gt;, &lt;em&gt;splitPoints0.xml.gz&lt;/em&gt;. In the &lt;em&gt;soycReport&lt;/em&gt; output directory, there's 5 of each these files and I'm not sure what the difference between reports is. Hopefully someone on the GWT team can elaborate. The exec-maven-plugin version is as follows:&lt;/p&gt;
&lt;pre class="brush: xml"&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;exec-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;executable&amp;gt;java&amp;lt;/executable&amp;gt;
        &amp;lt;arguments&amp;gt;
            &amp;lt;argument&amp;gt;-cp&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;
                ${settings.localRepository}/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar:${settings.localRepository}/com/google/gwt/gwt-dev/2.0.0-SNAPSHOT/gwt-dev-2.0.0-SNAPSHOT-${platform}.jar
            &amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;com.google.gwt.soyc.SoycDashboard&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;-out&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;target/soyc-report&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;-resources&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;
                ${settings.localRepository}/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar
            &amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;${project.build.directory}/extra/org.appfuse.gwt.mvc.MVC/soycReport/stories0.xml.gz&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;${project.build.directory}/extra/org.appfuse.gwt.mvc.MVC/soycReport/dependencies0.xml.gz&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;${project.build.directory}/extra/org.appfuse.gwt.mvc.MVC/soycReport/splitPoints0.xml.gz&amp;lt;/argument&amp;gt;
        &amp;lt;/arguments&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;After configuring this plugin in your project, you should be able to run &lt;strong&gt;mvn gwt:compile exec:exec&lt;/strong&gt; and open the generated report (at &lt;em&gt;target/soyc-report/SoycDashboard-index.html&lt;/em&gt;). Currently, there doesn't seem to be much documentation on SOYC. &lt;a href="http://www.slideshare.net/fredsa/gwt-overview-and-feature-preview-sv-web-jug-june-16-2009"&gt;Fred Sauer's recent presentation&lt;/a&gt; talks a bit about SOYC and GWT.runAsync(), but that's about it.&lt;/p&gt;
&lt;p&gt;To figure out how to use GWT 2.0 with Maven, I used my &lt;a href="http://raibledesigns.com/rd/entry/gxt_s_mvc_framework"&gt;GWT MVC Example&lt;/a&gt; project. The first SOYC report I generated said the initial download was 108,967 KB. To integrate GWT.runAsync(), I modified all the project's controllers so their &lt;em&gt;handleEvent()&lt;/em&gt; methods changed from this:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public void handleEvent(AppEvent&lt;?&gt; event) {
    onViewHome(event);
}
&lt;/pre&gt;
&lt;p&gt;To this:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public void handleEvent(final AppEvent&lt;?&gt; event) {
    GWT.runAsync(new RunAsyncCallback() {
        public void onFailure(Throwable throwable) {
            Window.alert(throwable.getMessage());
        }

        public void onSuccess() {
            onViewHome(event);
        }
    });
}

&lt;/pre&gt;&lt;p&gt;When I generated a new SOYC report, the initial download size was reduced to 56,718 KB. Furthermore, I was able to see that my "Leftovers code" consisted of 63,175 KB. I'm sure there's better ways to split my project using GWT.runAsync(), but I'm happy to see I was able to reduce the initial download by 50%. &lt;/p&gt;
&lt;p&gt;If you'd like to try GWT 2.0, you can can &lt;a href="http://static.raibledesigns.com/downloads/gwt-mvc-1.1.zip"&gt;download my gwt-mvc example project&lt;/a&gt;. To build/run this project, you'll need to 1) build and install GWT, 2) patch gwt-maven-plugin and 3) run &lt;strong&gt;mvn gwt:compile exec:exec&lt;/strong&gt; to generate the SOYC report. In an ideal world, the gwt-maven-plugin can be enhanced to generate the SOYC report (rather than using the exec-maven-plugin). In the meantime, I think it's pretty cool that you can try out GWT 2.0 features while they're still being developed.&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64710092 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/json_parsing_with_javascript_overlay</guid><title>JSON Parsing with JavaScript Overlay Types in GWT</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/json_parsing_with_javascript_overlay</link><pubDate>Wed, 24 Jun 2009 09:52:49 -0600</pubDate><category>Java</category><category>gwt</category><category>json</category><category>javascript</category><category>twitter</category><category>overlaytypes</category><category>requestbuilder</category><description>A reader recently &lt;a href="http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt#comment-1245137914000"&gt;asked&lt;/a&gt;:&lt;/p&gt;
&lt;p style="color: #666" class="quote"&gt;
I would love to see a snippet of how to eval the JSON coming from RequestBuilder into the OverlayTypes. What is the mapping like? I used OverlayTypes to read in static data that I render into the head section of the hosted page, which is pretty easy and fast, but I don't know how to do this "reading" dynamically at runtime.&lt;/p&gt;
&lt;p&gt;If you're not familiar with GWT's Overlay Types (added in 1.5), see &lt;a href="http://googlewebtoolkit.blogspot.com/2008/08/getting-to-really-know-gwt-part-2.html"&gt;Getting to really know GWT, Part 2: JavaScript Overlay Types&lt;/a&gt;. In our project, we're using Overlay Types to simplify JSON parsing and make our application lean-and-mean as possible. 
&lt;/p&gt;
&lt;p&gt;
First of all, we have a JSOModel class that acts as our overlay type:
&lt;/p&gt;
&lt;pre class="brush: java"&gt;
import java.util.HashSet;
import java.util.Set;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;

/**
 * Java overlay of a JavaScriptObject.
 */
public abstract class JSOModel extends JavaScriptObject {

    // Overlay types always have protected, zero-arg constructors
    protected JSOModel() {
    }

    /**
     * Create an empty instance.
     * 
     * @return new Object
     */
    public static native JSOModel create() /*-{
        return new Object();
    }-*/;

    /**
     * Convert a JSON encoded string into a JSOModel instance.
     * &amp;lt;p/&amp;gt;
     * Expects a JSON string structured like '{"foo":"bar","number":123}'
     *
     * @return a populated JSOModel object
     */
    public static native JSOModel fromJson(String jsonString) /*-{
        return eval('(' + jsonString + ')');
    }-*/;

    /**
     * Convert a JSON encoded string into an array of JSOModel instance.
     * &amp;lt;p/&amp;gt;
     * Expects a JSON string structured like '&amp;#91;{"foo":"bar","number":123}, {...}&amp;#93;'
     *
     * @return a populated JsArray
     */
    public static native JsArray&amp;lt;JSOModel&amp;gt; arrayFromJson(String jsonString) /*-{
        return eval('(' + jsonString + ')');
    }-*/;

    public final native boolean hasKey(String key) /*-{
        return this&amp;#91;key&amp;#93; != undefined;
    }-*/;

    public final native JsArrayString keys() /*-{
        var a = new Array();
        for (var p in this) { a.push(p); }
        return a;
    }-*/;

    @Deprecated
    public final Set&amp;lt;String&amp;gt; keySet() {
        JsArrayString array = keys();
        Set&amp;lt;String&amp;gt; set = new HashSet&amp;lt;String&amp;gt;();
        for (int i = 0; i &amp;lt; array.length(); i++) {
            set.add(array.get(i));
        }
        return set;
    }

    public final native String get(String key) /*-{
        return "" + this&amp;#91;key&amp;#93;;
    }-*/;

    public final native String get(String key, String defaultValue) /*-{
        return this&amp;#91;key&amp;#93; ? ("" + this&amp;#91;key&amp;#93;) : defaultValue;
    }-*/;

    public final native void set(String key, String value) /*-{
        this&amp;#91;key&amp;#93; = value;
    }-*/;

    public final int getInt(String key) {
        return Integer.parseInt(get(key));
    }

    public final boolean getBoolean(String key) {
        return Boolean.parseBoolean(get(key));
    }

    public final native JSOModel getObject(String key) /*-{
        return this&amp;#91;key&amp;#93;;
    }-*/;

    public final native JsArray&amp;lt;JSOModel&amp;gt; getArray(String key) /*-{
        return this&amp;#91;key&amp;#93; ? this&amp;#91;key&amp;#93; : new Array();
    }-*/;
}
&lt;/pre&gt;
&lt;p&gt;This class alone allows you to easily parse JSON returned in a callback. For example, here's an example of parsing &lt;a href="http://twitter.com/statuses/user_timeline.json"&gt;Twitter's User Timeline&lt;/a&gt; in my &lt;a href="http://raibledesigns.com/rd/entry/implementing_oauth_with_gwt"&gt;OAuth with GWT&lt;/a&gt; application.
&lt;/p&gt;
&lt;pre class="brush: java"&gt;
private class TwitterApiCallback implements RequestCallback {
    public void onResponseReceived(Request request, Response response) {
        if (response.getStatusCode() == 200) {
            JsArray&amp;lt;JSOModel&amp;gt; data = JSOModel.arrayFromJson(response.getText());
            List&amp;lt;JSOModel&amp;gt; statuses = new ArrayList&amp;lt;JSOModel&amp;gt;();
            for (int i = 0; i &amp;lt; data.length(); i++) {
                statuses.add(data.get(i));
            }

            // populate textarea with returned statuses
            for (JSOModel status : statuses) {
                payload.setValue(payload.getValue() + status.get("text") + "\n\n");
            }
            
            Label success = new Label("API call successful!");
            success.setStyleName("success");
            form.add(success);
        } else {
            onError(request, new RequestException(response.getText()));
        }
    }

    public void onError(Request request, Throwable throwable) {
        Window.alert("Calling API failed. " + OAuthPage.STANDARD_ERROR + "\n\n" + throwable.getMessage());
    }
}
&lt;/pre&gt;
&lt;p&gt;To simply things even more, we created a BaseModel class that can be extended.&lt;/p&gt;
&lt;pre class="brush: java"&gt;
import java.util.Map;
import java.util.HashMap;

import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.DOM;

public abstract class BaseModel {

    protected JSOModel data;

    public BaseModel(JSOModel data) {
        this.data = data;
    }

    public String get(String field) {
        String val = this.data.get(field);
        if (val != null &amp;amp;&amp;amp; "null".equals(val) || "undefined".equals(val)) {
            return null;
        } else {
            return escapeHtml(val);
        }
    }

    public Map&amp;lt;String, String&amp;gt; getFields() {
        Map&amp;lt;String, String&amp;gt; fieldMap = new HashMap&amp;lt;String, String&amp;gt;();

        if (data != null) {
            JsArrayString array = data.keys();

            for (int i = 0; i &amp;lt; array.length(); i++) {
                fieldMap.put(array.get(i), data.get(array.get(i)));
            }
        }
        return fieldMap;
    }

    private static String escapeHtml(String maybeHtml) {
        final Element div = DOM.createDiv();
        DOM.setInnerText(div, maybeHtml);
        return DOM.getInnerHTML(div);
    }
}
&lt;/pre&gt;
&lt;p&gt;You can extend this class and create model objects that represent a more Java-like view of your data. For example, I could create a Status class with the following code:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public class Status extends BaseModel {
    
    public Status(JSOModel data) {
        super(data);
    }

    public String getText() {
        return get("text");
    }
}
&lt;/pre&gt;
&lt;p&gt;Then I could change my JSON parsing in TwitterApiCallback to be:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
    private class TwitterApiCallback implements RequestCallback {
    public void onResponseReceived(Request request, Response response) {
        if (response.getStatusCode() == 200) {
            JsArray&amp;lt;JSOModel&amp;gt; data = JSOModel.arrayFromJson(response.getText());
            List&amp;lt;Status&amp;gt; statuses = new ArrayList&amp;lt;Status&amp;gt;();
            for (int i = 0; i &amp;lt; data.length(); i++) {
                Status s = new Status(data.get(i));
                statuses.add(s);
            }

            // populate textarea with returned statuses
            for (Status status : statuses) {
                payload.setValue(payload.getValue() + status.getText() + "\n\n");
            }

            Label success = new Label("API call successful!");
            success.setStyleName("success");
            form.add(success);
        } else {
            onError(request, new RequestException(response.getText()));
        }
    }

    public void onError(Request request, Throwable throwable) {
        Window.alert("Calling API failed. " + OAuthPage.STANDARD_ERROR + "\n\n" + throwable.getMessage());
    }
}
&lt;/pre&gt;
&lt;p&gt;That's how we're doing lightweight JSON parsing with GWT. I've updated my &lt;a href="http://demo.raibledesigns.com/gwt-oauth/"&gt;GWT with OAuth demo&lt;/a&gt; with this code. You can also &lt;a href="http://static.raibledesigns.com/downloads/gwt-oauth-1.1.zip"&gt;download the source&lt;/a&gt;. Please let me know if you have any questions. &lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=64656146&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=64656146&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64656146 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/a_fun_father_s_day</guid><title>A Fun Father's Day at Great Sand Dunes</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/a_fun_father_s_day</link><pubDate>Tue, 23 Jun 2009 23:28:13 -0600</pubDate><category>General</category><category>sanddunes</category><category>fathersday</category><category>camping</category><category>greatsanddunes</category><category>dad</category><category>colorado</category><category>abbie</category><category>jack</category><category>kids</category><description>Our &lt;a href="http://raibledesigns.com/rd/entry/going_to_the_great_sand"&gt;Father's Day trip&lt;/a&gt; started out a bit rocky when my Dad's flight got delayed an entire day. Fortunately, it ended up being a blessing in disguise. As &lt;a href="http://raibledesigns.com/rd/entry/going_to_the_great_sand#comment-1245646443000"&gt;Doug commented&lt;/a&gt;, Friday night was wet and Saturday wasn't much better. Our friends, Jenny and Jeff, left early Saturday morning and arrived in time for a couple hours of rain. At 3:00 on Saturday afternoon, it cleared up and was beautiful for the rest of the weekend. 
&lt;/p&gt;
&lt;p&gt;
We showed up at 8:30 on Saturday night and stayed through Monday morning. If you asked Abbie and Jack, they'd say the best part was driving on the road past the &lt;a href="http://activities.wildernet.com/pages/activity.cfm?actid=SANDIO*16195prk"&gt;Point of No Return&lt;/a&gt;. My favorite moment was when they climbed to the top of a dune with me. The mosquitoes were mean and plentiful, but the campground was well equipped and had excellent views. 
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3410/3655575351_15034a94c7.jpg" title="Jack's first hike to The Dunes" rel="lightbox[sanddunes2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3410/3655575351_15034a94c7_m.jpg" width="240" height="180" alt="Jack's first hike to The Dunes" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3338/3656373540_a0dd349d0d.jpg" title="There's a good spot!" rel="lightbox[sanddunes2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3338/3656373540_a0dd349d0d_m.jpg" width="240" height="180" alt="There's a good spot!" style="border: 1px solid black; margin-left: 10px"  /&gt;&lt;/a&gt;

&lt;br/&gt;&lt;br/&gt;

&lt;a href="http://farm3.static.flickr.com/2461/3655577467_c84ac6e9d7.jpg" title="Running to see Jenny and Jeff" rel="lightbox[sanddunes2009]"&gt;&lt;img src="http://farm3.static.flickr.com/2461/3655577467_c84ac6e9d7_m.jpg" width="240" height="180" alt="Running to see Jenny and Jeff" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm3.static.flickr.com/2471/3655577971_fbbbef5dc0.jpg" title="The Pratts" rel="lightbox[sanddunes2009]"&gt;&lt;img src="http://farm3.static.flickr.com/2471/3655577971_fbbbef5dc0_m.jpg" width="240" height="180" alt="The Pratts" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;br/&gt;&lt;br/&gt;
&lt;a href="http://farm3.static.flickr.com/2151/3656377546_58a9f59c25.jpg" title="Hiking back to campsite" rel="lightbox[sanddunes2009]"&gt;&lt;img src="http://farm3.static.flickr.com/2151/3656377546_58a9f59c25_m.jpg" width="240" height="180" alt="Hiking back to campsite" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3622/3656378886_c1806dfc33.jpg" title="Sunset at The Dunes" rel="lightbox[sanddunes2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3622/3656378886_c1806dfc33_m.jpg" width="240" height="180" alt="Sunset at The Dunes" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;If you ever get a chance to take your kids to &lt;a href="http://www.nps.gov/grsa/"&gt;Great Sand Dunes&lt;/a&gt;, you should jump at the opportunity. This place is simply awesome. For more pictures, see my &lt;a href="http://www.flickr.com/photos/mraible/sets/72157620431004902/"&gt;Great Sand Dunes 2009&lt;/a&gt; set on &lt;a href="http://www.flickr.com/"&gt;Flickr&lt;/a&gt;.&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64656145 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/going_to_the_great_sand</guid><title>Going to the Great Sand Dunes for Father's Day</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/going_to_the_great_sand</link><pubDate>Fri, 19 Jun 2009 15:57:01 -0600</pubDate><category>General</category><category>camping</category><category>fathersday</category><category>greatsanddunes</category><category>dad</category><description>Last year's &lt;a href="http://raibledesigns.com/rd/entry/the_father_s_day_camping"&gt;Father's Day Camping Trip&lt;/a&gt; was quite the debacle. Regardless, we had a lot of fun and I'm committed to making it a tradition. This year, we're going camping at the &lt;a href="http://www.nps.gov/grsa/"&gt;Great Sand Dunes&lt;/a&gt; in Southern Colorado. The last time I went camping at the Sand Dunes was before Abbie was born, so I'm very much looking forward to it. It's really an amazing place that's somewhat indescribable with words. It's one of those places you have to see to believe.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://photography.nationalgeographic.com/photography/enlarge/great-sand-dunes_pod_image.html" title="The Great Sand Dunes"&gt;&lt;img src="http://farm4.static.flickr.com/3620/3642487758_c73e6de423.jpg" width="500" height="375" alt="The Great Sand Dunes" style="border: 1px solid black" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;The funny part of this year's trip is it's already looking like we might have some good adventures. My dad was supposed to fly into Denver today at 3:00. It's a 4-hour drive to the dunes, which puts us arriving around 7:30. That's probably enough time to pitch a tent and have a beer or two. Instead, his &lt;a href="http://twitter.com/mraible/status/2241339305"&gt;flight is delayed&lt;/a&gt;. Arriving in the dark w/o a campsite seems like a bad idea, so I made a reservation at the KOA Campground in Alamosa. I'm somewhat disappointed we won't be camping at the dunes tonight, but we'll get to see the dunes first thing in the morning. &lt;/p&gt;
&lt;p&gt;To all the dads out there - I hope you have a great Father's Day weekend!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update @ 5:45 PM:&lt;/strong&gt; My dad just called and said United cancelled his flight. Apparently, they'll put him on the same flight tomorrow. That means we won't get to the dunes until 7:30 tomorrow night. &lt;img src="http://raibledesigns.com/images/smileys/sad.gif" class="smiley" alt=":(" title=":(" /&gt;&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=64656144&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=64656144&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64656144 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/implementing_oauth_with_gwt</guid><title>Implementing OAuth with GWT</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/implementing_oauth_with_gwt</link><pubDate>Thu, 18 Jun 2009 13:59:13 -0600</pubDate><category>Java</category><category>javascript</category><category>oauth</category><category>google</category><category>gwt</category><description>I've heard about &lt;a href="http://oauth.net/"&gt;OAuth&lt;/a&gt; for quite some time, but never had an opportunity to implement it on a project. For a good explanation of what OAuth is, see its &lt;a href="http://oauth.net/about"&gt;Introduction&lt;/a&gt;. Here's an excerpt: &lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
...it allows you the User to grant access to your private resources on one site (which is called the Service Provider), to another site (called Consumer, not to be confused with you, the User). While OpenID is all about using a single identity to sign into many sites, OAuth is about giving access to your stuff without sharing your identity at all (or its secret parts).
&lt;/p&gt;
&lt;p&gt;The reason I needed OAuth was to interact with the &lt;a href="http://code.google.com/apis/contacts/"&gt;Google Contacts API&lt;/a&gt;. I've always hated how sites make you import all your contacts from Gmail. I wanted to develop a system that'd let you simply read your contacts from Google in real-time.
&lt;/p&gt;
&lt;p&gt;Since the &lt;a href="http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt"&gt;application I'm working on uses GWT&lt;/a&gt;, I chose to implement an OAuth client in GWT. After googling for "&lt;a href="http://www.google.com/search?q=gwt+oauth"&gt;gwt oauth&lt;/a&gt;", I found &lt;a href="http://code.google.com/p/gwt-examples/wiki/oAuth"&gt;two&lt;/a&gt; &lt;a href="www.sergimansilla.com/blog/?p=75"&gt;examples&lt;/a&gt;. Unfortunately, neither worked out-of-the-box. 
&lt;/p&gt;
&lt;p&gt;
The good news is I did manage to create a working solution. The bad news is it only seems to work at random. That's right folks, I created a solution that only works 50% of the time. I'm somewhat embarrassed to post it here, but I also realize the power of open source and community. By sharing, I hope we can find the flaws in my logic and come up with a solution for all GWT applications. 
&lt;/p&gt;
&lt;p&gt;The best project for OAuth libraries seems to be &lt;a href="http://code.google.com/p/oauth/"&gt;oauth on Google Code&lt;/a&gt;. However, you'll notice that there is no JavaScript implementation listed on the homepage. I did look at the &lt;a href="http://oauth.googlecode.com/svn/code/java/"&gt;Java&lt;/a&gt; implementation, but quickly realized it wouldn't be usable in GWT. Therefore, I opted for the &lt;a href="http://oauth.googlecode.com/svn/code/javascript/"&gt;JavaScript&lt;/a&gt; implementation.
&lt;/p&gt;
&lt;p&gt;OAuth consists of several steps. The following diagram explains the authentication flow nicely.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3384/3638983340_e353831f5c_o.png" title="OAuth Authentication Flow" rel="lightbox[gwt-oauth]"&gt;&lt;img src="http://farm4.static.flickr.com/3384/3638983340_4d939fd820.jpg" width="500" height="368" alt="OAuth Authentication Flow" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;In a nutshell, you have to complete the following steps:
&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Get a token from the service provider.&lt;/li&gt;
&lt;li&gt;Redirect user to service provider to grant access and redirect back to application.&lt;/li&gt;
&lt;li&gt;Request access token to access protected resources.&lt;/li&gt;
&lt;li&gt;Access protected resources and pull/push data.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
To access a service provider's OAuth service, you'll likely need to start by registering your application. For Google, &lt;a href="http://code.google.com/apis/accounts/docs/OAuth.html"&gt;OAuth Authentication for Web Applications&lt;/a&gt; is an excellent resource. Google's &lt;a href="http://googlecodesamples.com/oauth_playground/"&gt;OAuth Playground&lt;/a&gt; is a great way to with the Google Data APIs after you've registered.
&lt;/p&gt;
&lt;p&gt;
Now that you know how OAuth works, let's look at how I implemented it with GWT.  I started by adding the necessary JavaScript references to my *.gwt.xml file.&lt;/p&gt;
&lt;pre class="brush: xml"&gt;
&amp;lt;script src="http://oauth.googlecode.com/svn/code/javascript/oauth.js"/&amp;gt;
&amp;lt;script src="http://oauth.googlecode.com/svn/code/javascript/sha1.js"/&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Next, I needed a way to sign the request. I tried to use Sergi Mansilla's &lt;a href="http://sergimansilla.com/public/flyqlr/flyqlr/src/com/sergi/client/OAuth.java"&gt;OAuth.java&lt;/a&gt; for this, but discovered issues with how the parameters were being written with GWT 1.6. I opted for Paul Donnelly's &lt;a href="http://paul.donnelly.org/2008/10/31/2-legged-oauth-javascript-function-for-yql/"&gt;makeSignedRequest function&lt;/a&gt; instead. By adding this to my application's HTML page, I'm able to call it using the following JSNI method:
&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public native static String signRequest(String key, String secret, String tokenSecret, String url) /*-{
    return $wnd.makeSignedRequest(key, secret, tokenSecret, url);
}-*/;
&lt;/pre&gt;
&lt;p&gt;After the URL is signed, it needs to be sent to the provider to get a &lt;em&gt;request token&lt;/em&gt;. To do this, I used GWT's RequestBuilder and created a &lt;em&gt;send()&lt;/em&gt; method:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
protected void send(RequestCallback cb, String URL) {
    RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL);
    builder.setTimeoutMillis(10000);
    builder.setCallback(cb);
    
    Request req = null;
    try {
        req = builder.send();
    } catch (RequestException e) {
        cb.onError(req, e);
    }
}
&lt;/pre&gt;
&lt;p&gt;If you try this with Google's &lt;a href="https://www.google.com/accounts/OAuthGetRequestToken"&gt;Request Token URL&lt;/a&gt; in GWT's hosted mode, nothing will happen. Compile/browse to Safari and you'll still see nothing. Try it in Firefox and you'll see the following.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;img src="http://farm3.static.flickr.com/2437/3639119788_b675d86360_o.png" width="400" alt="SOP Error" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;To workaround browsers' &lt;a href="http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/FAQ_SOP"&gt;Same Origin Policy&lt;/a&gt;I added a proxy servlet to send the requests. I started with Jason Edwards's &lt;a href="http://edwardstx.net/wiki/attach/HttpProxyServlet/ProxyServlet.java"&gt;ProxyServlet&lt;/a&gt; and modified it to fit my needs. I then registered it in both *.gwt.xml and web.xml.
&lt;/p&gt;
&lt;pre class="brush: xml"&gt;
&amp;lt;servlet path="/google/" class="org.appfuse.gwt.servlet.AlternateHostProxyServlet"/&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now, before calling the &lt;em&gt;send()&lt;/em&gt; method, I replace the start of the URL so the request would be routed through the servlet.&lt;/p&gt;
&lt;pre class="brush:java"&gt;
public void getToken(RequestCallback cb) {
    String url = signRequest(provider.getConsumerKey(), 
                             provider.getConsumerSecret(), 
                             "", provider.getRequestTokenURL());
    url = url.replace("https://www.google.com/", "/google/");
    send(cb, url);
}
&lt;/pre&gt;
&lt;p&gt;When the request returns, I create two cookies by calling a &lt;em&gt;createOAuthCookies()&lt;/em&gt; method with the payload returned:&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public static String[] createOAuthCookies(String data) {
    String oauth_token = data.substring(data.indexOf("oauth_token=") + 12);
    oauth_token = oauth_token.substring(0, oauth_token.indexOf("&amp;"));

    String oauth_token_secret = data.substring(data.indexOf("oauth_token_secret=") + 19);

    Cookies.setCookie("oauth_token", URL.decode(oauth_token));
    Cookies.setCookie("oauth_token_secret", URL.decode(oauth_token_secret));
    return new String[]{oauth_token, oauth_token_secret};
}
&lt;/pre&gt;
&lt;p&gt;The next step is to authorize the token. This is where things got tricky with my proxy servlet and I had to add some special logic for GWT. Google was sending back a 302 with a Location header, but it wasn't hitting the &lt;em&gt;onResponseReceived()&lt;/em&gt; method in my callback. For this reason, I had to change it to a 200 status code and add the redirect location to the body. I also discovered that sometimes they'd return an HTML page with a &lt;code&gt;&amp;lt;meta http-equiv="refresh" ...&amp;gt;&lt;/code&gt; tag. When using Twitter, I discovered the full HTML for the allow/deny page was returned.
Below is the callback I'm using. &lt;a href="http://gwt-widget.sourceforge.net/docs/xref/org/gwtwidgets/client/util/WindowUtils.html"&gt;WindowUtils&lt;/a&gt; is a class I got from Robert Hanson and the &lt;a href="http://gwt-widget.sourceforge.net/"&gt;gwt-widget&lt;/a&gt; project.
&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public void onResponseReceived(Request request, Response response) {
    String text = response.getText();
    if (response.getStatusCode() == 200 &amp;&amp; response.getText().startsWith("http")) {
        WindowUtils.changeLocation(response.getText());
    } else {
        // look for meta-tag that refreshes and grab its URL
        if (text.contains("&lt;meta http-equiv=\"refresh\"")) {
            String tokenToStartWith = "url=&amp;#39;";
            String tokenToEndWith = "&amp;#39;\"&gt;";
            String url = text.substring(text.indexOf(tokenToStartWith) + tokenToStartWith.length());
            url = url.substring(0, url.indexOf(tokenToEndWith) + tokenToEndWith.length());
            WindowUtils.changeLocation(url);
        } else {
            // Twitter returns a full HTML page, so redirect to the authorize URL manually
            if (provider instanceof Twitter) {
                String url = provider.getAuthorizeTokenURL();
                url = url.replace("$1", OAuthRequest.getAuthToken());
                url = url.replace("$2", DefaultRequest.getCurrentLocation());
                WindowUtils.changeLocation(url);
            } else {
                onError(request, new RequestException(text));
            }
        }
    }
}

public void onError(Request request, Throwable caught) {
    Window.alert("Calling authorize token failed. " + OAuthPage.STANDARD_ERROR + "\n\n" + caught.getMessage());
}&lt;/pre&gt;
&lt;p&gt;The 3rd step is to get an access token. The most important thing to remember when you do this is to include the "oauth_token_secret" value when signing the request.&lt;/p&gt;
&lt;pre class="brush: java"&gt;
signRequest(provider.getConsumerKey(), provider.getConsumerSecret(), 
            getAuthTokenSecret(), url);
&lt;/pre&gt;
&lt;p&gt;After this completes with a 200, I create the cookies again (since oauth_token and oauth_token_secret are returned in the body), then call the API to get a list of contacts. The ContactsRequests class is responsible for making the call. The DefaultRequest class contains the &lt;em&gt;send()&lt;/em&gt; method as well as utility methods to get the cookie values of the oauth tokens.&lt;/p&gt;
&lt;pre class="brush: java"&gt;
public class ContactsRequest extends DefaultRequest {
    private static final String GOOGLE_CONTACTS_URL = 
        "http://www.google.com/m8/feeds/contacts/default/thin?oauth_token=$1";
    private OAuthProvider provider;

    public ContactsRequest(OAuthProvider provider) {
        this.provider = provider;
    }

    public void getContacts(RequestCallback cb) {
        String url = GOOGLE_CONTACTS_URL.replace("$1", getAuthToken());
        url = signRequest(provider.getConsumerKey(), provider.getConsumerSecret(), 
                          getAuthTokenSecret(), url);

        String proxiedURLPrefix = "/contacts/";
        // allow for deploying at /gwt-oauth context
        if (WindowUtils.getLocation().getPath().contains("gwt-oauth")) {
            proxiedURLPrefix = "/gwt-oauth" + proxiedURLPrefix;
        }

        url = url.replace("http://www.google.com/", proxiedURLPrefix);

        send(cb, url);
    }
}&lt;/pre&gt;
&lt;p&gt;If all goes well, the response contains the data you requested and it's used to populate a textarea (at least in this demo application). Of course, additional processing needs to occur to parse/format this data into something useful.&lt;/p&gt;
&lt;p&gt;This all sounds pretty useful for GWT applications, right? I believe it does - but only if it works consistently. I sent &lt;a href="http://groups.google.com/group/oauth/browse_thread/thread/e180000f5bd9dc2c"&gt;a message&lt;/a&gt; to the OAuth Google Group explaining the issues I've had.
&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
I'm trying to use the JavaScript API to authenticate with OAuth from a
GWT application. I've got it working with both Google and Twitter's
OAuth implementations. However, it seems to fail to sign the URL at
random. In other words, it works 1 out of 3 times.
...
Any idea why this could be happening? 
&lt;/p&gt;
&lt;p&gt;I received a &lt;a href="http://groups.google.com/group/oauth/msg/ba2cb1bed6eecceb"&gt;response&lt;/a&gt; with a cleaner &lt;em&gt;makeSignedRequest()&lt;/em&gt; function. I tried it and, unfortunately, it seems to be equally unreliable. I suspect the problem is with the OAuth JavaScript implementation, GWT's interpretation of it, or that OAuth isn't as mature as it appears to be. I'd like to think one of the first two causes the problem.
&lt;/p&gt;
&lt;p&gt;To make it easier to create a robust example of GWT and OAuth, I created a gwt-oauth project you can &lt;a href="http://static.raibledesigns.com/downloads/gwt-oauth-1.0.zip"&gt;download&lt;/a&gt; or &lt;a href="http://demo.raibledesigns.com/gwt-oauth"&gt;view online&lt;/a&gt;. Please keep in mind the demo is likely to be flakey. If you're persistent and try enough times, it's likely to work. Firefox seems to succeed moreso than Safari or Chrome. If you have any suggestions for improving this example, please let me know.&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64412236 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><title>[Ad] Los Angeles Mom Lost 47 lbs Following 1 rule!</title><link>http://www.rsscache.com/Section/Advertise/click.aspx?a=190947</link><description>I Cut Down 47 lbs of Stomach Fat In A Month By Obeying This 1 Old Rule</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt</guid><title>Enhancing Evite.com with GWT and Grails</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt</link><pubDate>Mon, 15 Jun 2009 07:41:37 -0600</pubDate><category>Java</category><category>rest</category><category>gxt</category><category>memcached</category><category>gwt</category><category>evite</category><category>grails</category><category>java</category><category>sofea</category><description>&lt;a href="http://www.evite.com"&gt;&lt;img src="http://static.raibledesigns.com/repository/images/evite-logo.png" width="144" height="93" alt="Evite.com" class="picture" style="border: 1px solid silver" /&gt;&lt;/a&gt;
On my &lt;a href="http://www.linkedin.com/in/mraible"&gt;LinkedIn Profile&lt;/a&gt;, it says my current gig is a SOFEA consultant at a stealth-mode startup. &lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
SOFEA Consultant, Stealth Mode Startup, Los Angeles, CA. December 2008 -- Present.
&lt;/p&gt;
&lt;p&gt;
OK, I lied. It's not a startup, it's a well-known company that helps you plan parties.
For the last 5+ months, my &lt;a href="http://raibledesigns.com/rd/entry/what_s_next"&gt;UI team from LinkedIn&lt;/a&gt; has been working with &lt;a href="http://www.evite.com"&gt;Evite.com&lt;/a&gt; to enhance portions of their site with a &lt;a href="http://raibledesigns.com/rd/entry/re_life_above_the_service"&gt;SOFEA architecture&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;In January, we started &lt;a href="http://raibledesigns.com/rd/entry/choosing_an_ajax_framework"&gt;evaluating Ajax Frameworks&lt;/a&gt; and came to the conclusion that &lt;a href="http://raibledesigns.com/rd/entry/ajax_framework_analysis_results"&gt;GWT was right for us&lt;/a&gt;. After we chose the UI framework, other team members chose &lt;a href="http://grails.org"&gt;Grails&lt;/a&gt; and &lt;a href="http://www.danga.com/memcached/"&gt;memcached&lt;/a&gt; to develop scalable RESTful services. The architecture we implemented involves using GWT's &lt;a href="http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/http/client/RequestBuilder.html"&gt;RequestBuilder&lt;/a&gt; to talk to Grails' services, which cache almost all their JSON output in memcached.
&lt;/p&gt;
&lt;p&gt;To see an example of a feature we developed with GWT, see Evite's &lt;a href="http://www.evite.com/party/invitations"&gt;Design Gallery&lt;/a&gt;. I personally worked on this feature and very much enjoyed becoming a GWT aficionado in the process. GWT's zero-turnaround feature made doing pure client-side work a lot of fun. It's definitely something I'd like to continuing doing at my next gig. &lt;/p&gt;
&lt;p&gt;Everyone from Evite is very happy with what we've been able to do with GWT and Grails. We have a stateless architecture and are quickly able to develop both client-side and server-side features. We've learned to scale the client by using out-of-the-box GWT components. We've scaled Grails by caching as much as possible. We serve up Ads and Analytics using the same JavaScript mechanisms that traditional server-side frameworks use. 
&lt;/p&gt;
&lt;p&gt;At the end of this month, my gig with Evite comes to an end. I'll be spending a few weeks at my family's cabin in Montana and then it's on to the next big thing. What's the next big thing? I'm not sure yet, hence the reason for writing this. If you're looking to develop a GWT application, introduce a SOFEA architecture at your company, or simply adopt some open source frameworks, I'd love to help out. &lt;a href="http://raibledesigns.com/contact.jsp"&gt;Drop me a line&lt;/a&gt; and let's start a conversation. &lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=64393132&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=64393132&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64393132 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/2nd_row_at_red_rocks</guid><title>2nd Row at Red Rocks and Elephant Rock Ride</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/2nd_row_at_red_rocks</link><pubDate>Mon, 8 Jun 2009 22:54:15 -0600</pubDate><category>General</category><category>bigheadtodd</category><category>elephantrock</category><category>riding</category><category>biking</category><category>redrocks</category><description>&lt;a href="http://farm4.static.flickr.com/3392/3609197663_ae8d26a755.jpg" title="Bear Lake Trail" rel="lightbox[bhtm2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3392/3609197663_ae8d26a755_t.jpg" width="100" height="75" alt="Bear Lake Trail" class="picture" /&gt;&lt;/a&gt;
This past weekend, I did a lot of traveling by 2 wheels. The weather was beautiful and - thanks to &lt;a href="http://bsnyderblog.blogspot.com/"&gt;Bruce&lt;/a&gt; - we had 2nd row seats to the &lt;a href="http://www.bigheadtodd.com/"&gt;Big Head Todd&lt;/a&gt; concert at Red Rocks. We did our &lt;a href="http://raibledesigns.com/rd/entry/riding_to_red_rocks"&gt;annual ride&lt;/a&gt;, leaving my house around 4 and arriving 30 minutes before the show began. Upon arrival, Bruce's odometer showed 21 miles. 
&lt;/p&gt;
&lt;p&gt;The seats were awesome - 2nd row, just left of center. They were so close, it felt like a private show. In fact, I got a head-nod from Jeremy (keyboardist) because he could see my face in the crowd.
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm3.static.flickr.com/2446/3609197875_74b0c9b694.jpg" title="First Band" rel="lightbox[bhtm2009]"&gt;&lt;img src="http://farm3.static.flickr.com/2446/3609197875_74b0c9b694_t.jpg" width="100" height="75" alt="First Band" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3609/3609197909_1b40f5a00f.jpg" title="View of the crowd" rel="lightbox[bhtm2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3609/3609197909_1b40f5a00f_t.jpg" width="100" height="75" alt="View of the crowd" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3407/3609197993_f8df3afd48.jpg" title="Big Head Todd" rel="lightbox[bhtm2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3407/3609197993_f8df3afd48_t.jpg" width="100" height="75" alt="Big Head Todd" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3662/3610011518_ed567e1d06.jpg" title="Incredible" rel="lightbox[bhtm2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3662/3610011518_ed567e1d06_t.jpg" width="100" height="75" alt="Incredible" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;The show ended around midnight and we hopped on our bikes for the ride home. This time, it only took 1:40 (it took 3 hours for the trip out) and I was in bed by 2. 

&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://farm4.static.flickr.com/3333/3609198111_5f18a68db1.jpg" title="Halfway" rel="lightbox[bhtm2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3333/3609198111_5f18a68db1_t.jpg" width="100" height="75" alt="Halfway" class="picture" /&gt;&lt;/a&gt;
Sunday morning, I woke up at 7, looked up the &lt;a href="http://www.elephantrockride.com/"&gt;Elephant Rock&lt;/a&gt; start times and hit snooze for an hour.  The last start for the 25-mile off road ride was 9:30 and I left the starting gate at 9:28. I had a very enjoyable ride (temp was 65&amp;deg;F) and finished in 2.5 hours.&lt;/p&gt;
 &lt;p&gt;As you can imagine, I was pretty tired after 67 miles in 18 hours. I can't imagine what it'd be like to do 100 miles in a single day. Century riders are either impressive or crazy, I'm not sure which. &lt;img src="http://raibledesigns.com/images/smileys/wink.gif" class="smiley" alt=";-)" title=";-)" /&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=64017781 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/creating_a_facebook_style_autocomplete</guid><title>Creating a Facebook-style Autocomplete with GWT</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/creating_a_facebook_style_autocomplete</link><pubDate>Fri, 5 Jun 2009 07:05:10 -0600</pubDate><category>Java</category><category>facebook</category><category>autocomplete</category><category>jquery</category><category>gwt</category><category>gwt-autocomplete</category><category>linkedin</category><description>Have you used the "To:" widget on on Facebook or LinkedIn when composing a message? It's an autocompleter that looks up contact names and displays them as you type. It looks like a normal textbox (a.k.a. &amp;lt;input type="text"&amp;gt;), but wraps the contact name to allow you to easily delete it. Here's a screenshot of what Facebook's widget looks like.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;img src="http://farm3.static.flickr.com/2468/3595186177_5334fff971.jpg" width="500" height="233" alt="Facebook Autocomplete" /&gt;
&lt;/p&gt;
&lt;p&gt;Last week, I was asked to create a similar widget with GWT. After searching the web and &lt;a href="
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/627687a4b607ce02"&gt;not finding much&lt;/a&gt;, I decided to try writing my own. The best example I found on how to create this widget was from James Smith's &lt;a href="http://loopj.com/2009/04/25/jquery-plugin-tokenizing-autocomplete-text-entry/"&gt;Tokenizing Autocomplete jQuery Plugin&lt;/a&gt;. I used its &lt;a href="http://loopj.com/tokeninput/demo.html"&gt;demo&lt;/a&gt; to help me learn how the DOM changed after you selected a contact. 
&lt;/p&gt;
&lt;p&gt;GWT's &lt;a href="http://gwt.google.com/samples/Showcase/Showcase.html#CwSuggestBox"&gt;SelectBox&lt;/a&gt; allows you to easily create an autocompleter. However, &lt;a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=3044&amp;amp;can=5"&gt;it doesn't have support for multiple values&lt;/a&gt; (for example, a comma-delimited list). The good news is it's not difficult to add this functionality using &lt;a href="http://ljvjonok.blogspot.com/2008/10/gwt-suggestbox-how-to-make-multiple.html"&gt;Viktor Zaprudnev's HowTo&lt;/a&gt;. Another feature you might want in a SelectBox is to populate it with POJOs. &lt;a href="http://eggsylife.blogspot.com/2008/08/gwt-suggestbox-backed-by-dto-model.html"&gt;GWT SuggestBox backed by DTO Model&lt;/a&gt; is a good blog post that shows how to do this.&lt;/p&gt;
&lt;p&gt;Back to the Facebook Autocompleter. To demonstrate how to create this widget in GWT, I put together a simple application. You can &lt;a href="http://demo.raibledesigns.com/gwt-autocomplete"&gt;view the demo&lt;/a&gt; or &lt;a href="http://static.raibledesigns.com/downloads/gwt-autocomplete-1.0.zip"&gt;download it&lt;/a&gt;. The meat of this example is in an InputListWidget. After looking at the jQuery example, I learned the widget was a &amp;lt;div&amp;gt; with a unordered list (&amp;lt;ul&amp;gt;). It starts out looking like this:&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;ul class="token-input-list-facebook"&amp;gt;
    &amp;lt;li class="token-input-input-token-facebook"&amp;gt;
        &amp;lt;input type="text" style="outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;"/&amp;gt;
    &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/pre&gt;
&lt;p&gt;I did this in GWT using custom BulletList and ListItem widgets (contained in the download).&lt;/p&gt;
&lt;pre class="brush:java"&gt;
final BulletList list = new BulletList();
list.setStyleName("token-input-list-facebook");

final ListItem item = new ListItem();
item.setStyleName("token-input-input-token-facebook");

final TextBox itemBox = new TextBox();
itemBox.getElement().setAttribute("style", 
        "outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;");

final SuggestBox box = new SuggestBox(getSuggestions(), itemBox);
box.getElement().setId("suggestion_box");

item.add(box);
list.add(item);
&lt;/pre&gt;
&lt;p&gt;After tabbing off the input, I noticed that it was removed and replaced with a &amp;lt;p&amp;gt; around the value and a &amp;lt;span&amp;gt; to show the "x" to delete it. After adding a couple items, the HTML is as follows:&lt;/p&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;ul class="token-input-list-facebook"&amp;gt;
    &amp;lt;li class="token-input-token-facebook"&amp;gt;
        &amp;lt;p&amp;gt;What's New Scooby-Doo?&amp;lt;/p&amp;gt;
        &amp;lt;span class="token-input-delete-token-facebook"&amp;gt;x&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li class="token-input-token-facebook"&amp;gt;
        &amp;lt;p&amp;gt;Fear Factor&amp;lt;/p&amp;gt;
        &amp;lt;span class="token-input-delete-token-facebook"&amp;gt;x&amp;lt;/span&amp;gt;
     &amp;lt;/li&amp;gt;
     &amp;lt;li class="token-input-input-token-facebook"&amp;gt;
         &amp;lt;input type="text" style="outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;"/&amp;gt;
     &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/pre&gt;
&lt;p&gt;To do this, I created a &lt;code&gt;deselectItem()&lt;/code&gt; method that triggers the DOM transformation.
&lt;/p&gt;
&lt;pre class="brush:java"&gt;
private void deselectItem(final TextBox itemBox, final BulletList list) {
    if (itemBox.getValue() != null &amp;&amp; !"".equals(itemBox.getValue().trim())) {
        /** Change to the following structure:
         * &amp;lt;li class="token-input-token-facebook"&amp;gt;
         * &amp;lt;p&amp;gt;What's New Scooby-Doo?&amp;lt;/p&amp;gt;
         * &amp;lt;span class="token-input-delete-token-facebook"&amp;gt;x&amp;lt;/span&amp;gt;
         * &amp;lt;/li&amp;gt;
         */

        final ListItem displayItem = new ListItem();
        displayItem.setStyleName("token-input-token-facebook");
        Paragraph p = new Paragraph(itemBox.getValue());

        displayItem.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                displayItem.addStyleName("token-input-selected-token-facebook");
            }
        });

        Span span = new Span("x");
        span.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                list.remove(displayItem);
            }
        });

        displayItem.add(p);
        displayItem.add(span);
        
        list.insert(displayItem, list.getWidgetCount() - 1);
        itemBox.setValue("");
        itemBox.setFocus(true);
    }
}
&lt;/pre&gt;
&lt;p&gt;This method is called after selecting a new item from the SuggestBox:&lt;/p&gt;
&lt;pre class="brush:java"&gt;
box.addSelectionHandler(new SelectionHandler&lt;SuggestOracle.Suggestion&gt;() {
    public void onSelection(SelectionEvent selectionEvent) {
        deselectItem(itemBox, list);
    }
});
&lt;/pre&gt;
&lt;p&gt;I also added the ability for you to type in an e-mail address manually and to delete the previous item when you backspace from the input field. Here's the handler that calls &lt;code&gt;deselectItem()&lt;/code&gt; and allows deleting with backspace:&lt;/p&gt;
&lt;pre class="brush:java"&gt;
// this needs to be on the itemBox rather than box, or backspace will get executed twice
itemBox.addKeyDownHandler(new KeyDownHandler() {
    public void onKeyDown(KeyDownEvent event) {
        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
            // only allow manual entries with @ signs (assumed email addresses)
            if (itemBox.getValue().contains("@"))
                deselectItem(itemBox, list);
        }
        // handle backspace
        if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {
            if ("".equals(itemBox.getValue().trim())) {
                ListItem li = (ListItem) list.getWidget(list.getWidgetCount() - 2);
                Paragraph p = (Paragraph) li.getWidget(0);

                list.remove(li);
                itemBox.setFocus(true);
            }
        }
    }
});
&lt;/pre&gt;
&lt;p&gt;I'm happy with the results, and grateful for the &lt;a href="http://loopj.com/tokeninput/token-input-facebook.css"&gt;jQuery plugin's CSS&lt;/a&gt;. However, it still has one issue that I haven't been able to solve: I'm unable to click on a list item (to select it) and then delete it (with the backspace key). I believe this is because I'm unable to give focus to the list item. Here's the code that highlights the item and you can see the commented-out code that doesn't work.
&lt;/p&gt;
&lt;pre class="brush:java"&gt;
displayItem.addClickHandler(new ClickHandler() {
    public void onClick(ClickEvent clickEvent) {
        displayItem.addStyleName("token-input-selected-token-facebook");
    }
});

/** TODO: Figure out how to select item and allow deleting with backspace key
displayItem.addKeyDownHandler(new KeyDownHandler() {
    public void onKeyDown(KeyDownEvent event) {
        if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {
            list.remove(displayItem);
        }
    }
});
displayItem.addBlurHandler(new BlurHandler() {
    public void onBlur(BlurEvent blurEvent) {
        displayItem.removeStyleName("token-input-selected-token-facebook");
    }
});
*/
&lt;/pre&gt;
&lt;p&gt;If you know of a solution to this issue, please let me know. Feel free to use this widget and improve it as you see fit. I'd love to see this as a native widget in GWT. In the meantime, here's the &lt;a href="http://demo.raibledesigns.com/gwt-autocomplete"&gt;GWT Facebook-style Autocomplete demo&lt;/a&gt; and &lt;a href="http://static.raibledesigns.com/downloads/gwt-autocomplete-1.0.zip"&gt;code&lt;/a&gt;.&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=63929064&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=63929064&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=63929064 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/the_end_of_colorado_software</guid><title>The End of the Colorado Software Summit</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/the_end_of_colorado_software</link><pubDate>Thu, 4 Jun 2009 14:39:20 -0600</pubDate><category>Java</category><category>softwaresummit</category><description>It looks like the &lt;a href="http://softwaresummit.com"&gt;Colorado Software Summit&lt;/a&gt; has come to an end.&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
To Our Friends and Supporters,
&lt;br/&gt;&lt;br/&gt;
In these challenging economic times, business has slowed, many companies have had to resort to layoffs and/or closures, and everyone has been tightening their belts. Unfortunately, Colorado Software Summit has not been immune to this downturn. As have so many companies and individuals, we too have experienced a severe decline in our business, and as a result we are not able to continue producing this annual conference.
&lt;br/&gt;&lt;br/&gt;
This year would have been our 18th conference, and we had planned to continue through our 20th in 2011, but instead we must end it now. [&lt;a href="http://softwaresummit.com/"&gt;Read More&lt;/a&gt;]
&lt;/p&gt;
&lt;p&gt;I first attended this conference in &lt;a href="http://raibledesigns.com/rd/entry/heading_to_the_summit"&gt;October 2005&lt;/a&gt;. I enjoyed it so much, I returned again in &lt;a href="http://raibledesigns.com/rd/date/20061023"&gt;2006&lt;/a&gt;, &lt;a href="http://raibledesigns.com/rd/date/20071023"&gt;2007&lt;/a&gt; and &lt;a href="http://raibledesigns.com/rd/entry/going_to_colorado_software_summit"&gt;2008&lt;/a&gt;. As I &lt;a href="http://raibledesigns.com/rd/entry/the_colorado_software_summit_and"&gt;mentioned last year&lt;/a&gt;, this was my favorite conference.
&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
The reason I like it so much is because it's an annual gathering (this will be my 4th year) with friends and it's somewhat like a vacation, except you get to learn a lot.
&lt;/p&gt;
&lt;p&gt;While I'm sad to see it go, I completely understand Wayne and Peggy's decision. If you ever attended this conference, I encourage you to join the &lt;a href="http://www.linkedin.com/groups?gid=1083347"&gt;Colorado Software Summit LinkedIn Group&lt;/a&gt;. To see all my posts from the talks I attended at this conference, see my &lt;a href="http://raibledesigns.com/rd/tags/softwaresummit"&gt;softwaresummit&lt;/a&gt;-tagged entries.
&lt;/p&gt;
&lt;p&gt;
To Wayne and Peggy: thanks for all the great memories and for putting together such an excellent conference. Cheers to you both!&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=63929063 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/my_eye_surgery_experience</guid><title>My Eye Surgery Experience</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/my_eye_surgery_experience</link><pubDate>Wed, 3 Jun 2009 00:46:18 -0600</pubDate><category>General</category><category>health</category><category>prk</category><category>eyesight</category><category>eye</category><category>eyesurgery</category><category>photorefractive_keratectomy</category><category>lasik</category><category>tlc</category><category>vision</category><category>lasereyesurgery</category><description>On May 7, I visited my local &lt;a href="http://www.tlcvision.com/"&gt;TLC Laser Eye Center&lt;/a&gt; for eye surgery. I began looking into eye surgery way back in December. At that time, I wore my glasses for a week, then waltzed into my local TLC and tried to get it done the next day. I quickly found out that 1) it wasn't possible for 2 weeks and 2) I couldn't ski for a couple weeks afterward. Since we were in the midst of a great ski season, I decided to schedule it for May.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.aucklandeye.co.nz/index.asp?PageID=2145866567"&gt;&lt;img src="http://tbn2.google.com/images?q=tbn:0igiNq5dr67w7M:http://www.aucklandeye.co.nz/images/Prk_assembled_procedure.jpg" alt="PRK" width="116" height="80" class="picture" /&gt;&lt;/a&gt;
I failed the LASIK-eligibility and learned I'd have to have &lt;a href="http://en.wikipedia.org/wiki/Photorefractive_keratectomy"&gt;PRK&lt;/a&gt; instead. The scars on my right eyeball caused me to fail. I received these scars as a boy when a friend and I blew up a &lt;a href="http://en.wikipedia.org/wiki/.45-70"&gt;.45-70&lt;/a&gt; bullet with a nail and sledgehammer. I was the one holding the nail and couldn't see for the next 3 days.
&lt;/p&gt;
&lt;p&gt;
In a nutshell: with LASIK they cut a flap, lift it up and shoot the laser under it. It heals quickly and is relatively painless. PRK has been around since before LASIK. With PRK, they seem to &lt;em&gt;shave your eyeball&lt;/em&gt; and then shoot a laser into it. PRK takes a lot longer to heal, but the results are often as good or better than LASIK. Wikipedia has a more technical &lt;a href="http://en.wikipedia.org/wiki/Photorefractive_keratectomy#PRK_versus_LASIK"&gt;PRK vs. LASIK&lt;/a&gt; reference.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Procedure&lt;/strong&gt;&lt;br/&gt;
My mom flew into town for my surgery and drove me to TLC's office on that Thursday morning. It took 2 hours to prep for surgery, with most of the time spent sitting around and talking to my mom. Finally, they asked her to sit in the lobby and took me back to a waiting area. When I walked in the room, there were 2 other patients with surgery gear (funny hat and booties) and masks. They were leaning back, looking at the ceiling with their masks on and eyes closed. I quickly became the 3rd person who looked like this. Right before they started putting drops in my eyes, I remember being terrified that I might never see daylight again. At the very least, I thought I wouldn't see anything but black for the next 3 days.
&lt;/p&gt;
&lt;p&gt;Right before they called me in, the previous patient walked out and muttered "Damn, that burns." Believe me, this is &lt;em&gt;not&lt;/em&gt; what you want to hear right before it's your turn. I was led into the operating room, sat down and received numbing drops in my eyes. Less than a minute later, I was led over to the operating table. 
&lt;/p&gt;
&lt;p&gt;
The rest of the procedure lasted less than 5 minutes. They taped my left eye shut and told me to stare at the red light with my right eye. At this point, they used some contraption to shave my eyeball. It was slightly painful, similar to the mild pain you feel when getting a cavity drilled with Novocaine. After each stroke, the world would ripple like a pebble thrown into in a lake. After 10 strokes or so, they shot a laser into my eye for around 20 seconds. You don't actually &lt;em&gt;see&lt;/em&gt; the laser (the red light looks the same), but you can smell your eyeball burning. Each eye only took a few minutes. My mom was able to watch the entire surgery on a television on the other side of a glass wall.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The Recovery&lt;/strong&gt;&lt;br/&gt;
I was surprised to discover I was immediately able to open my eyes and see normally. Of course, my eyes felt heavy, so I didn't open them wide nor feel like I could. I was led back to the waiting room where I was given a Valium and sent home. I put my sunglasses on when we left and kept my eyes closed for the 5-minute drive home. After arriving at my house, I immediately downed some Tylenol PM and went to bed. It was hard to fall asleep and my eyes began tearing up. There was a dull pain in my eyes that kept the tears flowing for most of the afternoon. It took me 2 hours to fall asleep and I remember my eyes causing my nose to get stuffed up from all the tears.
&lt;/p&gt;
&lt;p&gt;When I woke up that evening, everything was blurry, but I was able to open my eyes and see better than I had previously w/o glasses. I didn't expect anything in the form of good vision and was mostly pre-occupied with trying to stop the pain (which wasn't &lt;em&gt;terrible&lt;/em&gt;, but definitely present). I was prescribed &lt;a href="http://en.wikipedia.org/wiki/Vicodin"&gt;Vicodin&lt;/a&gt; and started taking it on a regular basis. I was completely unable to watch TV at all that night. Viewing the computer screen was unthinkable.&lt;/p&gt;
&lt;p&gt;The next morning, my vision was a lot better as evidenced by the &lt;a href="http://twitter.com/mraible/status/1738496118" title="I guess you can say I'm recovering well if I can tweet this."&gt;tweet from my iPhone&lt;/a&gt;. Shortly after, my mom drove me to my eye doctor's office for a 1-day checkup. The &lt;a href="http://twitter.com/mraible/status/1739313338" title="Just got back from eye doctor. 20/20 in right eye, not as good in left eye. Apparently better than normal results for PRK this early."&gt;results&lt;/a&gt; were surprising.
&lt;/p&gt;
&lt;p&gt;Friday night was one of the &lt;a href="http://twitter.com/mraible/status/1742765806" title="Feels like I have sand in my eyes. Hard to keep them open, hurts to close. Youch!"&gt;most painful&lt;/a&gt;. Saturday wasn't very painful, but my eyesight was very blurry. That afternoon, it was hard to keep my eyes open. Every time I tried to open them, I felt like I had to sneeze. Fortunately, I was able to watch the &lt;a href="http://twitter.com/mraible/status/1756648655" title="Eyesight still blurry; a lot less pain today. As much as it hurt, I did get to watch a fair bit of the Nuggets; loved Melo's winning shot."&gt;Nuggets game&lt;/a&gt;. I couldn't see players' numbers, but I was able to see Melo's last-second 3-pointer to win.
&lt;/p&gt;
&lt;p&gt;On Monday, I was able to drive to TLC for my 3-day checkup. Things were definitely blurry, but I didn't feel like it was dangerous for me to be behind the wheel. I was able to work on Monday, but I also had to increase my font sizes to 36pt and used a 30" monitor all day. OS X's Universal Access -&gt; Zoom feature came in awful handy. That night, TV was a LOT clearer than the previous night, but it was still fuzzy.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What's it like now?&lt;/strong&gt;&lt;br/&gt;
It's been almost 4 weeks and I'm very glad that I had the surgery done. I haven't felt any pain since the Sunday after surgery and I haven't had any issues with dryness. My vision does fluctuate from day-to-day. Some days I feel like I have super-hero vision and other days there's a halo around objects beyond 10 feet. According to my doctor, fluctuations are expected to continue for 6 months. I don't mind since it never gets bad enough to seem strange.&lt;/p&gt;
&lt;p&gt;Now I enjoy not having to worry about glasses or contacts when traveling. I love waking up every morning and not having to do anything to improve my vision. I feel like I have more freedom in my life. Getting eye surgery is definitely one of the best things I've ever done.
&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=63929062&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=63929062&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=63929062 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/ryan_and_breanne_s_wedding</guid><title>Ryan and Breanne's Wedding in Playa del Carmen</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/ryan_and_breanne_s_wedding</link><pubDate>Mon, 1 Jun 2009 21:53:44 -0600</pubDate><category>General</category><category>cancun</category><category>destinationwedding</category><category>marriage</category><category>playadelcarmen</category><category>mexico</category><category>travel</category><category>wedding</category><category>vacation</category><description>Despite the warnings about &lt;a href="http://fishbowl.pastiche.org/2009/04/28/swine_flu_faq/"&gt;Swine Flu&lt;/a&gt;, two weeks ago I flew to Cancun for my good friends' Ryan and Breanne's wedding. The night before leaving, I &lt;a href="http://twitter.com/mraible/status/1858047737"&gt;didn't get much sleep&lt;/a&gt;, but managed to get a good nap on the plane. We arrived in Cancun around 2:00pm and begin enjoying the beautiful weather of Mexico. We took a shuttle from CUN to the all-inclusive &lt;a href="http://www.iberostar.com/EN/Riviera-Maya-hotels/Iberostar-Paraiso-Maya_3_76.html"&gt;Paraiso Maya&lt;/a&gt;. Thanks to Swine Flu, we got upgraded twice and ended up paying $110/night for a place that's normally $450/night. &lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm3.static.flickr.com/2438/3580780588_0b3376927a.jpg" title="Landing in Cancun" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm3.static.flickr.com/2438/3580780588_0b3376927a_t.jpg" width="100" height="75" alt="Landing in Cancun" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3568/3580780696_75ca362c2c.jpg" title="Navs and Colin" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3568/3580780696_75ca362c2c_t.jpg" width="100" height="75" alt="Navs and Colin" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3649/3580780966_5ce62f5457.jpg" title="Paraiso Maya" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3649/3580780966_5ce62f5457_t.jpg" width="100" height="75" alt="Paraiso Maya" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3352/3579971375_b70c67c6ac.jpg" title="Pool at Paraiso Maya"&gt;&lt;img src="http://farm4.static.flickr.com/3352/3579971375_b70c67c6ac_t.jpg" width="100" height="75" alt="Pool at Paraiso Maya" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;My two favorite parts of the trip were 1) the people and 2) the place. There was around 15 of us, many of us good friends since college. We stayed at the Paraiso Maya, which was a very nice hotel with beautiful pools, elaborate buffets and awesome beach access. We had a ton of fun at the pool bar, playing water basketball, jet skiing and playing beach volleyball. The dinners at the Steakhouses were great and The Galaxy (Star War themed) club created many good memories. It's great to travel with that many people, especially when the beer is flowing for (what seems like) free and you're partying with old friends.
 &lt;/p&gt;
&lt;p&gt;My third favorite part of the trip was watching the &lt;a href="http://nuggets.com"&gt;Nuggets&lt;/a&gt; vs. Lakers games. We watched 3 games in the resort's "Sports Bar" and had a blast doing it. Since we had a couple Lakers' fans in the mix, it made things interesting.
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3653/3580782968_9fc2c33fcd.jpg" title="Wave Pool" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3653/3580782968_9fc2c33fcd_t.jpg" width="100" height="75" alt="Wave Pool" style="border: 1px solid black"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3662/3579970835_40e397088f.jpg" title="Water Basketball" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3662/3579970835_40e397088f_t.jpg" width="100" height="75" alt="Water Basketball" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3648/3579972225_d24d92ee28.jpg" title="Beach Volleyball" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3648/3579972225_d24d92ee28_t.jpg" width="100" height="75" alt="Beach Volleyball" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3617/3579972403_8b7c2d75c0.jpg" title="Breanne and Jenna" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3617/3579972403_8b7c2d75c0_t.jpg" width="100" height="75" alt="Breanne and Jenna" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;We spent 3 days at the pool and on the beach before the wedding happened on Saturday. It was a very cool ceremony and enjoyed a &lt;a href="http://en.wikipedia.org/wiki/Mariachi"&gt;Mariachi band&lt;/a&gt; for a good hour afterward. I've definitely become a big fan of &lt;a href="http://raibledesigns.com/rd/entry/costa_rica_was_awesome"&gt;beach&lt;/a&gt; &lt;a href="http://raibledesigns.com/rd/entry/jason_and_holly_s_wedding"&gt;weddings&lt;/a&gt; in the last 6 months. &lt;img src="http://raibledesigns.com/images/smileys/wink.gif" class="smiley" alt=";-)" title=";-)" /&gt;
&lt;/p&gt;

&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3618/3580803902_449464cf49.jpg" title="Ready for the Ceremony" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3618/3580803902_449464cf49_t.jpg" width="100" height="75" alt="Ready for the Ceremony" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3644/3579992115_05c0cb7b7f.jpg" title="Vows" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3644/3579992115_05c0cb7b7f_t.jpg" width="100" height="75" alt="Vows" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3153/3580823360_3e2e997894.jpg" title="Mariachi Band" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3153/3580823360_3e2e997894_t.jpg" width="100" height="75" alt="Mariachi Band" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3374/3580011379_fa403528cb.jpg" title="Mr. and Mrs. Johnson" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3374/3580011379_fa403528cb_t.jpg" width="100" height="75" alt="Mr. and Mrs. Johnson" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;


&lt;/p&gt;
&lt;p&gt;After 5 days in Playa del Carmen, my buddy (Kevin Navarro) and I spent 2 days at &lt;a href="http://www.starwoodhotels.com/westin/property/overview/index.html?propertyID=1092"&gt;The Westin&lt;/a&gt; in Cancun. This was a &lt;em&gt;very&lt;/em&gt; nice resort; especially since we had an ocean-front room.
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3318/3580845054_52d7e6b2bd.jpg" title="View from room in Cancun" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3318/3580845054_52d7e6b2bd_t.jpg" width="100" height="75" alt="View from room in Cancun" style="border: 1px solid black"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3407/3580032391_fb0326e617.jpg" title="Poolside" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3407/3580032391_fb0326e617_t.jpg" width="100" height="75" alt="Poolside" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm3.static.flickr.com/2426/3580845382_eb28850032.jpg" title="Beach" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm3.static.flickr.com/2426/3580845382_eb28850032_t.jpg" width="100" height="75" alt="Beach" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3601/3580845562_a89d289e81.jpg" title="Beach from Room" rel="lightbox[mexico2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3601/3580845562_a89d289e81_t.jpg" width="100" height="75" alt="Beach from Room"  style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;/p&gt; 
&lt;p&gt;I had so much fun on this trip, I've been inspired to learn Spanish. I don't know when I'll carve out the time to do it, but I know I'll return to Mexico several times, so the sooner the better.
&lt;/p&gt;
&lt;p&gt;
To see all my pictures from this trip, see my &lt;a href="http://www.flickr.com/photos/mraible/collections/72157619028951930/"&gt;Mexico 2009 Collection&lt;/a&gt; on &lt;a href="http://flickr.com"&gt;Flickr&lt;/a&gt;.&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=63720614 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/life_update_new_treehouse_new</guid><title>Life Update: New Treehouse, New Kittens and More</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/life_update_new_treehouse_new</link><pubDate>Wed, 6 May 2009 07:19:59 -0600</pubDate><category>General</category><category>life</category><category>kittens</category><category>abbie</category><category>treehouse</category><category>jack</category><category>eyesurgery</category><category>prk</category><category>mexico</category><category>cancun</category><category>appfuse</category><description>It's been awhile since I wrote a life update post so here you go. After returning from &lt;a href="http://raibledesigns.com/rd/entry/jason_and_holly_s_wedding"&gt;Jason and Holly's Wedding&lt;/a&gt; in Florida, I took the next week off to "catch up on life". Having a vacation at home with no packing and lots of time to wipe my "to do" list clean was great. Not only that, but the weather was beautiful all week. If you ever get a chance to take a "catch up on life" vacation, I highly recommend it.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Treehouse&lt;/strong&gt;&lt;br/&gt;
I started out the week by doing something I've been telling the kids I'd do for the last year: building a treehouse. I used &lt;a href="http://www.ronhazelton.com/archives/howto/treehouse_construction.shtm"&gt;this tutorial&lt;/a&gt; as a guide for the "foundation" and had a lot of fun doing it. The best part was discovering my Dad had stocked my garage with many tools over the last couple years.  I had to make several runs to Home Depot and Ace Hardware for building supplies, but rarely had to buy any new tools. My Dad has been a carpenter for over 30 years (he used to do it for a living in Montana). I was pleasantly surprised to discover some of his skills have rubbed off on me. We still need to build the structure on top of the platform, but everyone is happy with the results so far.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3549/3471564772_1f9c19a38a.jpg" title="Day 1 - Sunset" rel="lightbox[lifeupdatespring2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3549/3471564772_1f9c19a38a_t.jpg" width="100" height="75" alt="Day 1 - Sunset" style="border: 1px solid black"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3593/3470750609_84bc33216b.jpg" title="Day 2 - Bolting frame in place" rel="lightbox[lifeupdatespring2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3593/3470750609_84bc33216b_t.jpg" width="100" height="75" alt="Day 2 - Bolting frame in place" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3656/3471565132_7a5e4ebdb2.jpg" title="Day 3 - They love it!" rel="lightbox[lifeupdatespring2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3656/3471565132_7a5e4ebdb2_t.jpg" width="100" height="75" alt="Day 3 - They love it!" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3545/3470751035_d016beb0d9.jpg" title="Day 4 - Floor completed" rel="lightbox[lifeupdatespring2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3545/3470751035_d016beb0d9_t.jpg" width="100" height="75" alt="Day 4 - Floor completed" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AppFuse&lt;/strong&gt;&lt;br/&gt;
After finishing Phase 1 of the treehouse, I started working on the next version of AppFuse. I've made good progress so far:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Archetypes now include all the source from web modules.&lt;/li&gt;
&lt;li&gt;Archetypes are now created using archetype:create-from-project, making things easier to maintain.&lt;/li&gt;
&lt;li&gt;Switched Cargo from downloaded Tomcat to embedded Jetty, allowing for faster builds.&lt;/li&gt;
&lt;li&gt;Upgraded to Struts 2.1.6 and Tapestry 5.0.18.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There's still &lt;a href="http://issues.appfuse.org/secure/IssueNavigator.jspa?mode=hide&amp;amp;requestId=10160"&gt;lots of open issues&lt;/a&gt;, but I believe there's a lot of value in &lt;em&gt;starting&lt;/em&gt; the "working on the next version" process. With the way things are shaping up, I'm considering bumping the version to 2.5 or 3.0 instead of 2.1. 3.0 might be a little ambitious, but there are going to be a lot of improvements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Kittens&lt;/strong&gt;&lt;br/&gt;
Last weekend, I decided it was time to create some happy kids and get some pets in my house. On Saturday, we set out on a quest to find some kittens. We visited a couple shelters and a couple pet stores, but came home empty handed. We didn't look Sunday because we had &lt;a href="http://twitter.com/mraible/status/1687500847"&gt;more important things to do&lt;/a&gt;. On Monday, we hit up &lt;a href="http://denver.craigslist.org/search/pet?query=kittens"&gt;craigslist&lt;/a&gt; and found our kittens with a family in Thornton. Upon arrival, I figured they'd be good since the family had a 6-year old, a 4-year old and a 1-year old that was carrying a kitten around by the tail. At least their new home is slightly less chaotic than their last one. &lt;img src="http://raibledesigns.com/images/smileys/wink.gif" class="smiley" alt=";-)" title=";-)" /&gt;&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3360/3505899171_3cb4e849b1.jpg" title="Jack and Olivia" rel="lightbox[lifeupdatespring2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3360/3505899171_3cb4e849b1_m.jpg" width="240" height="180" alt="Jack and Olivia" style="border: 1px solid black"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3562/3506709142_21fa103252.jpg" title="Abbie and Mittens" rel="lightbox[lifeupdatespring2009]"&gt;&lt;img src="http://farm4.static.flickr.com/3562/3506709142_21fa103252_m.jpg" width="240" height="180" alt="Abbie and Mittens" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Eye Surgery&lt;/strong&gt;&lt;br/&gt;
Today is my last day wearing glasses. Tomorrow morning, I'm scheduled to receive &lt;a href="http://www.jeffsandquist.com/recovering-from-prk-laser-eye-surgery/"&gt;PRK eye surgery&lt;/a&gt; at &lt;a href="http://lasik.com/"&gt;TLC Laser Eye Center&lt;/a&gt;. I'm nervous about the procedure and dreading the recovery. My mom is flying in tonight to assist me while I'm blind and in pain, so hopefully it won't be too bad. A co-worker has lots of books on tape that I'm borrowing to pass the time.
&lt;/p&gt;
&lt;p&gt;My life is showing no signs of slowing down anytime soon, but I will have lots of opportunities to relax. In two weeks, I'm heading to Cancun for a friend's wedding. Having a week on the sunny beaches of Mexico is always fun. My current contract expires a couple days after my return. I'm currently negotiating with a few potential clients and hope to have my summer work plans solidified before leaving for Mexico. More than anything, I'm looking forward to taking the entire month of July off and spending it at our cabin in Montana. My Dad is moving up there to work on The New Cabin and there's nothing I'd rather do than help him out. &lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=62832837&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=62832837&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=62832837 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/ajax_framework_analysis_results</guid><title>Ajax Framework Analysis Results</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/ajax_framework_analysis_results</link><pubDate>Thu, 23 Apr 2009 20:34:44 -0600</pubDate><category>Java</category><category>jquery</category><category>gxt</category><category>ajax</category><category>java</category><category>smartgwt</category><category>extjs</category><category>gwt</category><category>dojo</category><category>yui</category><description>Way back in January, I wrote about how my colleagues and I were &lt;a href="http://raibledesigns.com/rd/entry/choosing_an_ajax_framework"&gt;evaluating Ajax frameworks&lt;/a&gt; to build a SOFEA-style architecture. To make our choice, we used the following process:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Choose a short list of frameworks to prototype with.&lt;/li&gt;
&lt;li&gt;Create an application prototype with each framework.&lt;/li&gt;
&lt;li&gt;Document findings and create a matrix with important criteria.&lt;/li&gt;
&lt;li&gt;Create presentation to summarize document.&lt;/li&gt;
&lt;li&gt;Deliver document, presentation and recommendation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When I wrote that entry, we had just finished step 2 and were starting step 3. I first wrote this blog post a week later, when we delivered step 5. Here is the comparison and conclusion sections of the analysis document we composed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Framework Comparison&lt;/strong&gt;&lt;br/&gt;
In order to evaluate the different frameworks against important criteria, we created a matrix with weights and ranks for each framework. This matrix shows how our weighting and rankings lead us to the winner for our project.  You can &lt;a href="http://spreadsheets.google.com/ccc?key=p2SLd279MTmShLQdCjfi0OQ&amp;hl=en"&gt;view this matrix online&lt;/a&gt; or see below for a summary.
&lt;/p&gt;

&lt;iframe width='520' height='500' frameborder='0' src='http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;output=html&amp;gid=0&amp;single=true&amp;widget=true' style='margin: 0 auto'&gt;&lt;/iframe&gt;

&lt;p style="text-align: left"&gt;
&lt;strong&gt;Note:&lt;/strong&gt; Criteria whose values were identical across all candidates were weighted at zero. 
Charting capability was weighted at zero b/c we decided to use Flash for this.
&lt;/p&gt;

&lt;p&gt;This matrix indicates that &lt;strong&gt;GWT&lt;/strong&gt; is the best candidate for our team to develop SOFEA-style applications with.
In addition to the matrix, below are graphs that illustrate interesting (and possibly meaningless) statistics about each project. 
&lt;p style="text-align: center"&gt;
&lt;img src="http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=1&amp;amp;output=image" width="320" alt="Number of Committers"/&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;!--img src="http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=2&amp;amp;output=image" width="320" alt="Mailing List Traffic"/&gt;
&lt;br/&gt;&lt;br/--&gt;
&lt;img src="http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=3&amp;amp;output=image" width="320" alt="Books on Amazon"/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br/&gt;

After working with the various frameworks, we believe that all the frameworks were very good and could be used to write applications with. If all weights are equal, these frameworks were almost even when compared against our evaluation criteria. The graph below illustrates this. 
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;img src="http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=4&amp;amp;output=image" width="320" alt="Ranking with equal criteria weights"/&gt;
&lt;/p&gt;
&lt;p&gt;Even after applying the weighted criteria, the evenness doesn't change a whole lot. &lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;img src="http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=5&amp;amp;output=image" width="320" alt="Ranking with weighted criteria" /&gt;
&lt;/p&gt;
&lt;p&gt;
Without considering the even or weighted criteria, we believe the decision all comes down to what the developers on the project feel they will be most comfortable with. If you're developing with Dojo or YUI, chances are you're &lt;em&gt;dressing up&lt;/em&gt; existing HTML and possibly using &lt;a href="http://www.alistapart.com/articles/understandingprogressiveenhancement"&gt;progressive enhancement&lt;/a&gt; to add more rich functionality. On the other hand, Ext JS and GWT are similar to Swing programming where you build the UI with code (JavaScript for Ext JS, Java for GWT).
&lt;/p&gt;
&lt;p&gt;
The tools available for JavaScript development have gotten increasingly better in recent years. IntelliJ IDEA has a &lt;a href="http://www.jetbrains.com/idea/features/javascript_editor.html"&gt;JavaScript Editor&lt;/a&gt; that provides many of the same features as its Java editor. &lt;a href="http://www.aptana.com/studio"&gt;Aptana Studio&lt;/a&gt; also has excellent support for authoring and debugging JavaScript. However, we believe the Java debugging and authoring support in IDEs is much better. Furthermore, we are more familiar with organizing code in Java projects and feel more comfortable in this development environment. 
&lt;/p&gt;
&lt;p&gt;
Based on this evaluation, we believe that GWT is the best framework for our team to develop SOFEA-style applications with. 

&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flash Forward to Today...&lt;/strong&gt;&lt;br/&gt;
The core GWT library from Google doesn't have a whole lot of widgets, nor do they look
good out-of-the-box.  So early on, we experimented with two alternative implementations
that continue to leverage GWT concepts and tools:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://extjs.com/products/gxt"&gt;GXT&lt;/a&gt;: a GWT version of Ext JS&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/smartgwt"&gt;SmartGWT&lt;/a&gt;: a GWT version of SmartClient&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Unfortunately, over the past few months, we've found that both of these implementations are too heavy for our requirements, mostly because of the file size of the generated JavaScript code. For example, a feature I wrote generated a 275K *.cache.html file using GXT. After determining that was too slow to give users the initial "pop", I re-wrote it &lt;em&gt;without&lt;/em&gt; GXT. After a day, we had an application with *.cache.html files of 133K. Yes, that's over a 50% reduction in size!&lt;a href="http://raibledesigns.com/rd/entry/ajax_framework_analysis_results#footnote-gxtmvc"&gt;*&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Because of these findings, we are proceeding with the core GWT library from Google and adding in new components as needed.
It is cool to know you can make a UI "pop" with GWT, as long as you stick to the core - close-to-the-metal - components. For those applications that can afford an initial "loading..." state, I'd definitely recommend looking at GXT and SmartGWT.
&lt;/p&gt;
&lt;p style="font-size: 90%"&gt;&lt;a name="footnote-gxtmvc"&gt;*&lt;/a&gt; To make refactoring easier, I copied &lt;a href="http://raibledesigns.com/rd/entry/gxt_s_mvc_framework"&gt;GXT MVC&lt;/a&gt; into our source tree and modified all imports.&lt;/p&gt;
&lt;p&gt;















&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=62317113 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/jason_and_holly_s_wedding</guid><title>Jason and Holly's Wedding was a blast!</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/jason_and_holly_s_wedding</link><pubDate>Tue, 21 Apr 2009 09:53:54 -0600</pubDate><category>General</category><category>travel</category><category>westpalmbeach</category><category>friends</category><category>family</category><category>abbie</category><category>florida</category><category>jack</category><category>wedding</category><category>beach</category><description>This past weekend, I experienced an incredible 4 days in West Palm Beach, Florida. When Julie and I got married there in April 2000, we had so much fun that we always wanted to do it again. We had a lot of good friends and family fly in for the wedding. If you've ever experienced a beach holiday with many good friends, you'll know what I'm talking about. Julie is Holly's sister and Jason (her new husband) is one of my fraternity brothers. That means I knew both sides of the wedding party and it very much resembled the reunion we always wanted.&lt;/p&gt;
&lt;p&gt;I flew down on Thursday morning after a &lt;a href="http://twitter.com/mraible/status/1534664829"&gt;little bit of oversleeping&lt;/a&gt;. Because I flew into Orlando, I had to rent a car and drive 2 hours to West Palm.  This wasn't so bad since I got hooked up with a convertible and it was a beautiful 80&amp;deg;F on the drive. That night, I picked up Abbie and Jack from "Grammy's" house and they spent the night with me in my hotel.&lt;/p&gt;
&lt;p&gt;The next morning, we woke up and headed to &lt;a href="http://www.sailfishmarina.com/"&gt;Sailfish&lt;/a&gt; for a ride on a friend's boat. After a couple hours on the intercostal, we played in the pool, enjoyed the sun and started getting ready for the Rehearsal Dinner.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3620/3461902608_e81e4e0f95.jpg" title="Jack and Uncle Jason" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3620/3461902608_e81e4e0f95_t.jpg" width="100" height="75" alt="Jack and Uncle Jason" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3613/3461087705_536c853a65.jpg" title="The Hook" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3613/3461087705_536c853a65_t.jpg" width="100" height="75" alt="The Hook" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3480/3461087737_0f81b80e35.jpg" title="Kids are ready!" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3480/3461087737_0f81b80e35_t.jpg" width="100" height="75" alt="Kids are ready!" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;

&lt;a href="http://farm4.static.flickr.com/3607/3461902696_5d91ae0b06.jpg" title="Abbie and Jack on The Hook" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3607/3461902696_5d91ae0b06_t.jpg" width="100" height="75" alt="Abbie and Jack on The Hook" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3510/3461902732_1acf69afee.jpg" title="Crazy Abbie" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3510/3461902732_1acf69afee_t.jpg" width="100" height="75" alt="Crazy Abbie" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3525/3461902754_f0bbfb0acf.jpg" title="Captain Jack" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3525/3461902754_f0bbfb0acf_t.jpg" width="100" height="75" alt="Captain Jack" style="border: 1px solid black; margin-left: 10px" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;During the Rehearsal Dinner, a friend (Navarro) and I were bartenders while Abbie was in charge of making sure everyone's drinks were full. Below are some of my favorite pictures from Friday night.
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3596/3461903020_3def9a02fb.jpg" title="The Bride-To-Be" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3596/3461903020_3def9a02fb_t.jpg" width="100" height="75" alt="The Bride-To-Be" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3506/3461090669_6a7f8ea4fc.jpg" title="The Crew" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3506/3461090669_6a7f8ea4fc_t.jpg" width="100" height="75" alt="The Crew" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3551/3461091113_32c91972ea.jpg" title="Julie, Holly and Jack" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3551/3461091113_32c91972ea_t.jpg" width="100" height="75" alt="Julie, Holly and Jack" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;

&lt;a href="http://farm4.static.flickr.com/3510/3461094791_8476b34c33.jpg" title="Daddy and Jack" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3510/3461094791_8476b34c33_t.jpg" width="100" height="75" alt="Daddy and Jack" style="border: 1px solid black"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3537/3461910994_8af0aaacfd.jpg" title="Crazy Kids" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3537/3461910994_8af0aaacfd_t.jpg" width="100" height="75" alt="Crazy Kids" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3565/3461911848_2818619d57.jpg" title="Give me back that wine opener!" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3565/3461911848_2818619d57_t.jpg" width="100" height="75" alt="Give me back that wine opener!" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;After the rehearsal dinner, the party crowd headed to &lt;a href="http://www.yelp.com/biz/cruzan-rum-bar-north-palm-beach"&gt;Rum Bar&lt;/a&gt; and had lots of laughs and played many games of "hook". On the wedding day (Saturday), we took another boat ride, hung out on the beach and enjoyed a beautiful ceremony on the beach.
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3587/3461099643_273bb5b404.jpg" title="Jack the ringbearer" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3587/3461099643_273bb5b404_t.jpg" width="100" height="75" alt="Jack the ringbearer" style="border: 1px solid black" /&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3574/3461099973_2815a7e291.jpg" title="Flower Girls" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3574/3461099973_2815a7e291_t.jpg" width="100" height="75" alt="Flower Girls" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;

&lt;a href="http://farm4.static.flickr.com/3602/3461915178_4e9dfaf11b.jpg" title="Awesome Wedding" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3602/3461915178_4e9dfaf11b_t.jpg" width="100" height="75" alt="Awesome Wedding" style="border: 1px solid black; margin-left: 10px"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;The rest of the night was spent dancing and enjoying everyone's company. The party didn't end that night though. Sunday, Holly and Julie's mom had a brunch at her house where we all laid by the pool, played with the kids and sipped on many cold drinks. At sunset, we walked down to the beach so Mr. and Mrs. Harris could get some sand from their ceremony location.
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://farm4.static.flickr.com/3545/3461916124_11582cee7c.jpg" title="Mr. and Mrs. Harris" rel="lightbox[jasonandhollyswedding]"&gt;&lt;img src="http://farm4.static.flickr.com/3545/3461916124_11582cee7c_m.jpg" width="240" height="180" alt="Mr. and Mrs. Harris" style="border: 1px solid black"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;It was a spectacular weekend with lots of good friends and a ton of great memories. Congratulations Jason and Holly!&lt;/p&gt;
&lt;p&gt;For more pictures, see &lt;a href="http://www.flickr.com/photos/mraible/sets/72157617023261045/"&gt;Flickr&lt;/a&gt; or &lt;a href="http://www.facebook.com/album.php?aid=88589&amp;amp;id=571296711&amp;amp;l=bbc7258898"&gt;Facebook&lt;/a&gt;.&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=62317112&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=62317112&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=62317112 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/my_drunk_on_software_interview</guid><title>My Drunk on Software Interview</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/my_drunk_on_software_interview</link><pubDate>Sun, 5 Apr 2009 22:23:57 -0600</pubDate><category>Java</category><category>sofea</category><category>ajax</category><category>java</category><category>interview</category><category>drunkonsoftware</category><category>flex</category><description>Back in February, I met up with &lt;a href="http://www.jamesward.com/blog/"&gt;James Ward&lt;/a&gt; and &lt;a href="http://ectropic.com/wordpress/"&gt;Jon Rose&lt;/a&gt; for a &lt;a href="http://www.drunkonsoftware.com/2009/04/05/episode-11-matt-raible/"&gt;Drunk on Software interview&lt;/a&gt;. We enjoyed some &lt;a href="http://www.gordonbiersch.com/restaurants/index.php?pg=beer"&gt;good beer&lt;/a&gt; and had a great conversation about SOFEA, open source and RIA. See larger video &lt;a href="http://www.drunkonsoftware.com/2009/04/05/episode-11-matt-raible/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;embed src="http://blip.tv/play/AfbqQpHGOw" type="application/x-shockwave-flash" width="500" height="281.25" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt; 
&lt;/p&gt;&lt;p&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=61591982 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/congratulations_on_retiring_dad</guid><title>Congratulations on Retiring Dad!</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/congratulations_on_retiring_dad</link><pubDate>Tue, 31 Mar 2009 16:46:47 -0600</pubDate><category>General</category><category>congratulations</category><category>dad</category><category>thecabin</category><category>joeraible</category><category>montana</category><category>career</category><category>retirement</category><description>&lt;a href="http://farm3.static.flickr.com/2373/2360759827_bf5ac30092.jpg" title="Dad's New Rig" rel="lightbox[retiringdad]"&gt;&lt;img src="http://farm3.static.flickr.com/2373/2360759827_bf5ac30092_m.jpg" width="240" height="180" alt="Dad's New Rig" class="picture" /&gt;&lt;/a&gt;
Today is a very special day in my Dad's life. Today is his last day of work. Within the next hour, Joseph Edward Raible, Jr. will officially become retired and subsequently one of the happiest people I know. My dad has always had an interesting relationship with &lt;em&gt;work&lt;/em&gt;. I've never met someone who hated working for &lt;em&gt;The Man&lt;/em&gt; more, yet had such a strong work ethic.&lt;/p&gt;
&lt;p&gt;Growing up in Montana, my dad always had the shittiest jobs. When I was a toddler, he used to walk several miles to work, often during the cruel Montana winters. As I got older, I remember him working as a carpenter, logger, trail crew specialist, firefighter, radio technician and even a programmer. The reason his jobs were so shitty is because he told us they were. I don't think he made over $5/hour until I was in the second grade.&lt;/p&gt;
&lt;p&gt;
He was able to turn his career around in impressive fashion in the early 90s. He'd always been a "computer guy" at &lt;a href="http://raibledesigns.com/rd/entry/the_cabin"&gt;the cabin&lt;/a&gt;. He even went to Graduate School for his Masters in Computer Science. When we moved to Oregon, he volunteered at &lt;a href="http://www.blm.gov/or/districts/salem/index.php"&gt;my mom's new office&lt;/a&gt; as a Network Administrator. After 6 months, they hired him and he quickly moved up the ranks. I believe his current title is something fancy like Director of Wireless Communications. Over the last 19 years, he's worked for the BLM and done amazing things like setup radio networks in Honduras and Tanzania. He's turned into quite the world traveler.
&lt;/p&gt;
&lt;p&gt;The thing I remember the most is his perseverance. One winter when he couldn't find work, he &lt;a href="http://www.flickr.com/photos/mraible/208273170/in/set-72157594226552398/"&gt;built a barn&lt;/a&gt;. From scratch, mostly by himself.&lt;/p&gt;
&lt;p&gt;The other thing I remember well is how much he complained about work. It was never the actual work that he complained about, it was the "stupid fuckin' idiots" that he had to work with (or for). This is the reason that this is such a special day. I can't help but think a huge weight is being lifted from his shoulders and he's going to much happier. Then again, you know how these things go - he might actually miss having people around to complain about.&lt;/p&gt;
&lt;p&gt;One thing's for sure, I'm super pumped and happy for the guy. He plans on moving back to Montana for the summer to work on the New Cabin and it's likely I'll get to spend a lot more time with him in the coming years.&lt;/p&gt;
&lt;p&gt;Congratulations and cheers to you Dad. You did it. I'm extremely proud of you today. &lt;img src="http://raibledesigns.com/images/smileys/grin.gif" class="smiley" alt=":-D" title=":-D" /&gt;&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=61311399&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=61311399&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=61311399 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/new_office_and_new_bike</guid><title>New Office and New Bike</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/new_office_and_new_bike</link><pubDate>Mon, 30 Mar 2009 23:51:39 -0600</pubDate><category>General</category><category>bike</category><category>commuting</category><category>riding</category><category>biking</category><category>denver</category><description>Back in January, I moved into a new office to work on my &lt;a href="http://raibledesigns.com/rd/entry/what_s_next"&gt;current project&lt;/a&gt;. The following week, &lt;a href="http://raibledesigns.com/rd/entry/r_i_p_giant_fcr3"&gt;my bike was stolen&lt;/a&gt;. The next day I &lt;a href="http://raibledesigns.com/rd/entry/running_to_work"&gt;ran to work&lt;/a&gt; and decided to do it for a couple months.&lt;/p&gt;
&lt;p class="quote" style="color: #666"&gt;
My current goal is to run until April 1st or until I lose 20 pounds, whichever comes first.
&lt;/p&gt;
&lt;p&gt;The next week, my co-worker's bike was stolen and I knew I had to stick with my goal. The significance of April 1st was that our office lease expires on April 1st and we were planning on moving to a new office. While &lt;a href="http://denver.youroffice.com/"&gt;our office&lt;/a&gt; is nice, it is a large one-room office with no windows. The &lt;a href="http://www.flickr.com/photos/mraible/sets/72157605402333390/"&gt;previous office&lt;/a&gt; was quite a bit cooler, but also cost twice as much.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://farm4.static.flickr.com/3585/3401026482_ce1c4b579b_o.jpg" title="Raible Designs HQ 2009" rel="lightbox[newofficenewbike]"&gt;&lt;img src="http://farm4.static.flickr.com/3585/3401026482_e79c859867_t.jpg" width="100" height="75" alt="Raible Designs HQ 2009" class="picture" /&gt;&lt;/a&gt;
A couple of weeks ago, we found a nice office near downtown. I signed a 1-year lease and moved in over the weekend. For folks in Denver, you might recognize the &lt;a href="http://www.forestroom5.com/"&gt;nice location&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
I did my final run to work last Thursday, in the midst the &lt;a href="http://www.associatedcontent.com/article/1603078/colorado_the_blizzard_of_2009.html"&gt;Blizzard of 2009&lt;/a&gt;. 

&lt;a href="http://farm4.static.flickr.com/3660/3401028776_b467c1f7e4_o.jpg" title="Almost Whiteout" rel="lightbox[newofficenewbike]"&gt;&lt;img src="http://farm4.static.flickr.com/3660/3401028776_2b2bff9ffc_t.jpg" width="100" height="75" alt="Almost Whiteout" class="picture" style="float: left; margin-top: 5px; margin-bottom: 5px; margin-left: 0" /&gt;&lt;/a&gt;

While running to work was a great experiment and I enjoyed telling people I was doing it, it wasn't &lt;em&gt;fun&lt;/em&gt;. I've been riding my bike to work for many years (first year was 1999). The one thing I've always enjoyed was the thrill of the ride in the morning. On a beautiful spring day, it's really a fantastic experience. It's easily been the best part of any job I've ever had.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://farm4.static.flickr.com/3469/3400215481_14c2f6a057_o.jpg" title="New Trek FX 7.5" rel="lightbox[newofficenewbike]"&gt;&lt;img src="http://farm4.static.flickr.com/3469/3400215481_7e1e54002e_t.jpg" width="100" height="75" alt="New Trek FX 7.5" class="picture" /&gt;&lt;/a&gt;
With the new office secured and the running mission completed, I walked over to my &lt;a href="http://campuscycles.com/"&gt;favorite bike shop&lt;/a&gt; and picked up a &lt;a href="http://www.trekbikes.com/us/en/bikes/bike_path/fx/75fx/"&gt;Trek FX 7.5&lt;/a&gt; yesterday. To research and figure out which bike to buy, I &lt;a href="http://www.linkedin.com/groupAnswers?viewQuestionAndAnswers=&amp;amp;gid=91090amp;&amp;discussionID=2147567"&gt;asked my network&lt;/a&gt; on LinkedIn. 
&lt;/p&gt;
&lt;p&gt;
As luck would have it, my first ride to the new office was today and 
&lt;a href="http://farm4.static.flickr.com/3435/3400215459_9f8df5cb57_o.jpg" title="First Ride on New Trek" rel="lightbox[newofficenewbike]"&gt;&lt;img src="http://farm4.static.flickr.com/3435/3400215459_f60a4485ed_t.jpg" width="100" height="75" alt="First Ride on New Trek" class="picture" style="float: left; margin-top: 5px; margin-bottom: 5px; margin-left: 0" /&gt;&lt;/a&gt;
we woke up to a morning snow storm. 
Even though the ride was cold and wet, I still had a blast. I've enjoyed riding since I traversed the hills on a BMX bike back in Montana. Getting back in the saddle today was simply awesome and I can't wait to ride again tomorrow, regardless of the weather.
I know those nice spring days are just around the corner. &lt;img src="http://raibledesigns.com/images/smileys/grin.gif" class="smiley" alt=":-D" title=":-D" /&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=61240147 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><item><guid isPermaLink="true">http://raibledesigns.com/rd/entry/optimizing_a_gwt_application_with</guid><title>Optimizing a GWT Application with Multiple EntryPoints</title><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Raible</dc:creator><link>http://raibledesigns.com/rd/entry/optimizing_a_gwt_application_with</link><pubDate>Wed, 25 Mar 2009 16:00:37 -0600</pubDate><category>Java</category><category>maven</category><category>gzip</category><category>entrypoint</category><category>gwt</category><category>gwt-maven</category><category>webframeworks</category><category>optimization</category><description>Building a GWT application is an easy way for Java Developers to write Ajax applications. However, it can be difficult to release a GWT application to production before it's finished. One of the most important things I've learned in Software Development is to get a new application into production as soon as possible. Not only does getting it from dev &amp;rarr; qa &amp;rarr; prod verify your process works, it also can do a lot to test the viability of the new application.
&lt;/p&gt;
&lt;p&gt;One of the biggest issues with GWT applications is size. The project I'm working on compiles Java to JavaScript and creates ~570K *.cache.html files (one for each modern browser). These files end up being around 180K gzipped. I believe this is an OK size for an entire application. However, if you're going to &lt;em&gt;release early, release often&lt;/em&gt; with GWT, chances are you'll just want to release one feature at a time. &lt;/p&gt;
&lt;p&gt;When the first feature was completed on my project, the *.cache.html files were around 300K. Rather than using branches to release to QA and UAT, bug fixes and new features were developed on trunk. Unfortunately, the QA and UAT process took several weeks longer than expected so by the time the feature was ready to release, the *.cache.html files had grown to around ~570K. The reason the file had grown so much was because it included all of the other features.&lt;/p&gt;
&lt;p&gt;Earlier this week, while running to a dentist appointment, I thought of a solution to this problem. The basic idea was to optimize the compilation process so only the to-be-released feature was included. Even better, the solution didn't require &lt;a href="http://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt"&gt;more modularization&lt;/a&gt;. The results:&lt;/p&gt;
&lt;pre&gt;
Before: *.cache.html -&gt; 569K, gzipped 175K
After: *.cache.html -&gt; 314K, gzipped 100K
&lt;/pre&gt;
&lt;p&gt;According to my calculations, that's a 56% reduction in size. How did I do it?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Created a new &lt;code&gt;FeatureName.java&lt;/code&gt; EntryPoint with only the to-be-released features imported. &lt;/li&gt;
&lt;li&gt;Created a new &lt;code&gt;FeatureName.gwt.xml&lt;/code&gt; that references the new EntryPoint.&lt;/li&gt;
&lt;li&gt;Copied old (kitchen-sink) EntryPoint.html to &lt;code&gt;FeatureName.html&lt;/code&gt; and changed the reference to the nocache.js file.&lt;/li&gt;
&lt;li&gt;Created a Maven profile that allows using -PFeatureName to build a FeatureName-only module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One downside to doing things this way is it's possible to create a WAR that has the same name and different features. Surely the Maven Overlords would frown upon this. Since this is just a temporary solution to release features incrementally, I'm not too worried about it. A possible workaround is to create different WAR names when a feature's profile is activated. I believe the true "Maven way" would be to make the "kitchen sink" application into a JAR and have several WAR modules with the different EntryPoints. Seems a bit complicated to me.
&lt;/p&gt;
&lt;p&gt;Other than this Maven publishing issue, the only other issue I can foresee is keeping the two EntryPoints and HTML files in synch. Then again, the separate files allow a feature to be customized for the release and can be deleted when its no longer needed.
&lt;/p&gt;
&lt;p&gt;What do you think? Do you know of a better way to compile a GWT application so it only contains certain features?&lt;p&gt;&lt;a href=http://nimbb.com&gt;&lt;span style=&amp;quote;text-decoration:none; font-family: Verdana, Arial;&amp;quote;&gt;&lt;img src="http://nimbb.com/App_Themes/default/Images/logo.jpg" border=0&gt;&lt;span style="letter-spacing: -1px; font-size: 22px;"&gt;nimbb.com&lt;/span&gt; Webcam video recording in your browser!&lt;/span&gt;&lt;/a&gt; &lt;p&gt;&lt;a href=http://www.rsscache.com/Section/Advertise/click.aspx?n=61065367&gt;&lt;img src="http://www.rsscache.com/Section/Advertise/ads.aspx?n=61065367&amp;f=133" border=0&gt;&lt;/a&gt;&lt;p&gt;&lt;div style="font-size: 8pt;"&gt;&lt;img align=left src=http://www.rsscache.com/Section/Stats/logo.aspx?n=61065367 border=0&gt; Bandwidth saved by &lt;a href=http://www.rsscache.com&gt;RSScache.com&lt;/a&gt;&lt;/div&gt;</description></item><rsscache:id>133</rsscache:id></channel></rss>