<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://raibledesigns.com/roller-ui/styles/rss.xsl" media="screen"?><rss version="2.0" 
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom" >
<channel>
  <title>Raible Designs</title>
  <link>https://raibledesigns.com/rd/</link>
      <atom:link rel="self" type="application/rss+xml" href="https://raibledesigns.com/rd/feed/entries/rss?tags=gwt" />
    <description>Raible Designs is an Enterprise Open Source Consulting company. We specialize in UI and Full Stack Architectures using HTML5, CSS, JavaScript and Java. We love HTML5, Angular, Bootstrap, Spring Boot, and especially JHipster.</description>
  <language>en-us</language>
  <copyright>Copyright 2026</copyright>
  <lastBuildDate>Thu, 30 Apr 2026 03:43:46 -0600</lastBuildDate>
  <generator>Apache Roller (incubating) 5.0.3 (1388864191739:dave)</generator>
        <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_3_5_released</guid>
    <title>AppFuse 3.5 Released!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_3_5_released</link>
        <pubDate>Fri, 20 Feb 2015 09:08:53 -0700</pubDate>
    <category>Java</category>
    <category>wicket</category>
    <category>java</category>
    <category>gwt</category>
    <category>springmvc</category>
    <category>springsecurity</category>
    <category>maven</category>
    <category>tapestry5</category>
    <category>javaee</category>
    <category>jsf</category>
    <category>struts2</category>
    <category>spring</category>
            <description>&lt;p&gt;
&lt;a href=&quot;http://appfuse.org&quot;&gt;&lt;img src=&quot;http://static.appfuse.org/images/appfuse-icon.gif&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;&gt;&lt;/a&gt;
The AppFuse Team is pleased to announce the release of AppFuse 3.5. This release contains a number of improvements.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;XML reduced by 8x in projects generated with AppFuse&lt;/li&gt;&lt;li&gt;CRUD generation&amp;nbsp;support for Wicket, as well as AppFuse Light archetypes (Spring Security, Spring FreeMarker and Stripes)&lt;/li&gt;&lt;li&gt;Upgraded Tapestry to 5.4&lt;/li&gt;&lt;li&gt;Integrated&amp;nbsp;Spring IO Platform for dependency management&lt;/li&gt;&lt;li&gt;Refactored unit tests to use JUnit 4&lt;/li&gt;&lt;li&gt;Renamed maven-warpath-plugin to warpath-maven-plugin&lt;/li&gt;&lt;li&gt;Upgraded to jWebUnit 3 for AppFuse Light integration tests&lt;/li&gt;&lt;li&gt;Updated all AppFuse Light modules to be up-to-date&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;For more details on specific changes
    see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+3.5.0&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br&gt;
    AppFuse is a full-stack framework for building web applications on the JVM. It was
    originally developed to eliminate the ramp-up time when building new web applications. Over
    the years, it has matured into a very testable and secure system for creating Java-based
    webapps.
&lt;/p&gt;
&lt;p&gt;Demos for this release can be viewed at &lt;a href=&quot;http://demo.appfuse.org/&quot;&gt;http://demo.appfuse.org&lt;/a&gt;. Please see
    the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot; style=&quot;font-weight: bold&quot;&gt;QuickStart Guide&lt;/a&gt; to
    get started with this release. &lt;/p&gt;

&lt;p&gt;If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot;&gt;FAQ&lt;/a&gt; or join the
    &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;user mailing list&lt;/a&gt;. If you find any
    issues, please report them on the users mailing list. You can also post them to &lt;a href=&quot;http://stackoverflow.com/questions/tagged/appfuse&quot;&gt;Stack Overflow&lt;/a&gt; with the &quot;appfuse&quot; tag.&lt;/p&gt;

&lt;p&gt;Thanks to everyone for their help contributing patches, writing documentation and participating on the mailing
    lists.&lt;/p&gt;

&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;We greatly appreciate the help from &lt;a href=&quot;http://appfuse.org/display/APF/Sponsors&quot;&gt;our
    sponsors&lt;/a&gt;, particularly &lt;a href=&quot;http://www.atlassian.com/c/NPOS/10160&quot;&gt;Atlassian&lt;/a&gt;,
    &lt;a href=&quot;http://contegix.com/&quot;&gt;Contegix&lt;/a&gt;, and &lt;a href=&quot;http://www.jetbrains.com/&quot;&gt;JetBrains&lt;/a&gt;.
    Atlassian and Contegix are especially awesome:
    &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_now_powered_by_contegix&quot;&gt;Atlassian has donated licenses to all
        its products and Contegix has donated an entire server&lt;/a&gt; to the AppFuse project. &lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/integrating_gwt_into_appfuse</guid>
    <title>Integrating GWT into AppFuse</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/integrating_gwt_into_appfuse</link>
        <pubDate>Thu, 7 Mar 2013 18:49:28 -0700</pubDate>
    <category>Java</category>
    <category>appfuse</category>
    <category>gwt</category>
            <description>&lt;a href=&quot;https://developers.google.com/web-toolkit/images/gwt-logo.png&quot;&gt;&lt;img src=&quot;//developers.google.com/web-toolkit/images/gwt-logo.png&quot; class=&quot;picture&quot;  height=&quot;100&quot; width=&quot;100&quot;&gt;&lt;/a&gt;
I&apos;ve been interested in integrating &lt;a href=&quot;https://developers.google.com/web-toolkit/&quot;&gt;GWT&lt;/a&gt; into &lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt; ever since &lt;a href=&quot;http://raibledesigns.com/rd/entry/gwt_and_appfuse&quot;&gt;I blogged about it 4 years ago&lt;/a&gt;. A few months after that post, I wrote about &lt;a href=&quot;http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt&quot;&gt;Enhancing Evite.com with GWT and Grails&lt;/a&gt;. After Evite, I had a gig near Boston where I developed with GXT for the remainder of the year. When all was said and done, I ended up spending a year with GWT and really enjoyed my experience. I haven&apos;t used it much since.&lt;/p&gt;
&lt;p&gt;GWT is &lt;a href=&quot;http://appfuse.org/display/APF/Roadmap&quot;&gt;scheduled to be integrated into AppFuse&lt;/a&gt; in version 4.0. That&apos;s quite a ways off. The good news is you might not have to wait that long, thanks to &lt;a href=&quot;https://github.com/ivangsa&quot;&gt;Iv&#225;n Garc&#237;a Sainz-Aja&lt;/a&gt;. Iv&#225;n let us know about his work a couple weeks ago in an &lt;a href=&quot;http://appfuse.547863.n4.nabble.com/Creating-a-new-archetype-td4656359.html&quot;&gt;email to the appfuse-dev&lt;/a&gt; mailing list.&lt;/p&gt;
&lt;div class=&quot;quote&quot;&gt;
&lt;p&gt;
It&apos;s still work in progress but it has already most of AppFuse functionality.. 
&lt;/p&gt;&lt;p&gt;
If you want to give it a try 
&lt;/p&gt;&lt;p&gt;
&lt;a href=&quot;https://github.com/ivangsa/appfuse.git&quot;&gt;https://github.com/ivangsa/appfuse.git&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;
the quickest way to have a go would be&lt;/p&gt;
&lt;pre&gt;
web/gwt&gt; mvn -P gwtDebug -Dgwt.inplace=true gwt:compile jetty:run  
&lt;/pre&gt;
&lt;p&gt;
at the moment it still requires this fork of gwt-bootstrap to be compiled first 
&lt;/p&gt;&lt;p&gt;
&lt;a href=&quot;https://github.com/ivangsa/gwt-bootstrap.git&quot;&gt;https://github.com/ivangsa/gwt-bootstrap.git&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;
It needs a lot of testing yet but it&apos;s getting quite there 
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As you can imagine, I was very excited to hear about Iv&#225;n&apos;s work. So I cloned his repo, built gwt-bootstrap locally and checked it out. Functionality wise, it was great! However, when I dug into the source code, I found a whole lotta code. 
&lt;/p&gt;
&lt;p&gt;
To see how the GWT flavor compared to the other implementations in AppFuse, I &lt;a href=&quot;https://gist.github.com/mraible/5033218&quot;&gt;created a cloc report&lt;/a&gt; on the various web frameworks in AppFuse. I&apos;m sure these reports could be adjusted to be more accurate, but I believe they give a good general overview. I posted some graphs that displays my findings in visual form.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;

&lt;a href=&quot;http://farm9.staticflickr.com/8090/8538497066_be60cb73da_o.png&quot; title=&quot;Lines of Java&quot; rel=&quot;lightbox[appfuse-loc]&quot;&gt;&lt;img src=&quot;//farm9.staticflickr.com/8090/8538497066_4f2a6ff71e_m.jpg&quot; width=&quot;240&quot; height=&quot;189&quot; alt=&quot;Lines of Java&quot; style=&quot;border: 1px solid black&quot;&gt;&lt;/a&gt;

&lt;a href=&quot;http://farm9.staticflickr.com/8235/8537391497_deaa49c22d_o.png&quot; title=&quot;Number of Files by mraible, on Flickr&quot; rel=&quot;lightbox[appfuse-loc]&quot;&gt;&lt;img src=&quot;//farm9.staticflickr.com/8235/8537391497_3bbafe2383_m.jpg&quot; width=&quot;240&quot; height=&quot;189&quot; alt=&quot;Number of Files&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot;&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;When I sent this to the mailing list, Ivan &lt;a href=&quot;http://appfuse.547863.n4.nabble.com/Creating-a-new-archetype-tt4656359.html#a4656374&quot;&gt;responded that it was a lot of code&lt;/a&gt; and estimated &lt;em&gt;12 new files&lt;/em&gt; would be needed to &lt;abbr title=&quot;Create, Retrieve, Update, Delete&quot;&gt;CRUD&lt;/a&gt; an entity. This sure seems like a lot to me, but he &lt;a href=&quot;http://appfuse.547863.n4.nabble.com/GWT-RESTFull-backend-tt4656418.html&quot;&gt;defended this yesterday&lt;/a&gt; and noted that his implementation follows many of GWT&apos;s latest best 
practices: MVP pattern, Activities and Places, EventBus, Gin and Guice. He also shared a &lt;a href=&quot;https://github.com/ivangsa/appfuse/wiki&quot;&gt;wiki page&lt;/a&gt; with explanations and diagrams of how things work.&lt;/p&gt;
&lt;p&gt;The reason I&apos;m writing this post is to get more feedback on this implementation. First of all, &lt;em&gt;does GWT really require this much code&lt;/em&gt;? Secondly, are there other GWT implementations that reduce a lot of the boilerplate? &lt;a href=&quot;https://code.google.com/p/smartgwt/&quot;&gt;SmartGWT&lt;/a&gt;, &lt;a href=&quot;https://vaadin.com/home&quot;&gt;Vaadin&lt;/a&gt;* and &lt;a href=&quot;http://www.jboss.org/errai&quot;&gt;Errai&lt;/a&gt; come to mind. 
&lt;/p&gt;
&lt;p&gt;If you were starting a new GWT project and using AppFuse, how would &lt;em&gt;you&lt;/em&gt; want it implemented?&lt;/p&gt;
&lt;p style=&quot;font-size: .9em; border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;* Vaadin 7 claims it &lt;a href=&quot;http://www.infoq.com/news/2013/02/vaadin-7&quot;&gt;can be used as a drop-in replacement for GWT&lt;/a&gt;. I tried &lt;a href=&quot;https://gist.github.com/mraible/5113636&quot;&gt;replacing the gwt-servlet and gwt-user dependencies&lt;/a&gt; with Vaadin&apos;s, but it &lt;a href=&quot;https://gist.github.com/mraible/5113607&quot;&gt;didn&apos;t work&lt;/a&gt;.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/livin_it_up_in_vegas</guid>
    <title>Livin&apos; it up in Vegas at TSSJS 2011</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/livin_it_up_in_vegas</link>
        <pubDate>Tue, 22 Mar 2011 09:04:17 -0600</pubDate>
    <category>Java</category>
    <category>vegas</category>
    <category>tssjs</category>
    <category>perfbench</category>
    <category>gwt</category>
    <category>webframeworks</category>
    <category>vaadin</category>
    <category>liftweb</category>
    <category>springmvc</category>
    <category>video</category>
    <category>playframework</category>
    <category>rubyonrails</category>
    <category>grails</category>
    <category>onlinevideo</category>
            <description>Last Wednesday, Trish and I traveled to Las Vegas for &lt;a href=&quot;http://javasymposium.techtarget.com/&quot;&gt;TheServerSide Java Symposium 2011 conference&lt;/a&gt;. We had a free room from TechTarget, but opted to upgrade to a suite with a view over the Bellagio Fountains. Trish won a trip to Vegas as a sales award earlier in the year and cleverly exchanged it for cash, so our upgrade was sort of free. 
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;a href=&quot;http://farm6.static.flickr.com/5305/5550023760_e8f128457a.jpg&quot; title=&quot;Caesars Pool&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5305/5550023760_e8f128457a_m.jpg&quot; width=&quot;240&quot; height=&quot;159&quot; alt=&quot;Caesars Pool&quot; style=&quot;border: 1px solid black&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://farm6.static.flickr.com/5053/5550024190_b272c2f012.jpg&quot; title=&quot;The Bellagio Fountains&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5053/5550024190_b272c2f012_m.jpg&quot; width=&quot;240&quot; height=&quot;159&quot; alt=&quot;The Bellagio Fountains&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;

&lt;/p&gt;
My first talk was on Online Video and my experience at Time Warner Cable. With my former team&apos;s &lt;a href=&quot;http://justanotheripadblog.com/ipad-app-reviews/quick-look-twcable-tv-for-ipad-time-warner-cables-new-live-streaming-app-looks-good&quot;&gt;iPad app releasing the day before&lt;/a&gt;, it was a fun session. The attendance was kind of sparse, but I had some good competition so wasn&apos;t surprised.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;object id=&quot;__sse7299514&quot; width=&quot;425&quot; height=&quot;355&quot;&gt; &lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=everythingonlinevideotssjs2011-110317161814-phpapp02&amp;rel=0&amp;stripped_title=everything-you-ever-wanted-to-know-about-online-video-tssjs-2011&amp;userName=mraible&quot; /&gt; &lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt; &lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt; &lt;embed name=&quot;__sse7299514&quot; src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=everythingonlinevideotssjs2011-110317161814-phpapp02&amp;rel=0&amp;stripped_title=everything-you-ever-wanted-to-know-about-online-video-tssjs-2011&amp;userName=mraible&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt; &lt;/object&gt;&lt;/p&gt;
&lt;p&gt;After I finished speaking, we headed to happy hour and met up with some friends that happened to be in town. We had dinner at the &lt;a href=&quot;http://www.toddenglishpub.com/&quot;&gt;Todd English Pub&lt;/a&gt; and headed to the &lt;a href=&quot;http://www.pennandteller.com/&quot;&gt;Penn &amp;amp; Teller&lt;/a&gt; show at the Rio. We closed the night after Trish had a 45-minute roll at the craps table at &lt;a href=&quot;http://www.harrahs.com/osheas/&quot;&gt;O&apos;Sheas&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;We slept in on Thursday and I gave my Comparing JVM Web Frameworks talk that afternoon. I made sure to mention some other methods to choosing web frameworks: doing &lt;a href=&quot;http://code.google.com/p/perfbench/&quot;&gt;performance comparisons&lt;/a&gt; like Peter Thomas has done or &lt;a href=&quot;http://lift.la/my-take-on-matt-raibles-spreadsheet&quot;&gt;choosing Lift&lt;/a&gt; because one of its developers says it&apos;s the best. While Vaadin did sneak into the #5 spot, I made sure and mentioned that Wicket and Tapestry seem to belong there moreso (based on stats, mailing list traffic, etc.).
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;object id=&quot;__sse7299545&quot; width=&quot;425&quot; height=&quot;355&quot;&gt; &lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=comparingjvmwebframeworkstssjs2011-110317162242-phpapp02&amp;rel=0&amp;stripped_title=comparing-jvm-web-frameworks-tssjs-2011&amp;userName=mraible&quot; /&gt; &lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt; &lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt; &lt;embed name=&quot;__sse7299545&quot; src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=comparingjvmwebframeworkstssjs2011-110317162242-phpapp02&amp;rel=0&amp;stripped_title=comparing-jvm-web-frameworks-tssjs-2011&amp;userName=mraible&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt; &lt;/object&gt; 
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mcginityphoto.com/&quot;&gt;Trish&lt;/a&gt; took a bunch of pictures during my talk, which had a great turnout and lots of participation.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;a href=&quot;http://farm6.static.flickr.com/5131/5550024506_e90c77ff59.jpg&quot; title=&quot;Getting Intro&apos;d&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5131/5550024506_e90c77ff59_t.jpg&quot; width=&quot;100&quot; height=&quot;66&quot; alt=&quot;Getting Intro&apos;d&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://farm6.static.flickr.com/5266/5549441719_057d56a957.jpg&quot; title=&quot;My Intro&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5266/5549441719_057d56a957_t.jpg&quot; width=&quot;100&quot; height=&quot;66&quot; alt=&quot;My Intro&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://farm6.static.flickr.com/5149/5550024786_52a3f6aaea.jpg&quot; title=&quot;My Dream Bus on Display&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5149/5550024786_52a3f6aaea_t.jpg&quot; width=&quot;100&quot; height=&quot;66&quot; alt=&quot;My Dream on Display&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;a href=&quot;http://farm6.static.flickr.com/5051/5549442047_5defbb12d0.jpg&quot; title=&quot;The Problem&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5051/5549442047_5defbb12d0_t.jpg&quot; width=&quot;100&quot; height=&quot;66&quot; alt=&quot;The Problem&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://farm6.static.flickr.com/5173/5550025074_d8af7137ba.jpg&quot; title=&quot;How do you choose?&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5173/5550025074_d8af7137ba_t.jpg&quot; width=&quot;100&quot; height=&quot;66&quot; alt=&quot;How do you choose?&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://farm6.static.flickr.com/5140/5550025200_a32831f218.jpg&quot; title=&quot;Choosing a Framework&quot; rel=&quot;lightbox[tssjs2011]&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5140/5550025200_a32831f218_t.jpg&quot; width=&quot;100&quot; height=&quot;66&quot; alt=&quot;Choosing a Framework&quot; style=&quot;border: 1px solid black; margin-left: 10px&quot; /&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;That evening, we celebrated St. Patty&apos;s Day with some college buddies of mine, ate great sushi at &lt;a href=&quot;http://www.mandalaybay.com/dining/casual-restaurants/mizuya.aspx&quot;&gt;Mizuya&lt;/a&gt; and experienced the joys of three card poker. Thanks to TechTarget for inviting me to TSSJS 2011; we had an awesome time. You can find all the pictures we took &lt;a href=&quot;http://www.flickr.com/photos/mraible/sets/72157626325120502/&quot;&gt;on Flickr&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; color: #666; padding-top: 5px&quot;&gt;
P.S. If you can&apos;t see the presentations in this post (a.k.a. you don&apos;t have Flash), you can &lt;a href=&quot;http://www.slideshare.net/mraible&quot; style=&quot;color: #666&quot;&gt;view them on on Slideshare&lt;/a&gt; or &lt;a href=&quot;http://raibledesigns.com/rd/page/publications&quot; style=&quot;color: #666&quot;&gt;download the PDFs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/jsr_303_and_web_framework</guid>
    <title>JSR 303 and JVM Web Framework Support</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/jsr_303_and_web_framework</link>
        <pubDate>Tue, 8 Mar 2011 11:33:24 -0700</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>tapestry</category>
    <category>struts2</category>
    <category>webframeworks</category>
    <category>jsr303</category>
    <category>vaadin</category>
    <category>lift</category>
    <category>springmvc</category>
            <description>Emmanuel Bernard recently sent an email to the JSR 303 Experts Group about the next revision of the Bean Validation JSR (303). Rather than sending the proposed changes privately, he &lt;a href=&quot;http://in.relation.to/Bloggers/JSRBeanValidation11WhatToPutIn&quot;&gt;blogged about them&lt;/a&gt;. I left a comment with what I&apos;d like to see:
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
+1 for Client-side validation. I&apos;d love to see an API that web frameworks can hook into to add &quot;required&quot; to their tags for HTML5. Or some service that can be registered so the client can make Ajax requests to an API to see if an object is valid.
&lt;/p&gt;
&lt;p&gt;Emmanuel replied that most of the necessary API already exists for this, but frameworks have been slow to adopt it.
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Hi Matt,
&lt;br/&gt;&lt;br/&gt;
The sad thing is that the API is present on the Bean Validation side but presentation frameworks are slow to adopt it and use it :(
&lt;br/&gt;&lt;br/&gt;
RichFaces 4 now has support for it but I wished more presentation frameworks had worked on the integration. If you can convince a few people or have access to a few people, feel free to send them by me :)
&lt;br/&gt;&lt;br/&gt;
The integration API is &lt;a href=&quot;http://people.redhat.com/~ebernard/validation/#constraintmetadata&quot;&gt;described here&lt;/a&gt;. Let me know if you think some parts are missing or should be improved. We should definitely do some more buzz around it.
&lt;/p&gt;
&lt;p&gt;In the interest of generating more buzz around it, I decided to do some research and see what JVM Frameworks support JSR 303. Here&apos;s what I&apos;ve come up with so far (in no particular order):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://relation.to/Bloggers/RichFaces4ClientSideValidation&quot;&gt;RichFaces 4 - Client Side Validation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tapestry.apache.org/bean-validation.html&quot;&gt;Tapestry&apos;s JSR 303 - Bean Validation Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.zenika.com/index.php?post/2010/02/24/Wicket-JSR-303-Validators&quot;&gt;Wicket JSR-303 Validators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#validation-mvc-jsr303&quot;&gt;Configuring a JSR-303 Validator for use by Spring MVC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/gwt-validation/&quot;&gt;GWT Validation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dev.vaadin.com/ticket/3156&quot;&gt;Vaadin Bean Validation JSR 303 support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wstrange.wordpress.com/2009/12/07/inline-field-validation-in-scalalift-using-jpa-and-jsr-303/&quot;&gt;Inline field validation in Scala/Lift using JPA and JSR 303&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Struts 2 has an &lt;a href=&quot;https://issues.apache.org/jira/browse/WW-2563&quot;&gt;open issue&lt;/a&gt;, but doesn&apos;t seem to support JSR 303. Since I did a quick-n-dirty google search for most of these, I&apos;m not sure if they support client-side JavaScript or HTML5&apos;s required. If you know of other JVM-based web frameworks that support JSR 303, please let me know in the comments. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/how_i_calculated_ratings_for</guid>
    <title>How I Calculated Ratings for My JVM Web Frameworks Comparison</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/how_i_calculated_ratings_for</link>
        <pubDate>Mon, 6 Dec 2010 11:55:18 -0700</pubDate>
    <category>Java</category>
    <category>devoxx2010</category>
    <category>webframeworks</category>
    <category>jvm</category>
    <category>lift</category>
    <category>comparingwebframeworks</category>
    <category>webframeworksmatrix</category>
    <category>spring</category>
    <category>rails</category>
    <category>vaadin</category>
    <category>jsf</category>
    <category>flex</category>
    <category>gwt</category>
    <category>wicket</category>
    <category>springmvc</category>
    <category>stripes</category>
    <category>java</category>
    <category>rubyonrails</category>
    <category>devoxx</category>
    <category>grails</category>
    <category>struts2</category>
    <category>playframework</category>
            <description>When I re-wrote my &lt;a href=&quot;http://raibledesigns.com/rd/entry/my_comparing_jvm_web_frameworks&quot;&gt;Comparing JVM Web Frameworks presentation&lt;/a&gt; from scratch, I decided to add a &lt;a href=&quot;http://bit.ly/jvm-frameworks-matrix&quot;&gt;matrix&lt;/a&gt; that allows you to rate a framework based on &lt;a href=&quot;https://docs.google.com/document/pub?id=1jAGPWwlEcYikqOPg8faYgRV7cQNS_iCCoJ1VNc_99M4&quot;&gt;20 different criteria&lt;/a&gt;. The reason I did this was because I&apos;d used this method when &lt;a href=&quot;http://raibledesigns.com/rd/entry/ajax_framework_analysis_results&quot;&gt;choosing an Ajax framework for Evite&lt;/a&gt; last year. The matrix seemed to work well for selecting the top 5 frameworks, but it also inspired a lot of discussion in the community that my &lt;a href=&quot;http://ptrthomas.wordpress.com/2010/12/04/comparing-jvm-web-frameworks-a-response-to-matt-raible/&quot;&gt;ratings&lt;/a&gt; &lt;a href=&quot;http://blog.frankel.ch/critical-analysis-of-frameworks-comparison&quot;&gt;were&lt;/a&gt; &lt;a href=&quot;http://basementcoders.com/2010/12/episode-27-hudson-oracle-raible-and-astycrapper/&quot;&gt;wrong&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;I expected this, as I certainly don&apos;t know every framework as well as I&apos;d like. The mistake I made was asking for the community to provide feedback on my ratings without describing how I arrived at them. From &lt;a href=&quot;http://ptrthomas.wordpress.com/2010/12/04/comparing-jvm-web-frameworks-a-response-to-matt-raible/&quot;&gt;Peter Thomas&apos;s blog&lt;/a&gt;:
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
What you are doing is adjusting ratings based on who in the community shouts the loudest. I can&apos;t help saying that this approach comes across as highly arrogant and condescending, you seem to expect framework developers and proponents to rush over and fawn over you to get better ratings, like waiters in a restaurant trying to impress a food-critic for Michelin stars.
&lt;/p&gt;
&lt;p&gt;
I apologize for giving this impression. It certainly wasn&apos;t my intent. By having simple numbers (1.0 == framework does well, 0.5 == framework is OK and 0 == framework not good at criteria) with no rationalization, I can see how the matrix can be interpreted as useless (or to put it bluntly, as &lt;a href=&quot;http://basementcoders.com/2010/12/episode-27-hudson-oracle-raible-and-astycrapper/&quot;&gt;something you should wipe your ass with&lt;/a&gt;). I don&apos;t blame folks for getting angry.&lt;/p&gt;
&lt;p&gt;For my Rich Web Experience presentation, I documented why I gave each framework the rating I did. Hopefully this will allow folks to critique my ratings more constructively and I can make the numbers more accurate. You can view this document below or &lt;a href=&quot;http://bit.ly/jvm-webfwk-ratings-logic&quot;&gt;on Google Docs&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;iframe src=&quot;//docs.google.com/document/pub?id=1X_XvpJd6TgEAMe4a6xxzJ38yzmthvrA6wD7zGy2Igog&amp;amp;embedded=true&quot; style=&quot;width: 100%; border: 1px solid silver; height: 400px&quot;&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;In the end, what I was hoping to do with this matrix was to simply highlight a &lt;em&gt;technique&lt;/em&gt; for choosing a web framework. Furthermore, I think adding a &quot;weight&quot; to each criteria is important because things like books often aren&apos;t as important as REST support. To show how this might be done, I added a second sheet to the matrix and made up some weighting numbers. I&apos;d expect anyone that wants to use this to &lt;a href=&quot;http://static.raibledesigns.com/repository/presentations/JVM_Web_Framework_Matrix_20101206.xls&quot;&gt;downloaded the matrix&lt;/a&gt;, verify the ratings are accurate for your beliefs and weight the criteria accordingly.
&lt;/p&gt;
&lt;p&gt;
Of course, as I and many others have said, the best way to choose a web framework is to try them yourself. I emphasized this at the end of my presentation with the following two slides.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;a href=&quot;http://www.flickr.com/photos/mraible/5238846712/&quot; title=&quot;Slide #77 from Comparing JVM Web Frameworks Talk at RWX2010&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5281/5238846712_375a63e4c6.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;Slide #77 from Comparing JVM Web Frameworks Talk at RWX2010&quot; /&gt;&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;a href=&quot;http://www.flickr.com/photos/mraible/5238846740/&quot; title=&quot;Slide #76 from Comparing JVM Web Frameworks Talk at RWX2010&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5129/5238846740_29b06ee0eb.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;Slide #76 from Comparing JVM Web Frameworks Talk at RWX2010&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/my_comparing_jvm_web_frameworks</guid>
    <title>My Comparing JVM Web Frameworks Presentation from Devoxx 2010</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/my_comparing_jvm_web_frameworks</link>
        <pubDate>Thu, 18 Nov 2010 05:23:10 -0700</pubDate>
    <category>Java</category>
    <category>spring</category>
    <category>stripes</category>
    <category>rubyonrails</category>
    <category>java</category>
    <category>jvm</category>
    <category>struts2</category>
    <category>devoxx2010</category>
    <category>playframework</category>
    <category>lift</category>
    <category>devoxx</category>
    <category>grails</category>
    <category>webframeworks</category>
    <category>rails</category>
    <category>wicket</category>
    <category>gwt</category>
    <category>springmvc</category>
    <category>vaadin</category>
    <category>jsf</category>
    <category>flex</category>
            <description>This week, I&apos;ve been having a great time in Antwerp, Belgium at the &lt;a href=&quot;http://www.devoxx.com/display/Devoxx2K10/Home&quot;&gt;Devoxx&lt;/a&gt; Conference. This morning, I had the pleasure of delivering my &lt;a href=&quot;http://www.devoxx.com/display/Devoxx2K10/Comparing+JVM+Web+Frameworks&quot;&gt;Comparing JVM Web Frameworks&lt;/a&gt; talk. I thoroughly enjoyed giving this presentation, especially to such a large audience. You can view the presentation below (if you have Flash installed) or &lt;a href=&quot;http://static.raibledesigns.com/repository/presentations/Comparing_JVM_Web_Frameworks_Devoxx2010.pdf&quot;&gt;download it here&lt;/a&gt;.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/uBZoC22SGdjpFy&quot; width=&quot;510&quot; height=&quot;420&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;
Unlike previous years, I chose to come up with a &lt;a href=&quot;http://bit.ly/jvm-frameworks-matrix&quot;&gt;spreadsheet matrix&lt;/a&gt; that shows why I chose the 5 I did. This spreadsheet and rankings given to each framework are likely to be debated, as I don&apos;t know all the frameworks as well as I&apos;d like to. Also, the missing column on this spreadsheet is a &quot;weighting&quot; column where you can prioritize certain criteria like I&apos;ve done in the past when &lt;a href=&quot;http://raibledesigns.com/rd/entry/ajax_framework_analysis_results&quot;&gt;Comparing Ajax Frameworks&lt;/a&gt;. If you believe there are incorrect numbers, please let me know and I&apos;ll try to get those fixed before I do this talk again at &lt;a href=&quot;http://www.therichwebexperience.com/conference/fort_lauderdale/2010/11/home&quot;&gt;The Rich Web Experience&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
One thing that doesn&apos;t come across in this presentation is that I believe &lt;em&gt;anyone&lt;/em&gt; can use this matrix, and weightings, to make &lt;em&gt;any&lt;/em&gt; of these frameworks come out on top. I also believe web frameworks are like spaghetti sauce in &lt;a href=&quot;http://www.gladwell.com/2004/2004_09_06_a_ketchup.html&quot;&gt;The Ketchup Conundrum&lt;/a&gt;. That is, the only way to make more happy spaghetti sauce lovers was to make more &lt;em&gt;types&lt;/em&gt; of spaghetti sauce. You can read more about this in my &lt;a href=&quot;http://raibledesigns.com/rd/entry/there_is_no_best_web&quot;&gt;There is no &quot;best&quot; web framework&lt;/a&gt; article.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; If you disagree with the various ratings I gave to web frameworks in this presentation, please provide your opinions by &lt;a href=&quot;http://bit.ly/webmatrixsurvey&quot;&gt;filling out this survey&lt;/a&gt;. Thanks to &lt;a href=&quot;http://twitter.com/sarbogast&quot;&gt;Sebastien Arbogast&lt;/a&gt; for setting this up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Sebastien has posted his survey results at &lt;a href=&quot;http://sebastien-arbogast.com/2010/11/19/jvm-web-framework-survey-first-results/&quot;&gt;JVM Web Framework Survey, First Results&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 12/6:&lt;/strong&gt; A video of this presentation is &lt;a href=&quot;http://parleys.com/d/2118&quot;&gt;now available on Parleys.com&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;
P.S. My current gig is ending in mid-December. If you&apos;re looking for a UI Architect with a passion for open source frameworks, please &lt;a href=&quot;http://raibledesigns.com/contact.jsp&quot;&gt;let me know&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/presentations_from_the_irish_software</guid>
    <title>My Presentations from The Irish Software Show 2010</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/presentations_from_the_irish_software</link>
        <pubDate>Thu, 10 Jun 2010 07:11:35 -0600</pubDate>
    <category>Java</category>
    <category>webframeworks</category>
    <category>grails</category>
    <category>iss2010</category>
    <category>rubyonrails</category>
    <category>flex</category>
    <category>rails</category>
    <category>gwt</category>
            <description>This week I&apos;ve been enjoying Dublin, Ireland thanks to the 2nd Annual &lt;a href=&quot;http://epicenter.ie/2010.html&quot;&gt;Irish Software Show&lt;/a&gt;. On Wednesday night, I spoke about &lt;a href=&quot;http://epicenter.ie/2010.html?zone_id=20&amp;amp;mode=agenda&amp;amp;session=152#session&quot;&gt;The Future of Web Frameworks&lt;/a&gt; and  participated in a panel with Grails, Rails, ASP.NET MVC and Seaside developers. It was a fun night with lots of lively discussion. Below is my presentation from this event.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;object id=&quot;__sse3271151&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=thefutureofwebframeworks-100225012146-phpapp02&amp;amp;stripped_title=the-future-of-web-frameworks&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse3271151&quot; src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=thefutureofwebframeworks-100225012146-phpapp02&amp;amp;stripped_title=the-future-of-web-frameworks&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/p&gt;
&lt;p&gt;This morning, I delivered my &lt;a href=&quot;http://epicenter.ie/2010.html?zone_id=20&amp;amp;mode=agenda&amp;amp;session=151#session&quot;&gt;Comparing Kick-Ass Web Frameworks&lt;/a&gt; talk. This presentation contains updated statistics for various metrics comparing Rails vs. Grails and Flex vs. GWT. 
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;object id=&quot;__sse2644393&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=comparingkickasswebframeworks-091203145644-phpapp02&amp;stripped_title=comparing-kick-ass-web-frameworks&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse2644393&quot; src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=comparingkickasswebframeworks-091203145644-phpapp02&amp;stripped_title=comparing-kick-ass-web-frameworks&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/p&gt;
&lt;p&gt;
Thanks to all who attended my talks this week!
&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;
P.S. I believe audio was recorded on Wednesday night, but I&apos;m unsure how it turned out. I&apos;m pretty sure no recordings were done on this morning&apos;s session. 
&lt;/p&gt;&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/tssjs_2010_presentations_and_summary</guid>
    <title>My TSSJS 2010 Presentations and Summary</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/tssjs_2010_presentations_and_summary</link>
        <pubDate>Fri, 19 Mar 2010 17:29:08 -0600</pubDate>
    <category>Java</category>
    <category>future</category>
    <category>webframeworks</category>
    <category>vegas</category>
    <category>tssjs</category>
    <category>gwt</category>
    <category>spring</category>
    <category>java</category>
    <category>flex</category>
            <description>This afternoon, I delivered my last talk at &lt;a href=&quot;http://javasymposium.techtarget.com/&quot;&gt;TSSJS 2010&lt;/a&gt; on &lt;a href=&quot;http://javasymposium.techtarget.com/html/frameworks.html#MRaibleFrameworks&quot;&gt;The Future of Web Frameworks&lt;/a&gt;. It&apos;s true that I made some &lt;a href=&quot;http://twitter.com/xgerman/status/10741037460&quot; title=&quot;JSF and Wicket are dead! Bold statement but GWT is a better alternative to begin with anyway #tssjs&quot;&gt;bold statements&lt;/a&gt;, but please remember that this is my personal opinion, based on my experience. For the most part, I&apos;ve been involved in super high-traffic websites for the last few years and this has influenced my opinion on web frameworks. Just because I don&apos;t recommend your favorite framework doesn&apos;t mean it won&apos;t work for you. In fact, many of the best web applications today were built without an open source (or commercial) web framework. In the end, it&apos;s not as much about the web framework you&apos;re using as it is about hiring smart people. Below is my slide deck from this talk.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;object width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=thefutureofwebframeworks-100225012146-phpapp02&amp;stripped_title=the-future-of-web-frameworks&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=thefutureofwebframeworks-100225012146-phpapp02&amp;stripped_title=the-future-of-web-frameworks&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;Yesterday, I did a &lt;a href=&quot;http://javasymposium.techtarget.com/html/theclientside.html#MRaibleSmack&quot;&gt;GWT vs. Flex Smackdown&lt;/a&gt; with &lt;a href=&quot;http://jamesward.com&quot;&gt;James Ward&lt;/a&gt;. While there wasn&apos;t as much trash talking as I&apos;d hoped, I enjoyed delivering it and disputing the greatness of Flex. Below is the presentation that James and I delivered.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;object width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=flexvsgwtsmackdown-100311234937-phpapp01&amp;stripped_title=flex-vs-gwt-smackdown&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=flexvsgwtsmackdown-100311234937-phpapp01&amp;stripped_title=flex-vs-gwt-smackdown&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/p&gt;
&lt;p&gt;The show itself was great this year. It had more attendees than I&apos;ve seen in a long time. There were a lot of really interesting sessions and and an often humorous &lt;a href=&quot;http://twitter.com/search?q=%23tssjs&quot;&gt;Twitter back-channel&lt;/a&gt;. I attended quite a few talks and jotted down my notes from several of them. Please see the links below if you&apos;re interested in the sessions I attended. You can view all of the presentations from TSSJS 2010 on &lt;a href=&quot;http://slideshare.net/javasymposium&quot;&gt;SlideShare&lt;/a&gt;.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/what_s_happening_in_the&quot;&gt;What&apos;s Happening in the Java World?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/software_quality_the_quest_for&quot;&gt;Software Quality: The Quest for the Holy Grail?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/the_cloud_computing_continuum_with&quot;&gt;The Cloud Computing Continuum with Bob McWhirter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/highly_interactive_software_with_java&quot;&gt;Highly Interactive Software with Java and Flex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/c_java_and_net_lessons&quot;&gt;C++, Java and .NET: Lessons Learned from the Internet Age&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/developing_rich_web_service_apis&quot;&gt;Developing Rich Web Service APIs with Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/what_s_new_in_spring&quot;&gt;What&apos;s New in Spring 3.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to everyone who came to Vegas and to &lt;a href=&quot;http://theserverside.com&quot;&gt;TheServerSide&lt;/a&gt; for an excellent conference.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/comparing_kick_ass_web_frameworks</guid>
    <title>Comparing Kick-Ass Web Frameworks at The Rich Web Experience</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/comparing_kick_ass_web_frameworks</link>
        <pubDate>Fri, 4 Dec 2009 08:16:48 -0700</pubDate>
    <category>Java</category>
    <category>jobs</category>
    <category>gwt</category>
    <category>richwebexperience</category>
    <category>richweb</category>
    <category>trends</category>
    <category>flex</category>
    <category>struts</category>
    <category>rails</category>
    <category>grails</category>
            <description>Yesterday, I delivered my &lt;a href=&quot;http://www.therichwebexperience.com/conference/orlando/2009/12/session?id=15951&quot;&gt;Comparing Kick-Ass Web Frameworks&lt;/a&gt; talk at the Rich Web Experience in Orlando, Florida. Below are the slides I used:&lt;/p&gt;
&lt;div style=&quot;text-align:center; margin-bottom: 10px&quot; id=&quot;__ss_2644393&quot;&gt;
&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=comparingkickasswebframeworks-091203145644-phpapp02&amp;stripped_title=comparing-kick-ass-web-frameworks&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=comparingkickasswebframeworks-091203145644-phpapp02&amp;stripped_title=comparing-kick-ass-web-frameworks&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;
&lt;p&gt;Although it&apos;s difficult to convey a presentation in a slide deck, I can offer you my conclusion: &lt;a href=&quot;http://java.dzone.com/news/there-no-best-web-framework&quot;&gt;there is no &quot;best&quot; web framework&lt;/a&gt;. I believe web frameworks are like &lt;a href=&quot;http://www.ted.com/talks/malcolm_gladwell_on_spaghetti_sauce.html&quot;&gt;spaghetti sauce&lt;/a&gt; in that everyone has different tastes and having so many choices is necessary to satisfy everyone. You can read more about the &lt;em&gt;plural nature of perfection&lt;/em&gt; in Malcolm Gladwell&apos;s &lt;a href=&quot;http://www.gladwell.com/2004/2004_09_06_a_ketchup.html&quot;&gt;The Ketchup Conundrum&lt;/a&gt; (a written version of &lt;a href=&quot;http://www.ted.com/talks/malcolm_gladwell_on_spaghetti_sauce.html&quot;&gt;What we can learn from spaghetti sauce&lt;/a&gt;). Even though there is no &quot;best&quot; web framework, I believe GWT, Flex, Rails and Grails are frameworks that every web developer should try. They really do make it fun to develop web applications.
&lt;/p&gt;
&lt;p&gt;You can find the slides for my other RWE talk at &lt;a href=&quot;http://raibledesigns.com/rd/entry/building_sofea_applications_with_gwt&quot;&gt;Building SOFEA Applications with GWT and Grails&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
Kudos to &lt;a href=&quot;http://www.nofluffjuststuff.com&quot;&gt;Jay Zimmerman&lt;/a&gt; for putting on a great show in Orlando this year. I had a great time talking with folks and learning in the sessions I attended. I particularly enjoyed bringing my parents and kids and staying at such a nice resort. Disney World (Magic Kingdom) and Universal Studios was very enjoyable due to the short lines. Also, the weather was perfect - especially considering the freezing cold in Denver this week. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gwt_oauth_and_linkedin_apis</guid>
    <title>GWT OAuth and LinkedIn APIs</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gwt_oauth_and_linkedin_apis</link>
        <pubDate>Tue, 24 Nov 2009 15:46:05 -0700</pubDate>
    <category>The Web</category>
    <category>api</category>
    <category>gwt</category>
    <category>oauth</category>
    <category>linkedin</category>
    <category>profile</category>
    <category>google</category>
    <category>twitter</category>
            <description>&lt;a href=&quot;http://www.linkedin.com&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/linkedin-logo.gif&quot; width=&quot;129&quot; height=&quot;36&quot; alt=&quot;LinkedIn Logo&quot; class=&quot;picture&quot; style=&quot;border: 0&quot; /&gt;&lt;/a&gt;
When I worked at LinkedIn last year, I received a lot of inquiries from friends and developers about LinkedIn&apos;s APIs. After a while, I started sending the following canned response:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
For API access to build LinkedIn features into your application, fill
out the following form:
&lt;br/&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&quot;http://www.linkedin.com/static?key=developers_apis&quot;&gt;http://www.linkedin.com/static?key=developers_apis&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
For requests to build an application, go to:
&lt;br/&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&quot;http://www.linkedin.com/static?key=developers_opensocial&quot;&gt;http://www.linkedin.com/static?key=developers_opensocial&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
I talked with the API team and they did say they look at every request that&apos;s sent via these forms. They don&apos;t respond to all of them b/c they know that many people would be angry if they told them &quot;no&quot;, so they&apos;d rather not have that headache.
&lt;/p&gt;
&lt;p&gt;Yesterday, I was pumped to see that they&apos;ve finally decided to &lt;a href=&quot;http://blog.linkedin.com/2009/11/23/linkedin-platform-launch/&quot;&gt;open up their API to Developers&lt;/a&gt;.
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Starting today, developers worldwide can integrate LinkedIn into their business applications and Web sites.  &lt;a href=&quot;http://developer.linkedin.com/&quot;&gt;Developer.linkedin.com&lt;/a&gt; is now &lt;strong&gt;live &lt;/strong&gt;and open for business.
&lt;/p&gt;
&lt;p&gt;First of all, congratulations to the API team on finally making this happen! I know it&apos;s no small feat. Secondly, it&apos;s great to see them using &lt;a href=&quot;http://www.jivesoftware.com/products&quot;&gt;Jive SBS&lt;/a&gt; for their API documentation and developer community. My current client uses this to facilitate development and I love how it integrates a wiki, JIRA, FishEye, Crucible and Bamboo into one central jumping off point.&lt;/p&gt;
&lt;p&gt;I&apos;ve always been a fan of LinkedIn, ever since I joined way back in &lt;a href=&quot;http://raibledesigns.com/rd/entry/happy_cinco_de_linko&quot;&gt;May 2003&lt;/a&gt;. However, I&apos;ve longed for a way to access my data. &lt;a href=&quot;http://developer.linkedin.com/community/widgets&quot;&gt;LinkedIn Widgets&lt;/a&gt; are nice, but there&apos;s something to be said for the full power of an API. Last night, I sat down for a couple hours and enhanced my &lt;a href=&quot;http://raibledesigns.com/rd/entry/implementing_oauth_with_gwt&quot;&gt;Implementing OAuth with GWT&lt;/a&gt; example to support LinkedIn&apos;s API.&lt;/p&gt;
&lt;p&gt;I&apos;m happy to report my experiment was a success and you can &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-oauth-1.2.zip&quot;&gt;download GWT OAuth 1.2&lt;/a&gt; or &lt;a href=&quot;http://demo.raibledesigns.com/gwt-oauth&quot;&gt;view it online&lt;/a&gt;. For now, I&apos;m simply &lt;a href=&quot;http://developer.linkedin.com/docs/DOC-1008&quot;&gt;authenticating with OAuth&lt;/a&gt; and accessing the &lt;a href=&quot;http://developer.linkedin.com/docs/DOC-1002&quot;&gt;Profile API&lt;/a&gt;. 
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;a href=&quot;http://demo.raibledesigns.com/gwt-oauth&quot; title=&quot;OAuth with GWT Demo&quot;&gt;&lt;img src=&quot;//farm3.static.flickr.com/2655/4132814004_b423779e59.jpg&quot; width=&quot;453&quot; height=&quot;326&quot; alt=&quot;OAuth with GWT&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;In the process, I learned a couple things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LinkedIn&apos;s OAuth implementation returns an &lt;a href=&quot;http://wiki.oauth.net/Signed-Callback-URLs&quot;&gt;oauth_verifier&lt;/a&gt; parameter after authenticating, whereas Google and Twitter do not. This parameter needs to be included when calling the &lt;em&gt;Access token path&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The Profile API example I implemented gets the current user&apos;s profile with &lt;a href=&quot;http://api.linkedin.com/v1/people/~&quot;&gt;http://api.linkedin.com/v1/people/~&lt;/a&gt;. This returns a &quot;light&quot; version of your profile. To get a more detailed version, you need to use &lt;a href=&quot;http://developer.linkedin.com/docs/DOC-1014&quot;&gt;Field Selectors&lt;/a&gt;. For example:
&lt;span style=&quot;display: block; margin: 5px 5px&quot;&gt;
&lt;a href=&quot;http://api.linkedin.com/v1/people/~:(id,first-name,last-name,picture-url,headline,summary,positions,educations)&quot;&gt;http://api.linkedin.com/v1/people/~:(id,first-name,last-name,picture-url,headline,summary,positions,educations)&lt;/a&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;LinkedIn&apos;s API only supports passing OAuth parameters in a header, rather than query parameters. To make this work, I modified my &lt;a href=&quot;http://raibledesigns.com/rd/entry/how_to_do_cross_domain#proxyServlet&quot;&gt;ProxyServlet&lt;/a&gt; to convert query parameters to an &quot;Authorization&quot; header at the end of the &lt;em&gt;setProxyRequestHeaders()&lt;/em&gt; method.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
// For LinkedIn&apos;s OAuth API, convert request parameters to an AuthorizationHeader
if (httpServletRequest.getRequestURL().toString().contains(&quot;linkedin-api&quot;)) {
    String&amp;#91;&amp;#93; parameters = httpServletRequest.getQueryString().split(&quot;&amp;amp;&quot;);
    StringBuilder sb = new StringBuilder(&quot;OAuth realm=\&quot;http://api.linkedin.com/\&quot;,&quot;);
    for (int i = 0; i &amp;lt; parameters.length; i++) {
        sb.append(parameters&amp;#91;i&amp;#93;);
        if (i &amp;lt; parameters.length - 1) {
            sb.append(&quot;,&quot;);
        }
    }

    Header authorization = new Header(&quot;Authorization&quot;, sb.toString());
    httpMethodProxyRequest.setRequestHeader(authorization);
}
&lt;/pre&gt;
&lt;p&gt;You might recall that my previous example had issues authenticating with Google, but worked well with Twitter. LinkedIn&apos;s authentication seems to work flawlessly. This leads me to believe that Twitter and LinkedIn have a much more mature OAuth implementation than Google.&lt;/p&gt;
&lt;p style=&quot;padding-top: 5px; border-top: 1px dotted silver; color: #666&quot;&gt;&lt;em&gt;&lt;strong&gt;Related OAuth News&lt;/strong&gt;: Apache Roller 5 will be shipping with OAuth support. See &lt;a href=&quot;http://rollerweblogger.org/roller&quot;&gt;Dave Johnson&apos;s&lt;/a&gt; &lt;a href=&quot;http://www.slideshare.net/snoopdave/whats-new-in-roller5&quot;&gt;What&apos;s New in Roller 5 presentation&lt;/a&gt; for more information.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update December 6, 2009:&lt;/strong&gt; I modified the gwt-oauth project to use GWT 1.7.1 and changed to the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;Maven GWT Plugin&lt;/a&gt; from Codehaus. &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-oauth-1.3.zip&quot;&gt;Download GWT OAuth 1.3&lt;/a&gt; or &lt;a href=&quot;http://demo.raibledesigns.com/gwt-oauth&quot;&gt;view it online&lt;/a&gt;.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/building_sofea_applications_with_gwt</guid>
    <title>Building SOFEA Applications with GWT and Grails</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/building_sofea_applications_with_gwt</link>
        <pubDate>Thu, 12 Nov 2009 09:30:09 -0700</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>evite</category>
    <category>sofea</category>
    <category>grails</category>
            <description>Last night, I spoke at the &lt;a href=&quot;http://denverjug.org&quot;&gt;Denver Java User Group&lt;/a&gt; meeting. The consulting panel with &lt;a href=&quot;http://www.ambientideas.com/blog/&quot;&gt;Matthew&lt;/a&gt;, &lt;a href=&quot;http://www.augusttechgroup.com/tim/blog/&quot;&gt;Tim&lt;/a&gt; and &lt;a href=&quot;http://www.jroller.com/JamesGoodwill/&quot;&gt;Jim&lt;/a&gt; 
a lot of fun and I enjoyed delivering my &lt;a href=&quot;http://raibledesigns.com/rd/entry/consulting_sofea_grails_and_gwt&quot;&gt;Building SOFEA Applications with GWT and Grails&lt;/a&gt; presentation for the first time. The talk was mostly a story about how we &lt;a href=&quot;http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt&quot;&gt;enhanced Evite.com with GWT and Grails&lt;/a&gt; and what we did to make both frameworks scale. I don&apos;t believe the presentation reflects the story format that well, but it&apos;s not about the presentation, it&apos;s about the delivery of it. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align:center&quot; id=&quot;__ss_2484656&quot;&gt;&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=sofeawithgwtandgrails-091112101640-phpapp01&amp;rel=0&amp;stripped_title=building-sofea-applications-with-gwt-and-grails&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;//static.slidesharecdn.com/swf/ssplayer2.swf?doc=sofeawithgwtandgrails-091112101640-phpapp01&amp;rel=0&amp;stripped_title=building-sofea-applications-with-gwt-and-grails&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;If you&apos;d like to hear the story about this successful SOFEA implementation at a high-volume site, I&apos;d recommend attending the &lt;a href=&quot;http://www.therichwebexperience.com&quot;&gt;Rich Web Experience&lt;/a&gt; next month. If you attended last night&apos;s meeting and have any feedback on how this talk can be improved, I&apos;d love to hear it.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/consulting_sofea_grails_and_gwt</guid>
    <title>Consulting, SOFEA, Grails and GWT at next week&apos;s Denver JUG</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/consulting_sofea_grails_and_gwt</link>
        <pubDate>Thu, 5 Nov 2009 22:52:37 -0700</pubDate>
    <category>Java</category>
    <category>consulting</category>
    <category>java</category>
    <category>denver</category>
    <category>gwt</category>
    <category>sofea</category>
    <category>grails</category>
    <category>denverjug</category>
            <description>Next Wednesday, I&apos;ll be at Denver&apos;s JUG meeting to talk about Independent Consulting and Building SOFEA Applications with Grails and GWT. The first talk will be a a panel discussion among local independent consultants, including &lt;a href=&quot;http://www.jroller.com/JamesGoodwill/&quot;&gt;James Goodwill&lt;/a&gt;, &lt;a href=&quot;http://www.ambientideas.com/blog/&quot;&gt;Matthew McCullough&lt;/a&gt;, &lt;a href=&quot;http://www.augusttechgroup.com/tim/blog/&quot;&gt;Tim Berglund&lt;/a&gt; and myself.
&lt;/p&gt;
&lt;p class=&quot;smokey&quot;&gt;
This session explores the trials and tribulations of an independent
consultant. How do you find contracts? Should you setup an LLC, an
S-Corp or just be a sole proprietorship? What about health insurance
and benefits? Are recruiters helpful or hurtful? Learn lots of tips
and tricks to get your dream job and your ideal lifestyle.
&lt;/p&gt;
&lt;p&gt;
The Grails and GWT talk is a preview of a talk I&apos;ll be doing at the &lt;a href=&quot;http://www.therichwebexperience.com/conference/speaker/topic_view?topicId=2104&quot;&gt;Rich Web Experience&lt;/a&gt; in December. Below is a rewrite of the abstract in first-person.
&lt;/p&gt;
&lt;p class=&quot;smokey&quot;&gt;Earlier this year, I participated in a major enhancement of a high-traffic well-known internet site. The company wanted us to quickly re-architect their site and use a modern Ajax framework to do it with. An Ajax Framework evaluation was done to help the team choose the best framework for their skillset. The application was built with a SOFEA architecture using GWT on the frontend and Grails/REST on the backend.
&lt;br/&gt;&lt;br/&gt;
This talk will cover how &lt;a href=&quot;http://www.linkedin.com/in/bryannoll&quot;&gt;Bryan Noll&lt;/a&gt;, &lt;a href=&quot;http://www.linkedin.com/in/scottthomasnicholls&quot;&gt;Scott Nicholls&lt;/a&gt;, &lt;a href=&quot;http://www.linkedin.com/in/jgoodwill&quot;&gt;James Goodwill&lt;/a&gt; and I came to choose GWT and Grails, as well as stumbling blocks we encountered along the way. In addition, we&apos;ll explore many topics such as raw GWT vs. GXT/SmartGWT, the Maven GWT Plugin, modularizing your code, multiple EntryPoints, MVP, integration testing and JSON parsing with Overlay Types. 
&lt;/p&gt;
&lt;p&gt;If you&apos;re in Denver next Wednesday night (November 11th), you should stop by the &lt;a href=&quot;http://www.denverjug.org/&quot;&gt;Denver JUG&lt;/a&gt; meeting. It&apos;ll be a fun night and there&apos;s sure to be a few beers afterward. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/testing_gwt_libraries_with_selenium</guid>
    <title>Testing GWT Libraries with Selenium and Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/testing_gwt_libraries_with_selenium</link>
        <pubDate>Wed, 4 Nov 2009 22:09:27 -0700</pubDate>
    <category>Java</category>
    <category>maven-dependencies-plugin</category>
    <category>maven</category>
    <category>gwt</category>
    <category>cargo</category>
    <category>gwt-maven-plugin</category>
    <category>java</category>
    <category>selenium</category>
            <description>On Tuesday, I wrote about &lt;a href=&quot;http://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt&quot;&gt;Running Hosted Mode in GWT Libraries&lt;/a&gt;.  Today I added an additional module to our project to run Selenium tests against our GWT library. In the process, I discovered some things I needed to modify in my GWT library&apos;s pom.xml. I&apos;m writing this post so others can use this setup to write GWT libraries and package them for testing with Selenium.
&lt;/p&gt;
&lt;p&gt;First of all, I noticed that when you&apos;re using the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;GWT Maven Plugin&lt;/a&gt; with a JAR project, it doesn&apos;t automatically run gwt:compile or gwt:test in the compile and test phases. I had to explicitly configure the &lt;em&gt;compile&lt;/em&gt; goal to run in the &lt;em&gt;compile&lt;/em&gt; phase. I also had to add &amp;lt;webappDirectory&amp;gt; to the configuration to compile the JavaScript files into the &lt;em&gt;war&lt;/em&gt; directory.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&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;module&amp;gt;org.appfuse.gwt.core.CoreUI&amp;lt;/module&amp;gt;
        &amp;lt;runTarget&amp;gt;index.html&amp;lt;/runTarget&amp;gt;
        &amp;lt;webappDirectory&amp;gt;war&amp;lt;/webappDirectory&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;compile&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;compile&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;p&gt;To package the generated JavaScript and index.html in the JAR, I added the following &amp;lt;resources&amp;gt; section to the maven-resources-plugin configuration I mentioned in my &lt;a href=&quot;http://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;resource&amp;gt;
    &amp;lt;directory&amp;gt;war&amp;lt;/directory&amp;gt;
    &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;core.ui/**&amp;lt;/include&amp;gt;
        &amp;lt;include&amp;gt;index.html&amp;lt;/include&amp;gt;
    &amp;lt;/includes&amp;gt;
&amp;lt;/resource&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
In addition, I discovered some javax.servlet.* classes in my JAR after running &quot;mvn package&quot;. I believe this is caused by the GWT plugin sucking these in when it compiles my ProxyServlet. I excluded them by adding the maven-jar-plugin.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jar-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;excludes&amp;gt;
            &amp;lt;exclude&amp;gt;javax/servlet/**&amp;lt;/exclude&amp;gt;
        &amp;lt;/excludes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;After doing this, I was able to publish my JAR with all the contents I needed to run Selenium tests against it. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Testing the GWT Library with Selenium&lt;/strong&gt;&lt;br/&gt;
The module that contains the Selenium tests is a WAR project that uses war overlays, Cargo and Selenium RC. You can read about the Maven setup I use for running Selenium tests in &lt;a href=&quot;http://raibledesigns.com/rd/entry/packaging_a_sofea_application_for&quot;&gt;Packaging a SOFEA Application for Distribution&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
The major difference when testing a JAR (vs. a WAR), is I had to use the &lt;a href=&quot;http://maven.apache.org/plugins/maven-dependency-plugin/&quot;&gt;maven-dependency-plugin&lt;/a&gt; to unpack the JAR so its contents would get included in the WAR for testing. Below is the configuration I used to accomplish this:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;unpack&amp;lt;/id&amp;gt;
            &amp;lt;phase&amp;gt;generate-sources&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;unpack&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;artifactItems&amp;gt;
                    &amp;lt;artifactItem&amp;gt;
                        &amp;lt;groupId&amp;gt;org.appfuse&amp;lt;/groupId&amp;gt;
                        &amp;lt;artifactId&amp;gt;gwt-core&amp;lt;/artifactId&amp;gt;
                        &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
                        &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
                        &amp;lt;overWrite&amp;gt;false&amp;lt;/overWrite&amp;gt;
                        &amp;lt;excludes&amp;gt;META-INF/**,org/**,javax/**&amp;lt;/excludes&amp;gt;
                    &amp;lt;/artifactItem&amp;gt;
                &amp;lt;/artifactItems&amp;gt;
                &amp;lt;outputDirectory&amp;gt;
                    ${project.build.directory}/${project.build.finalName}
                &amp;lt;/outputDirectory&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Hopefully this will help you develop GWT libraries and run Selenium tests against them. If you have any suggestions for simplifying this configuration, please let me know.&lt;/p&gt;
&lt;div style=&quot;padding-top: 5px; border-top: 1px dotted silver; color: #666&quot;&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; I did considering a couple of other options for running Selenium tests against our GWT library:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add something to the existing project that 1) creates a WAR and 2) fires up Cargo/Selenium in a profile to test it.
&lt;/li&gt;
&lt;li&gt;Create the tests in a GWT (war) project that includes widgets from the library.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I decided on the solution documented above because it seemed like the best option.&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;

</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt</guid>
    <title>Running Hosted Mode in GWT Libraries (when using Maven)</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt</link>
        <pubDate>Tue, 3 Nov 2009 09:37:07 -0700</pubDate>
    <category>Java</category>
    <category>hostedmode</category>
    <category>maven</category>
    <category>resources</category>
    <category>gwt-maven-plugin</category>
    <category>java</category>
    <category>ant</category>
    <category>gwt</category>
    <category>maven-gwt-plugin</category>
            <description>Earlier this year, I wrote about &lt;a href=&quot;http://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt&quot;&gt;Modularizing GWT Applications with GWT-Maven&lt;/a&gt;. Fast forward 8 months and I&apos;m still working with GWT and using this same technique. However, this time I&apos;m working with the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;Maven GWT Plugin&lt;/a&gt; from Codehaus. In my last post, I wrote:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
The results of modularizing your application are beneficial (shared code) and detrimental (you have to &lt;code&gt;mvn install&lt;/code&gt; gwt-core whenever you make changes in shared classes). If you know of a way to configure the gwt-maven plugin to read sources from both gwt-core and gwt-webapp in hosted mode, I&apos;d love to hear about it. 
&lt;/p&gt;
&lt;p&gt;The good news is I found a solution for this, using the &lt;a href=&quot;http://mojo.codehaus.org/build-helper-maven-plugin/&quot;&gt;Builder Helper Maven Plugin&lt;/a&gt;. The GWT Maven Plugin&apos;s &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/user-guide/productivity.html&quot;&gt;
Productivity tip for multi-project setup&lt;/a&gt; has more information on how to configure this (note: we use IntelliJ and Eclipse on my project and did not need to configure this in a profile).&lt;/p&gt;
&lt;p&gt;
All was fine and dandy with this configuration until I wanted to be able to run hosted mode to develop/test everything in my library before including it in my main project. Luckily, you can still run &lt;strong&gt;mvn gwt:run&lt;/strong&gt; on a JAR project. However, when you configure your pom.xml so sources are included in your JAR, you run into an issue: your *.java files will be copied to &lt;em&gt;war/WEB-INF/classes&lt;/em&gt; and hosted mode will use these files as source rather than the ones you&apos;re editing in &lt;em&gt;src/main/java&lt;/em&gt;. 
&lt;/p&gt;
&lt;p&gt;To solve this, I changed my pom.xml to do two things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Only copy resources right before packaging (in the test phase).&lt;/li&gt;
&lt;li&gt;When packaging is complete, delete the *.java files from &lt;em&gt;war/WEB-INF/classes&lt;/em&gt; (using Ant).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below is the XML I used to make this possible. Please let me know if you have a way to simplify this configuration.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.4.1&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;test&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;outputDirectory&amp;gt;${project.build.outputDirectory}&amp;lt;/outputDirectory&amp;gt;
                &amp;lt;resources&amp;gt;
                    &amp;lt;resource&amp;gt;
                        &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
                    &amp;lt;/resource&amp;gt;
                    &amp;lt;resource&amp;gt;
                        &amp;lt;directory&amp;gt;src/main/resources&amp;lt;/directory&amp;gt;
                    &amp;lt;/resource&amp;gt;
                &amp;lt;/resources&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-antrun-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.3&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;tasks&amp;gt;
                    &amp;lt;delete&amp;gt;
                        &amp;lt;fileset dir=&quot;${project.build.outputDirectory}&quot; includes=&quot;**/*.java&quot;/&amp;gt;
                    &amp;lt;/delete&amp;gt;
                &amp;lt;/tasks&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This solution seems to work pretty well. As far as developing your library in hosted mode, you&apos;ll need to configure two *.gwt.xml files, one that doesn&apos;t have an &amp;lt;entry-point&amp;gt; defined and one that does. Configure the one with the entry point as the &amp;lt;module&amp;gt; in your gwt-maven-plugin configuration.&lt;/p&gt;
&lt;p&gt;As a side note, I found a few issues with the 1.1 version of the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/user-guide/archetype.html&quot;&gt;Maven GWT Archetype&lt;/a&gt;. Below are the steps I used to fix these issues and upgrade to GWT 1.7.0 (I realize 1.7.1 is out, but gwt-dev-1.7.1-mac.jar &lt;a href=&quot;http://repo2.maven.org/maven2/com/google/gwt/gwt-dev/1.7.1/&quot;&gt;doesn&apos;t exist in Maven central&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;First, create a new project by running the following from the command line:

&lt;pre&gt;
mvn archetype:generate \
  -DarchetypeGroupId=org.codehaus.mojo \
  -DarchetypeArtifactId=gwt-maven-plugin \
  -DarchetypeVersion=1.1 \
  -DgroupId=com.yourcompany \
  -DartifactId=gwt-project -Dversion=1.0-SNAPSHOT -B
&lt;/pre&gt;
&lt;p&gt;
After creating the project, you&apos;ll need to modify the pom.xml as follows:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change the gwt-maven-plugin&apos;s version to &lt;strong&gt;1.1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Change the ${gwtVersion} property to &lt;strong&gt;1.7.0&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;&amp;lt;runTarget&gt;Application.html&amp;lt;/runTarget&gt;&lt;/code&gt; to the &amp;lt;configuration&amp;gt; element of the plugin.&lt;/li&gt;
&lt;li&gt;Move Application.html and web.xml so they&apos;re under the &quot;war&quot; directory.&lt;/li&gt;
&lt;li&gt;Update Application.html to prepend the GWT module name in the &amp;lt;script&amp;gt; tag.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I hope these instructions help you create modular GWT projects with Maven. This setup is working great on my current project.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/developing_and_testing_gwt_client</guid>
    <title>Developing and Testing GWT Client Services</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/developing_and_testing_gwt_client</link>
        <pubDate>Wed, 21 Oct 2009 06:55:17 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>requestbuilder</category>
    <category>junit</category>
    <category>gwtinpractice</category>
    <category>testing</category>
    <category>gwttestcase</category>
    <category>rest</category>
    <category>restygwt</category>
            <description>Earlier this week, Hiram Chirino released &lt;a href=&quot;http://github.com/chirino/resty-gwt&quot;&gt;RestyGWT&lt;/a&gt;, a GWT generator for REST services and JSON encoded data transfer objects. You can read more about it in Hiram&apos;s post &lt;a href=&quot;http://hiramchirino.com/blog/2009/10/restygwt-a-better-gwt-rpc/&quot;&gt;RestyGWT, a Better GWT RPC??&lt;/a&gt;. First of all, I&apos;m impressed with RestyGWT because provides something I&apos;ve always wanted with GWT: the ability to call RESTful services and get a populated POJO in your callback, much like &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/user/client/rpc/AsyncCallback.html&quot;&gt;AsyncCallback&lt;/a&gt; provides for RPC services. &lt;/p&gt;
&lt;p&gt;RestyGWT also allows you to easily create services using only interfaces and JAX-RS annotations. For example:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
import javax.ws.rs.POST;
...
public interface PizzaService extends RestService {
    @POST
    public void order(PizzaOrder request, MethodCallback&amp;lt;OrderConfirmation&amp;gt; callback);
}
&lt;/pre&gt;
&lt;p&gt;
After taking a brief look at RestyGWT, I thought it&apos;d be interesting to share how I develop and test GWT client services.
&lt;/p&gt;
&lt;p id=&quot;developing&quot;&gt;&lt;strong&gt;Developing GWT Client Services&lt;/strong&gt;&lt;br/&gt;
Writing services in a GWT application can be helpful when you&apos;re using MVP, especially since you can &lt;a href=&quot;http://googletesting.blogspot.com/2009/08/tott-testing-gwt-without-gwttest.html&quot;&gt;EasyMock them in a test&lt;/a&gt;. On my GWT projects, I&apos;ve often used &lt;a href=&quot;http://raibledesigns.com/rd/entry/json_parsing_with_javascript_overlay&quot;&gt;overlay types&lt;/a&gt; because they allow me to write less code and they make parsing JSON super simple. 
I&apos;ve &lt;a href=&quot;http://raibledesigns.com/rd/entry/building_gwt_applications_with_mvp&quot;&gt;had issues&lt;/a&gt; testing my presenters when using overlay types. The good news is I think I&apos;ve figured out a reasonable solution, but it does require using GWTTestCase. If RestyGWT supported overlay types, there&apos;s a good chance I&apos;d use it, especially since its  &lt;a href=&quot;http://github.com/chirino/resty-gwt/tree/master/src/it/resty-gwt-example/src/test/java/com/hiramchirino/restygwt/examples/client/&quot;&gt;integration tests&lt;/a&gt; seem to require GWTTestCase too.
&lt;/p&gt;
&lt;p&gt;Rather than using callbacks in my presenters, I try to only use them in my service implementations. That way, my presenters don&apos;t have to worry about overlay types and can be tested in a JUnit-only fashion. The callbacks in my services handle JSON parsing/object population and fire events with the populated objects. 
&lt;/p&gt;
&lt;p&gt;
GWT&apos;s &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/http/client/RequestBuilder.html&quot;&gt;RequestBuilder&lt;/a&gt; is one option for communicating with RESTful services. The &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/DevGuideHttpRequests&quot;&gt;Development Guide for HTTP Requests&lt;/a&gt; explains how to use this class. To simplify REST requests and allow multiple callbacks, I&apos;m using a &lt;strong&gt;RestRequest&lt;/strong&gt; class, and a number of other utility classes that make up a small GWT REST framework (created by a former colleague). &lt;!--good friend of mine, Dan Mesh. Unfortunately, Dan doesn&apos;t have a blog to link to; you&apos;ll have to trust me that he&apos;s a smart guy and a lot of fun to work with.--&gt; RestRequest wraps RequestBuilder and provides a &lt;a href=&quot;http://martinfowler.com/bliki/FluentInterface.html&quot;&gt;Fluent API&lt;/a&gt; for executing HTTP requests. Another class, &lt;strong&gt;Deferred&lt;/strong&gt;, is a GWT implementation of &lt;a href=&quot;http://twistedmatrix.com/projects/core/documentation/howto/defer.html&quot;&gt;Twisted&apos;s Deferred&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;As part of my service implementation, I inject an EventBus (with &lt;a href=&quot;http://code.google.com/p/google-gin/&quot;&gt;GIN&lt;/a&gt;) into the constructor and then proceed to implement callbacks that fire Events to indicate loading, saving and deleting has succeeded. Here&apos;s an example service:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class ConversationServiceImpl implements ConversationService {
    private EventBus eventBus;

    @Inject
    public ConversationServiceImpl(EventBus eventBus) {
        this.eventBus = eventBus;
    }

    public void getConversation(String name) {
        Deferred&amp;lt;Representation&amp;gt; d =
                RestRequest.get(URLs.CONVERSATION + &quot;/&quot; + URL.encode(name)).build();

        d.addCallback(new Callback&amp;lt;Representation&amp;gt;() {
            public void onSuccess(Representation result) {
                Conversation conversation = convertResultToConversation(result);
                eventBus.fireEvent(new ResourceLoadedEvent&amp;lt;Conversation&amp;gt;(conversation));
            }
        });

        d.run();
    }

    public void saveConversation(Conversation conversation) {
        Deferred&amp;lt;Representation&amp;gt; d = RestRequest.post(URLs.CONVERSATION)
                .setRequestData(conversation.toJson()).build();
        
        d.addCallback(new Callback&amp;lt;Representation&amp;gt;() {
            public void onSuccess(Representation result) {
                Conversation conversation = convertResultToConversation(result);
                eventBus.fireEvent(new ResourceSavedEvent&amp;lt;Conversation&amp;gt;(conversation));
            }
        });

        d.run();
    }

    public void deleteConversation(Long id) {
        Deferred&amp;lt;Representation&amp;gt; d =
                RestRequest.post(URLs.CONVERSATION + &quot;/&quot; + id).build();

        d.addCallback(new Callback&amp;lt;Representation&amp;gt;() {
            public void onSuccess(Representation result) {
                eventBus.fireEvent(new ResourceDeletedEvent());
            }
        });

        d.run();
    }

    /**
     * Convenience method to populate object in one location
     *
     * @param result the result of a resource request.
     * @return the populated object.
     */
    private Conversation convertResultToConversation(Representation result) {
        JSOModel model = JSOModel.fromJson(result.getData());
        return new Conversation(model);
    }
}
&lt;/pre&gt;
&lt;p&gt;In the &lt;em&gt;saveConversation()&lt;/em&gt; method you&apos;ll notice the &lt;em&gt;conversation.toJson()&lt;/em&gt; method call. This method uses a JSON class that loops through an objects properties and constructs a JSON String.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public JSON toJson() {
    return new JSON(getMap());
}
&lt;/pre&gt;
&lt;p id=&quot;testing&quot;&gt;&lt;strong&gt;Testing Services&lt;/strong&gt;&lt;br/&gt;
In my experience, the hardest part about using overlay types is writing your objects so they get populated correctly. I&apos;ve found that writing tests which read JSON from a file can be a great productivity boost. However, because of overlay types, you have to write a test that extends GWTTestCase. When using GWTTestCase, you can&apos;t simply read from the filesystem. The good news is there is a workaround where you can subclass GWTShellServlet and overwrite GWT&apos;s web.xml to have your own servlet that &lt;em&gt;can&lt;/em&gt; read from the filesystem. A detailed explanation of how to do this was written by Alex Moffat in &lt;a href=&quot;http://development.lombardi.com/?p=15&quot;&gt;Implementing a -noserver flag for GWTTestCase&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;Once this class is in place, I&apos;ve found you can easily write services using TDD and the server doesn&apos;t even have to exist. When constructing services, I&apos;ve found the following workflow to be the most productive:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a file with the expected JSON in src/test/resources/&lt;em&gt;resource&lt;/em&gt;.json where &lt;em&gt;resource&lt;/em&gt; matches the last part of the URL for your service.&lt;/li&gt;
&lt;li&gt;Create a *ServiceGwtTest.java and write tests.&lt;/li&gt;
&lt;li&gt;Run tests to make sure they fail.&lt;/li&gt;
&lt;li&gt;Implement the service and run tests to ensure JSON is getting consumed/produced properly to/from model objects.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below is the code for my JsonReaderServlet.java:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class JsonReaderServlet extends GWTShellServlet {

    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException {

        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        String uri = req.getRequestURI();
        if (req.getQueryString() != null) {
            uri += &quot;?&quot; + req.getQueryString();
        }

        if (uri.contains(&quot;/services&quot;)) {
            String method = req.getMethod();
            String output;

            if (method.equalsIgnoreCase(&quot;get&quot;)) {
                // use the part after the last slash as the filename
                String filename = uri.substring(uri.lastIndexOf(&quot;/&quot;) + 1, uri.length()) + &quot;.json&quot;;
                System.out.println(&quot;loading: &quot; + filename);
                String json = readFileAsString(&quot;/&quot; + filename);
                System.out.println(&quot;loaded json: &quot; + json);
                output = json;
            } else {
                // for posts, return the same body content
                output = getBody(req);
            }

            PrintWriter out = resp.getWriter();
            out.write(output);
            out.close();

            resp.setStatus(HttpServletResponse.SC_OK);
        } else {
            super.service(servletRequest, servletResponse);
        }
    }

    private String readFileAsString(String filePath) throws IOException {
        filePath = getClass().getResource(filePath).getFile();
        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        return getStringFromReader(reader);
    }

    private String getBody(ServletRequest request) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        return getStringFromReader(reader);
    }

    private String getStringFromReader(Reader reader) throws IOException {
        StringBuilder sb = new StringBuilder();
        char[] buf = new char[1024];
        int numRead;
        while ((numRead = reader.read(buf)) != -1) {
            sb.append(buf, 0, numRead);
        }
        reader.close();
        return sb.toString();
    }
}
&lt;/pre&gt;
&lt;p&gt;This servlet is mapped to &lt;code&gt;&amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;/code&gt; in a web.xml file in src/test/resources/com/google/gwt/dev/etc/tomcat/webapps/ROOT/WEB-INF.&lt;/p&gt;
&lt;p&gt;My Service Test starts by getting an EventBus from GIN and registering itself to handle the fired events.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class ConversationServiceGwtTest extends AbstractGwtTestCase
        implements ResourceLoadedEvent.Handler, ResourceSavedEvent.Handler, ResourceDeletedEvent.Handler {
    ConversationService service;
    ResourceLoadedEvent&amp;lt;Conversation&amp;gt; loadedEvent;
    ResourceSavedEvent&amp;lt;Conversation&amp;gt; savedEvent;
    ResourceDeletedEvent deletedEvent;

    @Override
    public void gwtSetUp() throws Exception {
        super.gwtSetUp();
        DesigntimeGinjector injector = GWT.create(MyGinjector.class);
        EventBus eventBus = injector.getEventBus();
        service = new ConversationServiceImpl(eventBus);
        eventBus.addHandler(ResourceLoadedEvent.ENGINE, this);
        eventBus.addHandler(ResourceSavedEvent.ENGINE, this);
        eventBus.addHandler(ResourceDeletedEvent.ENGINE, this);
    }

    @SuppressWarnings(&quot;unchecked&quot;)
    public void onLoad(ResourceLoadedEvent event) {
        this.loadedEvent = event;
    }

    @SuppressWarnings(&quot;unchecked&quot;)
    public void onSave(ResourceSavedEvent event) {
        this.savedEvent = event;
    }

    public void onDelete(ResourceDeletedEvent event) {
        this.deletedEvent = event;
    }
}
&lt;/pre&gt;
&lt;p&gt;After this groundwork has been done, a test can be written that loads up the JSON file and verifies the objects are populated correctly.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void testGetConversation() {

    service.getConversation(&quot;test-conversation&quot;);

    Timer t = new Timer() {
        public void run() {
            assertNotNull(&quot;ResourceLoadedEvent not received&quot;, loadedEvent);
            Conversation conversation = loadedEvent.getResource();
            assertEquals(&quot;Conversation name is incorrect&quot;,&quot;Test Conversation&quot;, conversation.getName());

            assertNotNull(&quot;Conversation has no channel&quot;, conversation.getChannel());
            assertEquals(&quot;Conversation has incorrect task size&quot;, 3, conversation.getTasks().size());

            convertToAndFromJson(conversation);
            finishTest();
        }
    };

    delayTestFinish(3000);
    t.schedule(100);
}

private void convertToAndFromJson(Conversation fromJsonModel) {
    Representation json = fromJsonModel.toJson();
    assertNotNull(&quot;Cannot convert empty JSON&quot;, json.getData());

    // change back into model
    JSOModel data = JSOModel.fromJson(json.getData());
    Conversation toJsonModel = new Conversation(data);
    verifyModelBuiltCorrectly(toJsonModel);
}

private void verifyModelBuiltCorrectly(Conversation model) {
    assertEquals(&quot;Conversation name is incorrect&quot;, &quot;Test Conversation&quot;, model.getString(&quot;name&quot;));
    assertEquals(&quot;Conversation has incorrect task size&quot;, 3, model.getTasks().size());
    assertEquals(&quot;Conversation channel is incorrect&quot;, &quot;Web&quot;, model.getChannel().getString(&quot;type&quot;));
}
&lt;/pre&gt;
&lt;p&gt;For more information on the usage of the Timer, &lt;em&gt;finishTest()&lt;/em&gt; and &lt;em&gt;delayTestFinish()&lt;/em&gt;, see &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/junit/client/GWTTestCase.html#delayTestFinish%28int%29&quot;&gt;GWTTestCase&apos;s javadoc&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
The tests for saving and deleting a resource look as follows:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void testSaveConversation() {
    Conversation conversation = new Conversation().setName(&quot;Test&quot;).setId(&quot;1&quot;);

    List&amp;lt;Task&amp;gt; tasks = new ArrayList&amp;lt;Task&amp;gt;();
    for (int i = 1; i &amp;lt; 4; i++) {
        tasks.add(new Task().setName(&quot;Task &quot; + i));
    }
    conversation.setTasks(tasks);

    System.out.println(&quot;conversation.toJson(): &quot; + conversation.toJson());

    assertTrue(conversation.toJson().toString().contains(&quot;Task 1&quot;));

    service.saveConversation(conversation);

    Timer t = new Timer() {
        public void run() {
            assertNotNull(&quot;ResourceSavedEvent not received&quot;, savedEvent);
            finishTest();
        }
    };

    delayTestFinish(3000);
    t.schedule(100);
}
  
public void testDeleteConversation() {
    service.deleteConversation(1L);

    Timer t = new Timer() {
        public void run() {
            assertNotNull(&quot;ResourceDeletedEvent not received&quot;, deletedEvent);
            finishTest();
        }
    };

    delayTestFinish(3000);
    t.schedule(100);
}
&lt;/pre&gt;
&lt;p id=&quot;summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br/&gt;This article has shown you how I develop and test GWT Client Services. If RestyGWT supported overlay types, there&apos;s a good chance I could change my service implementation to use it and I wouldn&apos;t have to change my test. &lt;a href=&quot;http://www.screaming-penguin.com/&quot;&gt;Robert Cooper&lt;/a&gt;, author of &lt;a href=&quot;http://www.manning.com/cooper/&quot;&gt;GWT in Practice&lt;/a&gt;, claims he &lt;a href=&quot;http://twitter.com/kebernet/status/4997144279&quot;&gt;has a framework that does this&lt;/a&gt;. Here&apos;s to hoping this article stimulates the GWT ecosystem and we get a GWT REST framework that&apos;s as easy to use as GWT RPC.
&lt;/p&gt;
&lt;p id=&quot;update&quot;&gt;&lt;strong&gt;Update:&lt;/strong&gt; Today I enhanced this code to use Generics-based classes (inspired by &lt;a href=&quot;http://www.ibm.com/developerworks/java/library/j-genericdao.html&quot;&gt;Don&apos;t repeat the DAO!&lt;/a&gt;) for the boiler-plate CRUD code in a service. In a nutshell, a service interface can now be written as:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public interface FooService extends GenericService&amp;lt;Foo, String&amp;gt; {
 
}
&lt;/pre&gt;
&lt;p&gt;The implementation class is responsible for the URL and converting the JSON result to an object:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class FooServiceImpl extends GenericServiceImpl&amp;lt;Foo, String&amp;gt; implements FooService {

    @Inject
    public FooServiceImpl(EventBus eventBus) {
        super(eventBus, &quot;/services/foo&quot;);
    }

    @Override
    protected Foo convertResultToModel(Representation result) {
        return new Foo(JSOModel.fromJson(result.getData()));
    }
}
&lt;/pre&gt;
&lt;p&gt;I&apos;m sure this can be further enhanced to get rid of the need to create classes altogether, possibly leveraging &lt;a href=&quot;http://code.google.com/p/google-gin/&quot;&gt;GIN&lt;/a&gt; or some sort of factory. The parent classes referenced in this code can be viewed at the following URLs:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://gist.github.com/216495&quot;&gt;GenericService.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gist.github.com/216496&quot;&gt;GenericServiceImpl.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s also a &lt;a href=&quot;http://gist.github.com/216497&quot;&gt;GenericServiceGwtTest.java&lt;/a&gt; that proves it all works as expected.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/what_would_you_like_to</guid>
    <title>What would you like to see at TSSJS 2010?</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/what_would_you_like_to</link>
        <pubDate>Mon, 12 Oct 2009 11:28:21 -0600</pubDate>
    <category>Java</category>
    <category>tssjs</category>
    <category>vegas</category>
    <category>java</category>
    <category>gwt</category>
    <category>jvm</category>
    <category>theserverside</category>
    <category>conference</category>
    <category>flex</category>
            <description>&lt;a href=&quot;http://static.raibledesigns.com/repository/images/thevenetian.jpg&quot; rel=&quot;lightbox&quot; title=&quot;The Venetian&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/thevenetian_sm.jpg&quot; class=&quot;picture&quot; alt=&quot;The Venetian&quot; height=&quot;98&quot; width=&quot;130&quot;&gt;&lt;/a&gt;
A couple months ago, I was asked by &lt;a href=&quot;http://www.theserverside.com/&quot;&gt;TheServerSide&lt;/a&gt; to speak at next year&apos;s &lt;a href=&quot;http://javasymposium.techtarget.com/&quot;&gt;TheServerSide Java Symposium&lt;/a&gt; in Las Vegas. In addition, they asked me to help them evaluate presentation proposals and suggest topics/speakers. 
&lt;/p&gt;
&lt;p&gt;
First of all, I think the biggest thing that TSSJS could do to improve is to host more networking events. With the &lt;a href=&quot;http://java.dzone.com/news/fate-javaone-community-round&quot;&gt;JavaOne Party being over&lt;/a&gt;, I think there&apos;s a tremendous opportunity to fill a gap in the networking needs of the Java Community. When I &lt;a href=&quot;http://raibledesigns.com/rd/entry/tssjs_bof_web_framework_sweet&quot;&gt;first attended TSSJS in 2006&lt;/a&gt;, there were a fair amount of parties and everyone got to interact quite a bit. &lt;a href=&quot;http://raibledesigns.com/rd/entry/java_web_framework_smackdown_at&quot;&gt;In 2008&lt;/a&gt;, there were no networking events. I believe having a strong networking story would attract a lot more attendees, companies and sponsors.
&lt;/p&gt;
&lt;p&gt;Secondly, I think it&apos;s possible that TSSJS has too many server-side related sessions. IMO, the server-side (and middleware in general) isn&apos;t that exciting. TechTarget appears to own &lt;a href=&quot;http://theclientside.com&quot;&gt;TheClientSide&lt;/a&gt;, so why not add some more client-side stuff to the mix? For example, I&apos;d love to see a Struts 1 app-makeover using different technologies (for example, Flex, GWT and jQuery). I think HTML5 and Google Wave&apos;s Architecture sessions would be interesting too. If adding client-side sessions is too far away from TheServerSide, maybe it should be renamed to TheServerSide JVM Symposium and there can be all kinds of sessions on JVM languages (e.g. Scala, JRuby, Groovy) and all the great things those languages can accomplish.
&lt;/p&gt;
&lt;p&gt;Lastly, I&apos;ve been asked to send a couple session proposals. Currently, I&apos;m thinking about a doing GWT vs. Flex Smackdown with &lt;a href=&quot;http://www.jamesward.com/blog/&quot;&gt;James Ward&lt;/a&gt;, but I&apos;m open to other ideas. It&apos;s been quite awhile since I did a &quot;Comparing Web Frameworks&quot; talk. Maybe &quot;Hot Web Frameworks for 2010&quot; is more appropriate? I also think it&apos;d be interesting to do a somewhat philosophical talk on &quot;The State of Web Frameworks&quot; and where we&apos;re headed in the next year.&lt;/p&gt;
&lt;p&gt;What would make &lt;em&gt;you&lt;/em&gt; want to attend TSSJS next year? Let me know your thoughts and I&apos;ll do my best to make them a reality.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update October 22, 2009:&lt;/strong&gt; Whoo hoo! It looks like &lt;a href=&quot;http://www.theserverside.com/news/thread.tss?thread_id=58300&quot;&gt;TheClientSide&lt;/a&gt; &lt;em&gt;will&lt;/em&gt; be a part of TSSJS Vegas next year. Should be a great show.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/packaging_a_sofea_application_for</guid>
    <title>Packaging a SOFEA Application for Distribution</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/packaging_a_sofea_application_for</link>
        <pubDate>Tue, 6 Oct 2009 01:17:38 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>selenium</category>
    <category>sofea</category>
    <category>tomcat</category>
    <category>maven</category>
    <category>waroverlays</category>
            <description>The project I&apos;m working on is a bit different from those I&apos;m used to. I&apos;m used to working on web applications that are hosted on servers and customers access with their browser. &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_as_a_service&quot;&gt;SaaS&lt;/a&gt; if you will. My current client is different. They&apos;re a product company that sells applications and distributes them to customers via download and CD. Their customers install these applications on internal servers (supported servers include WebSphere, WebLogic and Tomcat).
&lt;/p&gt;
&lt;p&gt;
The product I&apos;m currently working on is structured as a &lt;a href=&quot;http://raibledesigns.com/rd/entry/re_life_above_the_service&quot; title=&quot;Service Oriented Front End Architecture&quot;&gt;SOFEA&lt;/a&gt; application and therefore consists of two separate modules - a backend and a frontend. Since it&apos;s installed in a servlet container, both modules are WARs and can be installed separately. 
&lt;/p&gt;
&lt;p&gt;
Building the backend and frontend as separate projects makes a lot of sense for two reasons:
&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;In development, different teams can work on the frontend and backend projects.&lt;/li&gt;
&lt;li&gt;Having them as separate projects allows them to be versioned separately.
&lt;/ul&gt;
&lt;p&gt;However, having them as two separate projects does make it a bit more difficult for distribution. I&apos;m writing this post to show you how I recently added support for distributing our application as 2 WARs &lt;em&gt;or&lt;/em&gt; 1 WAR using the power of Maven, war overlays and the &lt;a href=&quot;http://www.tuckey.org/urlrewrite/&quot;&gt;UrlRewriteFilter&lt;/a&gt;. 
&lt;/p&gt;
&lt;p id=&quot;projectsetup&quot;&gt;&lt;strong&gt;Project Setup&lt;/strong&gt;&lt;br/&gt;
First of all, we have several different Maven modules, but the most important ones are as follows:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;product-services&lt;/li&gt;
&lt;li&gt;product-client&lt;/li&gt;
&lt;li&gt;product-integration-tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, our modules aren&apos;t really named &quot;product&quot;, but you get the point. The services project is really just a WAR project with Spring Security configured. It depends on other JAR modules that the services exist in. The client project is a GWT WAR that has a proxy servlet defined in its web.xml that makes it easier to develop. It also contains some UrlRewrite configuration that allows &lt;a href=&quot;http://code.google.com/p/gwt-log/&quot;&gt;GWT Log&apos;s&lt;/a&gt; Remote Logging feature to work. The proxy servlet is something we don&apos;t want to ship with our product, so we have a separate web.xml for production vs. development. We do the substitution using the maven-war-plugin:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;!-- Production web.xml --&amp;gt;
        &amp;lt;webXml&amp;gt;src/main/resources/web.xml&amp;lt;/webXml&amp;gt;
        &amp;lt;warSourceDirectory&amp;gt;war&amp;lt;/warSourceDirectory&amp;gt;
        &amp;lt;!-- Exclude everything but urlrewrite JAR --&amp;gt;
        &amp;lt;warSourceExcludes&amp;gt;
            WEB-INF/lib/aop**,WEB-INF/lib/commons-**,WEB-INF/lib/gin-**,
            WEB-INF/lib/guice-**,WEB-INF/lib/gwt-**,WEB-INF/lib/gxt-**,
            WEB-INF/lib/junit-**
        &amp;lt;/warSourceExcludes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p style=&quot;margin-left: 30px&quot;&gt;
&lt;em&gt;I could exclude WEB-INF/lib/** and WEB-INF/classes/**, but in my particular project, we still want UrlRewrite in standalone mode, and we have some i18n properties files in WEB-INF/classes that are served up for Selenium tests.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;With this configuration, we have a services WAR and a client WAR that can be installed and used by clients. To collapse them into one and make it possible to ship a single war, I turned to our &lt;em&gt;product-integration-tests&lt;/em&gt; module. This module contains Selenium tests that test both types of distributions.
&lt;/p&gt;
&lt;p id=&quot;mergingwars&quot;&gt;
&lt;strong&gt;Merging 2 WARs into 1&lt;/strong&gt;&lt;br/&gt;
The most important thing in the product-integration-tests module is that it creates a single WAR. First of all, it uses &lt;code&gt;&amp;lt;packaging&gt;war&amp;lt;/packaging&gt;&lt;/code&gt; to make this possible. The rest is done using the following 3 steps.
&lt;/p&gt;
&lt;p&gt;
1. Its dependencies include the client and servlet WARs (and Selenium RC for testing).
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;product-services&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
        &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;product-client&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
        &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.seleniumhq.selenium.client-drivers&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;selenium-java-client-driver&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;
        &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
    &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&lt;/pre&gt;
&lt;p&gt;2. The WAR created excludes the &quot;integration-tests&quot; part of the name:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;build&amp;gt;
    &amp;lt;finalName&amp;gt;product-${project.version}&amp;lt;/finalName&amp;gt;
    ...
&amp;lt;/build&amp;gt;
&lt;/pre&gt;
&lt;p&gt;3. WAR overlays are configured so the everything in the client&apos;s &lt;em&gt;WEB-INF&lt;/em&gt; directory is excluded from the merged WAR.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;!-- http://maven.apache.org/plugins/maven-war-plugin/overlays.html --&amp;gt;
        &amp;lt;overlays&amp;gt;
            &amp;lt;overlay&amp;gt;
                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;product-services&amp;lt;/artifactId&amp;gt;
                &amp;lt;excludes&amp;gt;
                    &amp;lt;!-- TODO: Rename to api.html (this is the Enunciate-generated documentation) --&amp;gt;
                    &amp;lt;exclude&amp;gt;index.html&amp;lt;/exclude&amp;gt;
                &amp;lt;/excludes&amp;gt;
            &amp;lt;/overlay&amp;gt;
            &amp;lt;!-- No server needed in product-client --&amp;gt;
            &amp;lt;overlay&amp;gt;
                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;product-client&amp;lt;/artifactId&amp;gt;
                &amp;lt;excludes&amp;gt;
                    &amp;lt;exclude&amp;gt;WEB-INF/**&amp;lt;/exclude&amp;gt;
                &amp;lt;/excludes&amp;gt;
            &amp;lt;/overlay&amp;gt;
            &amp;lt;!-- Only include META-INF/context.xml to set the ROOT path --&amp;gt;
            &amp;lt;overlay&amp;gt;
                &amp;lt;excludes&amp;gt;
                    &amp;lt;exclude&amp;gt;WEB-INF/**&amp;lt;/exclude&amp;gt;
                &amp;lt;/excludes&amp;gt;
            &amp;lt;/overlay&amp;gt;
        &amp;lt;/overlays&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;That&apos;s it! Using this configuration, it&apos;s possible to distribute a Maven-based SOFEA project as single or multiple WARs. However, there are some nuances.
&lt;/p&gt;
&lt;p&gt;One thing you might notice is the reference to &lt;em&gt;META-INF/context.xml&lt;/em&gt; in the overlays configuration. This subtly highlights one issue I experienced when merging the WARs. In our GWT client, we&apos;re using URLs that point to our services at &lt;strong&gt;/product-services/*&lt;/strong&gt;. This works in development (via a proxy servlet) and when the WARs are installed separately - as long as the services WAR is installed at &lt;strong&gt;/product-services&lt;/strong&gt;. However, when they&apos;re merged, a little URL rewriting needs to happen. To do this, I added the UrlRewriteFilter to the product-services module and configured a simple rule. 
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCENGINE urlrewrite PUBLIC &quot;-//tuckey.org//DTD UrlRewrite 3.0//EN&quot;
        &quot;http://tuckey.org/res/dtds/urlrewrite3.0.dtd&quot;&amp;gt;

&amp;lt;urlrewrite use-query-string=&quot;true&quot;&amp;gt;
    &amp;lt;!-- Used when services are merged into WAR with GWT client --&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/product-services/(.*)$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot;&amp;gt;/$1&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/urlrewrite&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;Because the services URLs point to the root (/product-services), the merged WAR has to be installed as the ROOT application. When you&apos;re using Cargo with Tomcat and want to deploy to ROOT, you have to have a &lt;em&gt;META-INF/context.xml&lt;/em&gt; with a path=&quot;&quot; reference (ref: &lt;a href=&quot;http://jira.codehaus.org/browse/CARGO-516&quot;&gt;CARGO-516&lt;/a&gt;).
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;Context path=&quot;&quot;/&amp;gt;
&lt;/pre&gt;
&lt;p&gt;It is possible to change the URLs in the client to be relative, but this gets seems to get messy when you&apos;re using separate WARs. When using relative URLs, I found I had to do solution using cross-context forwarding to get the results I wanted. Using a redirect instead of a forward worked, but resulted in the client talking to the server twice (once to get redirected, a second time for the actual call). Cross-context forwarding is supported by the UrlRewriteFilter and Tomcat, but I&apos;m not sure WebSphere or WebLogic support it. The best solution is probably to change the URLs dynamically at runtime, possibly using some sort of deferred binding technique. &lt;!--The upside to having the URLs start at a known location (/product-services) is that you could  install the merged WAR initially and install a newer product-services.war later to upgrade the services.--&gt;
&lt;/p&gt;
&lt;p id=&quot;testingwithselenium&quot;&gt;&lt;strong&gt;Testing with Cargo and Selenium&lt;/strong&gt;&lt;br/&gt;
Once I had everything merged, I wanted to configure Cargo and Selenium to allow testing both distribution types. If I installed all 3 wars at the same time, the &quot;product-services&quot; WAR would be used by both the product-client.war and the product.war, so I had to use profiles to allow installing the single merged WAR or both WARs. Below is the profile I used for starting Cargo, deploying the merged WAR, starting Selenium RC and running Selenium tests.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
&amp;lt;properties&amp;gt;
    &amp;lt;cargo.container&amp;gt;tomcat6x&amp;lt;/cargo.container&amp;gt;
    &amp;lt;cargo.container.url&amp;gt;
        http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip
    &amp;lt;/cargo.container.url&amp;gt;
    &amp;lt;cargo.host&amp;gt;localhost&amp;lt;/cargo.host&amp;gt;
    &amp;lt;cargo.port&amp;gt;23433&amp;lt;/cargo.port&amp;gt;
    &amp;lt;cargo.wait&amp;gt;false&amp;lt;/cargo.wait&amp;gt;
    &amp;lt;cargo.version&amp;gt;1.0&amp;lt;/cargo.version&amp;gt;

    &amp;lt;!-- *safari and *iexplore are additional options --&amp;gt;
    &amp;lt;selenium.browser&amp;gt;*firefox&amp;lt;/selenium.browser&amp;gt;
&amp;lt;/properties&amp;gt;
...
&amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;itest-bamboo&amp;lt;/id&amp;gt;
    &amp;lt;activation&amp;gt;
        &amp;lt;activeByDefault&amp;gt;false&amp;lt;/activeByDefault&amp;gt;
    &amp;lt;/activation&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${cargo.version}&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;wait&amp;gt;${cargo.wait}&amp;lt;/wait&amp;gt;
                    &amp;lt;container&amp;gt;
                        &amp;lt;containerId&amp;gt;${cargo.container}&amp;lt;/containerId&amp;gt;
                        &amp;lt;log&amp;gt;${project.build.directory}/${cargo.container}/cargo.log&amp;lt;/log&amp;gt;
                        &amp;lt;zipUrlInstaller&amp;gt;
                            &amp;lt;url&amp;gt;${cargo.container.url}&amp;lt;/url&amp;gt;
                            &amp;lt;installDir&amp;gt;${installDir}&amp;lt;/installDir&amp;gt;
                        &amp;lt;/zipUrlInstaller&amp;gt;
                    &amp;lt;/container&amp;gt;
                    &amp;lt;configuration&amp;gt;
                        &amp;lt;home&amp;gt;${project.build.directory}/${cargo.container}/container&amp;lt;/home&amp;gt;
                        &amp;lt;properties&amp;gt;
                            &amp;lt;cargo.hostname&amp;gt;${cargo.host}&amp;lt;/cargo.hostname&amp;gt;
                            &amp;lt;cargo.servlet.port&amp;gt;${cargo.port}&amp;lt;/cargo.servlet.port&amp;gt;
                        &amp;lt;/properties&amp;gt;
                        &amp;lt;!-- Deploy as ROOT since XHR requests are made to /product-services --&amp;gt;
                        &amp;lt;deployables&amp;gt;
                            &amp;lt;deployable&amp;gt;
                                &amp;lt;properties&amp;gt;
                                    &amp;lt;context&amp;gt;ROOT&amp;lt;/context&amp;gt;
                                &amp;lt;/properties&amp;gt;
                            &amp;lt;/deployable&amp;gt;
                        &amp;lt;/deployables&amp;gt;
                    &amp;lt;/configuration&amp;gt;
                &amp;lt;/configuration&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;start-container&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;start&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                    &amp;lt;/execution&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;stop-container&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;stop&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;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;selenium-maven-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;start-server&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;background&amp;gt;true&amp;lt;/background&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;excludes&amp;gt;
                                &amp;lt;exclude&amp;gt;none&amp;lt;/exclude&amp;gt;
                            &amp;lt;/excludes&amp;gt;
                            &amp;lt;includes&amp;gt;
                                &amp;lt;include&amp;gt;**/*SeleniumTest.java&amp;lt;/include&amp;gt;
                            &amp;lt;/includes&amp;gt;
                            &amp;lt;systemProperties&amp;gt;
                                &amp;lt;property&amp;gt;
                                    &amp;lt;name&amp;gt;selenium.browser&amp;lt;/name&amp;gt;
                                    &amp;lt;value&amp;gt;${selenium.browser}&amp;lt;/value&amp;gt;
                                &amp;lt;/property&amp;gt;
                                &amp;lt;property&amp;gt;
                                    &amp;lt;name&amp;gt;cargo.port&amp;lt;/name&amp;gt;
                                    &amp;lt;value&amp;gt;${cargo.port}&amp;lt;/value&amp;gt;
                                &amp;lt;/property&amp;gt;
                            &amp;lt;/systemProperties&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/profile&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This profile is run by our Bamboo nightly tests with &lt;code&gt;mvn install -Pitest-bamboo&lt;/code&gt;. The 2nd profile I added doesn&apos;t install the project&apos;s WAR, but instead installs the two separate WARs. Running &lt;code&gt;mvn install -Pitest-bamboo,multiple-wars&lt;/code&gt; executes the Selenium tests against the multi-WAR distribution.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
&amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;multiple-wars&amp;lt;/id&amp;gt;
    &amp;lt;activation&amp;gt;
        &amp;lt;activeByDefault&amp;gt;false&amp;lt;/activeByDefault&amp;gt;
    &amp;lt;/activation&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${cargo.version}&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;configuration&amp;gt;
                        &amp;lt;home&amp;gt;${project.build.directory}/${cargo.container}/container&amp;lt;/home&amp;gt;
                        &amp;lt;properties&amp;gt;
                            &amp;lt;cargo.hostname&amp;gt;${cargo.host}&amp;lt;/cargo.hostname&amp;gt;
                            &amp;lt;cargo.servlet.port&amp;gt;${cargo.port}&amp;lt;/cargo.servlet.port&amp;gt;
                        &amp;lt;/properties&amp;gt;
                        &amp;lt;deployables&amp;gt;
                            &amp;lt;deployable&amp;gt;
                                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;product-client&amp;lt;/artifactId&amp;gt;
                                &amp;lt;pingURL&amp;gt;http://${cargo.host}:${cargo.port}/product-client/index.html&amp;lt;/pingURL&amp;gt;
                                &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
                                &amp;lt;properties&amp;gt;
                                    &amp;lt;context&amp;gt;/product-client&amp;lt;/context&amp;gt;
                                &amp;lt;/properties&amp;gt;
                            &amp;lt;/deployable&amp;gt;
                            &amp;lt;deployable&amp;gt;
                                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;product-services&amp;lt;/artifactId&amp;gt;
                                &amp;lt;pingURL&amp;gt;
                                    http://${cargo.host}:${cargo.port}/project-services/index.jspx
                                &amp;lt;/pingURL&amp;gt;
                                &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
                                &amp;lt;properties&amp;gt;
                                    &amp;lt;context&amp;gt;/product-services&amp;lt;/context&amp;gt;
                                &amp;lt;/properties&amp;gt;
                            &amp;lt;/deployable&amp;gt;
                        &amp;lt;/deployables&amp;gt;
                    &amp;lt;/configuration&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/profile&amp;gt;
&lt;/pre&gt;
&lt;p&gt;I won&apos;t be including any information on authoring Selenium tests because there&apos;s already many good references. I encourage you to checkout the following if you&apos;re looking for Selenium testing techniques.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/carlossg/appfuse-selenium&quot;&gt;Carlos Sanchez&apos;s Selenium Test Environment for AppFuse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.extjs.com/blog/2008/11/03/testing-ext-js-ext-gwt-applications-with-selenium/&quot;&gt;Testing Ext JS &amp;amp; Ext GWT Applications With Selenium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sonatype.com/people/2009/09/testing-nexus-with-selenium-a-lesson-in-complex-ui-testing-part-1/&quot;&gt;Testing Nexus with Selenium: A lesson in complex UI testing (Part 1)&lt;/a&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sonatype.com/people/2009/10/selenium-part-2/&quot;&gt;Testing Nexus with Selenium: A lesson in complex UI testing (Part 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sonatype.com/people/2009/10/selenium-part-3/&quot;&gt;Testing Nexus with Selenium: A lesson in complex UI testing (Part 3)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br/&gt;
This article has shown you how I used Maven, war overlays and the UrlRewriteFilter to allow create different distributions of a SOFEA application. I&apos;m still not sure which packaging (1 WAR vs. 2) mechanism is best, but it&apos;s nice to know there&apos;s options. If you package and distribute SOFEA applications, I&apos;d love to hear about your experience in this area.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/building_gwt_applications_with_mvp</guid>
    <title>Building GWT Applications with MVP and Issues with Overlay Types</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/building_gwt_applications_with_mvp</link>
        <pubDate>Tue, 22 Sep 2009 13:41:36 -0600</pubDate>
    <category>Java</category>
    <category>json</category>
    <category>gxt</category>
    <category>testing</category>
    <category>gwt</category>
    <category>overlaytypes</category>
    <category>mvp</category>
    <category>java</category>
    <category>easymock</category>
            <description>MVP has recently become a popular strategy for structuring GWT applications. This is largely due to its &lt;a href=&quot;http://googletesting.blogspot.com/2009/02/with-all-sport-drug-scandals-of-late.html&quot;&gt;testability&lt;/a&gt; and Ray Ryan&apos;s &lt;a href=&quot;http://code.google.com/events/io/sessions/GoogleWebToolkitBestPractices.html&quot;&gt;Best Practices For Architecting Your GWT App&lt;/a&gt; from this year&apos;s Google I/O. GWT, by itself, is simply a widget toolkit and doesn&apos;t ship with any sort of MVC (or MVP) framework.
&lt;/p&gt;
&lt;p&gt;
On my current project, we&apos;re using &lt;a href=&quot;http://www.extjs.com/products/gxt/&quot;&gt;GXT&lt;/a&gt;, a GWT implementation based on ExtJS. It has its own MVC framework, but it has very little documentation and can be confusing when using it with GWT&apos;s History management. At one point, I attempted to make it more understandable by writing a blog entry on &lt;a href=&quot;http://raibledesigns.com/rd/entry/gxt_s_mvc_framework&quot;&gt;GXT&apos;s MVC Framework&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt; 
One of my initial assignments was to decide if we should use MVP or MVC. Regardless of which one was chosen, I was also tasked with deciding if we should use an existing framework or write our own. After watching &lt;a href=&quot;http://www.youtube.com/watch?v=PDuhR18-EdM&quot;&gt;Ray Ryan&apos;s session on YouTube&lt;/a&gt; and recalling my frustration with GXT MVC on my last project, I quickly became convinced MVP was the answer.
&lt;/p&gt;
&lt;p&gt;
To test my &quot;MVP is best for our project&quot; theory, I did a spike to implement it. I used the &lt;a href=&quot;http://blog.hivedevelopment.co.uk/2009/08/google-web-toolkit-gwt-mvp-example.html&quot;&gt;GWT MVP Example tutorial&lt;/a&gt; as a starting point and added the following libraries to my project.
&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/gwt-presenter/&quot;&gt;GWT-Presenter&lt;/a&gt;: An implementation of the MVP pattern.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/google-gin/&quot;&gt;Google Gin&lt;/a&gt;: Dependency Injection based on Google&apos;s Guice.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/gwt-log/&quot;&gt;GWT-Log&lt;/a&gt;: A log4j-style logger for GWT.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Implementing the MVP pattern itself was relatively straightforward, but I did encounter a few issues. I&apos;m writing this post to see if anyone has solved these issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MVP Implementation Issues&lt;/strong&gt;&lt;br/&gt;
The first issue I ran across was &lt;a href=&quot;http://www.extjs.com/forum/showthread.php?t=76968&quot;&gt;GXT&apos;s widgets don&apos;t implement standard GWT interfaces&lt;/a&gt;. To try and figure out a solution, I &lt;a href=&quot;http://tweader.com/conversation.php?id=3554190680&quot;&gt;posted&lt;/a&gt; the following on Twitter:
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;&quot;Wondering if it&apos;s possible to do MVP with GXT since it&apos;s buttons don&apos;t implement standard GWT interfaces.&quot;
&lt;/p&gt;
&lt;p&gt;
The best response I received was from Simon Stewart (founder of the &lt;a href=&quot;http://code.google.com/p/webdriver/&quot;&gt;WebDriver&lt;/a&gt; project, works for Google):&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
&quot;Put the GXT buttons in the View. Let that turn DOM events into semantic events.&quot;
&lt;/p&gt;
&lt;p&gt;He also pointed me to his &lt;a href=&quot;http://code.google.com/p/tdd-gwt-gae/&quot;&gt;tdd-gwt-gae&lt;/a&gt; project which shows many techniques for unit testing (with jMock) and integration testing (with GWTTestCase). Using Simon&apos;s examples, I was able to determine an initial strategy for implementing MVP with GXT.&lt;/p&gt;
&lt;p&gt;My strategy is instead of getting widgets from the view and adding handlers, you add handlers to to the view and it takes care of adding them to the widgets that should listen for them. This seems to work, but my View interface has a lot of void methods, which is a bit different than standard MVP patterns I&apos;ve seen.&lt;/p&gt;
&lt;p&gt;The 2nd issue I encountered is with unit testing. Unit testing can be be performed on MVP applications by mocking out any dependencies that use JSNI. Classes that use JSNI are not testable with plain ol&apos; JUnit and typically requires you to use &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/junit/client/GWTTestCase.html&quot;&gt;GWTTestCase&lt;/a&gt;, which can be slow and cumbersome. This isn&apos;t to say that GWTTestCase isn&apos;t useful, just that it has its place.
&lt;/p&gt;
&lt;p&gt;When unit testing MVP applications, the recommended practice seems to be you should test presenters and not views. Services fall into a similar &quot;don&apos;t unit test&quot; category because they&apos;ll need to connect to the server-side, which won&apos;t be running in a unit testing environment. 
&lt;/p&gt;
&lt;p&gt;This is where I ran into a major issue that I don&apos;t have a solution for.
&lt;/p&gt;
&lt;p&gt;I&apos;m using Overlay Types (as described in &lt;a href=&quot;http://raibledesigns.com/rd/entry/json_parsing_with_javascript_overlay&quot;&gt;JSON Parsing with JavaScript Overlay Types&lt;/a&gt;) to do JSON parsing in callbacks. Since Overlay Types use JSNI, it&apos;s not possible to do any JSON parsing in unit tests. The problem with not being able to do any JSON parsing is the callbacks will often call &lt;code&gt;eventBus.fireEvent(GwtEvent)&lt;/code&gt; after the JSON parsing has happened. This means I can&apos;t fully test the flow of a presenter if event firing happens in a callback.
&lt;/p&gt;
&lt;p&gt;
In attempt to try different mocking techniques for callbacks, I created a test that uses two recommended EasyMock-ing strategies. The first is a &quot;CallbackSuccessMatcher&quot; and is described in more detail in &lt;a href=&quot;http://googletesting.blogspot.com/2009/08/tott-testing-gwt-without-gwttest.html&quot;&gt;Testing GWT without GwtTestCase&lt;/a&gt;. The second technique uses a &quot;CallbackMockSupport&quot; class to allow EasyMock expectations such as &lt;em&gt;expectLastCallAsync() &lt;/em&gt;and &lt;em&gt;expectLastCallAsyncSuccess(T)&lt;/em&gt;. You can read more about this technique in &lt;a href=&quot;http://robvanmaris.jteam.nl/2008/04/22/test-driven-development-for-gwt-ui-code-with-asynchronous-rpc/&quot;&gt;Test driven development for GWT UI code with asynchronous RPC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Both of these examples use RPC, which typically has callbacks that have an onSuccess(T type) method. It&apos;s easy to use these callbacks in unit tests since T is a POJO and the onSuccess() method contains no JSNI code.&lt;/p&gt;
&lt;p&gt;Currently, I see a few possible solutions to this problem:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Figure out a way to detect when unit tests are running and add if/else logic to callbacks. 
&lt;/li&gt;
&lt;li&gt;Modify presenters and services so a callback can be set that is unit test-friendly.&lt;/li&gt;
&lt;li&gt;Make JSOModel an interface that can be replaced/mocked in tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last solution seems like best one, but I&apos;m also curious to know what others are doing. My hunch is that most GWT apps use RPC and haven&apos;t run into this issue. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/my_experience_with_java_rest</guid>
    <title>My Experience with Java REST Frameworks (specifically Jersey and CXF)</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/my_experience_with_java_rest</link>
        <pubDate>Thu, 27 Aug 2009 14:20:51 -0600</pubDate>
    <category>Java</category>
    <category>jersey</category>
    <category>cxf</category>
    <category>json</category>
    <category>gwt</category>
    <category>soap</category>
    <category>rpc</category>
    <category>rest</category>
    <category>webservices</category>
    <category>enunciate</category>
            <description>Recently I was tasked with developing a server-side REST strategy for a client. When I started working with them, they were using GWT RPC for exposing services. They wanted to move to RESTful services to allow for a more open platform, that multiple types of clients could talk to. There were interested in supporting SOAP and GWT RPC as well, but it wasn&apos;t required. They are using Spring, a &lt;a href=&quot;http://blog.springsource.com/2006/08/28/creating-a-spring-20-namespace-use-springs-abstractbeandefintionparser-hierarchy/&quot;&gt;custom namespace&lt;/a&gt; (for easily creating remote services) and an HTML documentation generator to expose their API in human readable form.
&lt;/p&gt;
&lt;p&gt;When I first starting developing, I chose to try &lt;a href=&quot;http://enunciate.codehaus.org/&quot;&gt;Enunciate&lt;/a&gt;. From Enunciate&apos;s homepage:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Enunciate is an engine for creating, maintaining, and deploying your rich Web service API on the Java platform.
If that sounds complicated, it&apos;s not. All you have to do is define your service interfaces in Java source code. ... 
Then invoke Enunciate.
&lt;/p&gt;
&lt;p&gt;Sounds pretty sweet, eh? At first glance, the things I liked about Enunciate were:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The ability to generate multiple endpoints (and clients).&lt;/li&gt;
&lt;li&gt;Generates nice-looking documentation.&lt;/li&gt;
&lt;li&gt;Allows selecting different frameworks (for example, &lt;a href=&quot;http://docs.codehaus.org/display/ENUNCIATE/Using+CXF+or+XFire&quot;&gt;CXF instead of JAX-WS RI&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Initially, the hardest part of using Enunciate was integrating it into my project. This was somewhat related to having a &lt;a href=&quot;http://docs.codehaus.org/display/ENUNCIATE/Multi-Module+Projects&quot;&gt;multi-module project&lt;/a&gt;, but moreso related to getting the settings right in my &lt;em&gt;enunciate.xml&lt;/em&gt; file. After getting everything working, I encountered &lt;a href=&quot;http://markmail.org/thread/g3wj2gyvtqq5v3f4&quot;&gt;a few Spring wiring issues&lt;/a&gt; with the GWT Endpoints and with Jersey&apos;s Spring support. 
&lt;/p&gt;
&lt;p&gt;
The good news is I believe most of these issues were related to my project and how it proxies Spring beans that Jersey couldn&apos;t find. Jersey&apos;s &lt;a href=&quot;http://blogs.sun.com/enterprisetechtips/entry/jersey_and_spring&quot;&gt;Spring support&lt;/a&gt; only supports annotations at this time, so I was unable to tell it the proxied bean names via XML (or even its own annotations). I&apos;m sure this problem is solvable, but after struggling with it for a day or two, I decided to give up on Enunciate. I had to get something working, and fast.
&lt;/p&gt;
&lt;p&gt;At this point, I was back to the drawing board. I knew there were plenty of good Java REST frameworks available, but Spring and CXF (for SOAP) were already available dependencies in my project, so I chose that route. I was able to get something up and running fairly quickly with &lt;a href=&quot;http://raulraja.com/2009/06/25/spring-exposing-a-bean-as-rest-xml-json-and-soap-webservice/&quot;&gt;this tutorial&lt;/a&gt; and CXF&apos;s &lt;a href=&quot;http://cwiki.apache.org/CXF20DOC/jax-rs.html&quot;&gt;JAX-RS documentation&lt;/a&gt;. I ran into an &lt;a href=&quot;http://twitter.com/mraible/statuses/3407586205&quot;&gt;Invalid JSON Namespace issue&lt;/a&gt;, but was able to solve it by &lt;a href=&quot;https://issues.apache.org/jira/browse/CXF-1671&quot;&gt;adding a custom namespace&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;It&apos;s not all rosy though, there are still a couple CXF issues I haven&apos;t solved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&apos;d like to remove the namespace prefixes on returned JSON. I&apos;ve never seen JSON with &quot;prefix.&quot; notation before and it doesn&apos;t seem right.&lt;/li&gt;
&lt;li&gt;I&apos;m &lt;a href=&quot;http://www.nabble.com/No-message-body-writer-found-for-response-class-%3A-String---tt25070046.html#a25070046&quot;&gt;unable to return String[] from services&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While CXF does take a bit of XML for each service, it&apos;s kinda slick in that it only requires you to annotate your service interfaces. It also generates documentation for your services (WSDL and WADL), but it&apos;s not as pretty as Enunciate&apos;s. To solve this, I &lt;a href=&quot;http://docs.codehaus.org/display/ENUNCIATE/Documentation+Only&quot;&gt;added Enunciate for documentation only&lt;/a&gt;. To make Enunciate work, I did have to add some annotations to my service implementation classes and &lt;a href=&quot;http://markmail.org/thread/r6i4rv45lkaknzv7&quot;&gt;parse the generated HTML&lt;/a&gt; to fix some links to CXF&apos;s services, but ultimately it works pretty well. 
&lt;/p&gt;
&lt;p&gt;In the end, I recommended my client not use Enunciate for generating endpoints. This was primarily related to their unique Spring configuration, but also because I was able to easily use the same classes for REST, SOAP and GWT Endpoints. However, I will continue to keep my eye on Enunciate. It could be very useful for the upcoming &lt;a href=&quot;http://jira.codehaus.org/browse/ENUNCIATE-290&quot;&gt;appfuse-ws&lt;/a&gt; archetype. I&apos;m also eager to see &lt;a href=&quot;http://jira.codehaus.org/browse/ENUNCIATE-319&quot;&gt;better GWT support&lt;/a&gt; and the ability to &lt;a href=&quot;http://jira.codehaus.org/browse/ENUNCIATE-290&quot;&gt;generate Overlay types&lt;/a&gt; in future releases. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/the_2009_rich_web_experience</guid>
    <title>The 2009 Rich Web Experience</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/the_2009_rich_web_experience</link>
        <pubDate>Tue, 11 Aug 2009 22:16:24 -0600</pubDate>
    <category>Java</category>
    <category>nofluff</category>
    <category>gwt</category>
    <category>orlando</category>
    <category>richwebexperience</category>
    <category>conference</category>
    <category>disneyworld</category>
    <category>nofluffjuststuff</category>
            <description>&lt;a href=&quot;http://www.therichwebexperience.com/&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/speakeratrichweb2009.jpg&quot; alt=&quot;Rich Web Experience 2009&quot; width=&quot;125&quot; height=&quot;125&quot; class=&quot;picture&quot;/&gt;&lt;/a&gt;
Late last year, I decided to take a year off from speaking at conferences. My reason was simple: I wanted to hunker down and do some learning. Ever since &lt;a href=&quot;http://raibledesigns.com/rd/entry/sofea_also_known_as_soui&quot;&gt;November 2007&lt;/a&gt;, I&apos;d been interested in getting into developing SOFEA applications. This year, I was able to accomplish that and I&apos;ve learned a lot about GWT and RESTful architectures in the process. Now I&apos;m happy to announce I&apos;ll be sharing my experiences at this year&apos;s &lt;a href=&quot;http://www.therichwebexperience.com/&quot;&gt;Rich Web Experience&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;I look forward to speaking on the following topics:&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.therichwebexperience.com/conference/speaker/topic_view?topicId=2103&quot;&gt;Web Frameworks of the Future: Flex, GWT, Grails, and Rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.therichwebexperience.com/conference/speaker/topic_view?topicId=2104&quot;&gt;Building SOFEA Applications with Grails and GWT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first one might look familiar since I used the same title at &lt;a href=&quot;http://en.oreilly.com/oscon2008/public/schedule/detail/2651&quot;&gt;OSCON 2008&lt;/a&gt;. The difference is this time I plan to dive much deeper into the frameworks and help the audience learn more. I also plan to re-visit developing with Flex and Rails in the near future. If there&apos;s anything in particular you&apos;d like to see covered in the above talks, please leave a comment.
&lt;/p&gt;
&lt;p&gt;This is sure to be a fun conference. First of all, it&apos;s pretty close to Disney World. A few years back, TSS hosted the &quot;Java In Action&quot; conference in Disney World and while the conference didn&apos;t do too well, it was awesome being there with my family. I plan on taking my kids and having some fun when I&apos;m not speaking. Secondly, this conference is the first to offer all-inclusive pricing for attendees - registration, flight (continental U.S.) and 3 nights lodging. This should allow you to get approval without having to jump through the traditional travel hoops. Lastly, the &lt;a href=&quot;http://www.jsfsummit.com/conference/orlando/2009/12/home&quot;&gt;JSF Summit&lt;/a&gt; will be held concurrently and you get access to it at no additional cost.&lt;/p&gt;
&lt;p&gt;So come on down to Florida in December, listen to all the great speakers, have some fun with your family and look me up for a beer or two. You &lt;em&gt;know&lt;/em&gt; it&apos;ll be a good time! &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/browser_based_username_password_autocomplete</guid>
    <title>My attempt at browser-based username/password autocomplete with GWT</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/browser_based_username_password_autocomplete</link>
        <pubDate>Fri, 7 Aug 2009 08:09:11 -0600</pubDate>
    <category>Java</category>
    <category>autocomplete</category>
    <category>gwt</category>
    <category>safari</category>
    <category>ie</category>
    <category>firefox</category>
            <description>Last night, I did a quick spike to try and implement username/password autocomplete in my GXT application. By &quot;autocomplete&quot;, I don&apos;t mean Ajax-style autocomplete, but rather browser-based autocomplete. The best information I found on doing this is in the following post:
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://osdir.com/ml/GoogleWebToolkit/2009-04/msg01838.html&quot;&gt;http://osdir.com/ml/GoogleWebToolkit/2009-04/msg01838.html&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I didn&apos;t use this technique (wrapping an existing form with a FormPanel) because I&apos;m using GXT and didn&apos;t want to lose the look-and-feel of my login form.&lt;/p&gt;
&lt;p&gt;
I was successful in getting everything to work in Firefox (it populates both the username and password). In IE, it only populates the username, not the password. In Safari/Chrome, it doesn&apos;t work at all. Here&apos;s how I did it:
&lt;/p&gt;
&lt;p&gt;
1. Created a hidden HTML form on my HTML page that embeds GWT.
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;form method=&quot;post&quot; action=&quot;javascript:void(0)&quot; style=&quot;display: none&quot;&amp;gt;
    &amp;lt;input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; value=&quot;&quot;/&amp;gt;
    &amp;lt;input type=&quot;password&quot; id=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot;/&amp;gt;
    &amp;lt;input type=&quot;submit&quot; value=&quot;Login&quot; id=&quot;login&quot;/&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
2. When a user clicks on the &quot;Login&quot; button in my GWT application, populate the fields in this hidden form and &quot;click&quot; on the Login button (which will do nothing since the &lt;em&gt;action=&quot;javascript:void(0)&quot;&lt;/em&gt;).
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
// Set the hidden fields to trigger the browser to remember
DOM.getElementById(&quot;username&quot;).setAttribute(&quot;value&quot;, username.getValue());
DOM.getElementById(&quot;password&quot;).setAttribute(&quot;value&quot;, password.getValue());
clickFormLogin();

...

public static native void clickFormLogin() /*-{
$doc.getElementById(&quot;login&quot;).click();
}-*/;
&lt;/pre&gt;
&lt;p&gt;This works in Firefox 3.5 and prompts me to save the user/pass at the top of the screen. Why doesn&apos;t this work in Safari/Chrome? My guess is because the form&apos;s action doesn&apos;t go anywhere and the form is not submitted. If I change the action to be an actual URL and show the form, clicking on the form&apos;s Login button will save it in those browsers.&lt;/p&gt;
&lt;p&gt;Grabbing the actual populated values when the screen loads did turn out to be a bit tricky. With IE, I was able to grab the username, but not the password. It seems that keyboard or mouse interaction (tabbing off or focusing/blurring) with the username field is necessary to get the password field populated. In Firefox, I was unable to grab the values if I did it straight away. The solution turned out to be wrapping everything in a Timer and waiting a 1/2 second.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
// grab user/pass from browser and hidden login form (if user has stored them)
// runs 1/2 second after page loads so cursor goes at end of username and works in Firefox
Timer t = new Timer() {
    public void run() {
        username.setValue(getElementValue(&quot;username&quot;));
        password.setValue(getElementValue(&quot;password&quot;));
        if (username.getValue() != null) {
            password.focus();
        }
        validate();
    }
};

t.schedule(500);

...

public static native String getElementValue(String domId) /*-{
    return $doc.getElementById(domId).value;
}-*/;
&lt;/pre&gt;
&lt;p&gt;While I&apos;m glad I got it working in Firefox, I&apos;m disappointed with IE&apos;s lack of password autocompletion. More than anything, I can&apos;t help but think there&apos;s a way to make this work in WebKit-based browsers. If you&apos;ve successfully implemented cross-browser username/password autocomplete in GWT, please share your experience. If you share your experience about successfully doing it in Safari/Chrome, I might even buy you a beer or two. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/integrating_gwt_with_spring_security</guid>
    <title>Integrating GWT with Spring Security</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/integrating_gwt_with_spring_security</link>
        <pubDate>Thu, 6 Aug 2009 08:50:15 -0600</pubDate>
    <category>Java</category>
    <category>authentication</category>
    <category>security</category>
    <category>spring</category>
    <category>gwt</category>
    <category>springsecurity</category>
            <description>Yesterday, I wrote about &lt;a href=&quot;http://raibledesigns.com/rd/entry/how_to_do_cross_domain&quot;&gt;How to do cross-domain GWT RPC with a ProxyServlet&lt;/a&gt;. Today I&apos;ll be discussing
    how to modify the ProxyServlet to authenticate with Spring Security. For the application I&apos;m working on, the ProxyServlet
    is only used in development (when running GWT&apos;s hosted mode) and isn&apos;t necessary when deploying the client and
    server on the same server. Using the ProxyServlet allows cross-domain requests so you can run GWT in hosted mode and
    talk to your backend running on another server. This setup can be especially handy in that you
    can easily point your hosted client at different backends (for example, if you have testing and staging environments).
&lt;/p&gt;
&lt;p&gt;
    In this example, the backend application is a JSF/Spring application that has Spring Security wired in to protect
    services with both Basic and Form-based authentication. Basic authentication will kick in if a &quot;Authorization&quot; header
    is sent, otherwise Form-based authentication is used. Here&apos;s the Spring Security context file that makes this happen:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;

&amp;lt;beans:beans xmlns=&quot;http://www.springframework.org/schema/security&quot;
             xmlns:beans=&quot;http://www.springframework.org/schema/beans&quot;
             xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
             xsi:schemaLocation=&quot;...&quot;&amp;gt;

    &amp;lt;http auto-config=&quot;true&quot; realm=&quot;My Web Application&quot;&amp;gt;
        &amp;lt;intercept-url pattern=&quot;/faces/welcome.jspx&quot; access=&quot;ROLE_USER&quot;/&amp;gt;
        &amp;lt;intercept-url pattern=&quot;/*.rpc&quot; access=&quot;ROLE_USER&quot;/&amp;gt;
        &amp;lt;http-basic/&amp;gt;
        &amp;lt;form-login login-page=&quot;/faces/login.jspx&quot; authentication-failure-url=&quot;/faces/accessDenied.jspx&quot;
                    login-processing-url=&quot;/j_spring_security_check&quot; default-target-url=&quot;/redirect.jsp&quot;
                    always-use-default-target=&quot;true&quot;/&amp;gt;
    &amp;lt;/http&amp;gt;

    &amp;lt;authentication-provider&amp;gt;
        &amp;lt;user-service &amp;gt;
            &amp;lt;user name=&quot;admin&quot; password=&quot;admin&quot; authorities=&quot;ROLE_USER&quot;/&amp;gt;
        &amp;lt;/user-service&amp;gt;
    &amp;lt;/authentication-provider&amp;gt;
&amp;lt;/beans:beans&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
The easiest way to configure your GWT application to talk to a Spring Security protected resource is to
&lt;a href=&quot;http://www.dotnetguru2.org/bmarchesson/index.php?p=678&amp;amp;more=1&amp;amp;c=1&amp;amp;tb=1&amp;amp;pb=1&quot;&gt;protect your HTML page that GWT is embedded in&lt;/a&gt;. This is the documented way to integrate GWT with Spring Security (ref: 
&lt;a href=&quot;http://code.google.com/p/google-web-toolkit-incubator/wiki/LoginSecurityFAQ&quot;&gt;GWT&apos;s LoginSecurityFAQ&lt;/a&gt;, search for &quot;Acegi&quot;).
This works well for production, but not for hosted-mode development.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Basic Authentication&lt;/strong&gt;&lt;br/&gt;
To authenticate with Basic Authentication, you can use GWT&apos;s RequestBuilder and set an &quot;Authentication&quot; header that
contains the user&apos;s (base64-encoded) credentials.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
private class LoginRequest {
    public LoginRequest(RequestCallback callback) {
        String url = &quot;/services/faces/welcome.jspx&quot;;

        RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, url);
        rb.setHeader(&quot;Authorization&quot;, createBasicAuthToken());
        rb.setCallback(callback);
        try {
            rb.send();
        } catch (RequestException e) {
            Window.alert(e.getMessage());
        }
    }
}

protected String createBasicAuthToken() {
    byte[] bytes = stringToBytes(username.getValue() + &quot;:&quot; + password.getValue());
    String token = Base64.encode(bytes);
    return &quot;Basic &quot; + token;
}

protected byte[] stringToBytes(String msg) {
    int len = msg.length();
    byte[] bytes = new byte[len];
    for (int i = 0; i &amp;lt; len; i++)
        bytes[i] = (byte) (msg.charAt(i) &amp;amp; 0xff);
    return bytes;
}
&lt;/pre&gt;
&lt;p&gt;
To use this LoginRequest class, create it with a callback and look for a 401 response code to determine if
authentication failed.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
new LoginRequest(new RequestCallback() {
    public void onResponseReceived(Request request, Response response) {
        if (response.getStatusCode() != Response.SC_UNAUTHORIZED &amp;amp;&amp;amp;
                response.getStatusCode() != Response.SC_OK) {
            onError(request, new RequestException(response.getStatusText() + &quot;:\n&quot; + response.getText()));
            return;
        }

        if (response.getStatusCode() == Response.SC_UNAUTHORIZED) {
            Window.alert(&quot;You have entered an incorrect username or password. Please try again.&quot;);
        } else {
            // authentication worked, show a fancy dashboard screen
        }
    }

    public void onError(Request request, Throwable throwable) {
        Window.alert(throwable.getMessage());
    }
});
&lt;/pre&gt;
&lt;p&gt;If your GWT application is included in the &quot;services&quot; war, everything should work at this point. However, if you try to login
with invalid credentials, your browser&apos;s login dialog will appear. To suppress this in the aforementioned
ProxyServlet, you&apos;ll need to make a change in its &lt;em&gt;executeProxyRequest()&lt;/em&gt; method so the &quot;WWW-Authenticate&quot; header
is not copied.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
// Pass the response code back to the client
httpServletResponse.setStatus(intProxyResponseCode);

// Pass response headers back to the client
Header[] headerArrayResponse = httpMethodProxyRequest.getResponseHeaders();
for (Header header : headerArrayResponse) {
    if (header.getName().equals(&quot;Transfer-Encoding&quot;) &amp;amp;&amp;amp; header.getValue().equals(&quot;chunked&quot;) ||
            header.getName().equals(&quot;Content-Encoding&quot;) &amp;amp;&amp;amp; header.getValue().equals(&quot;gzip&quot;) ||
            header.getName().equals(&quot;WWW-Authenticate&quot;)) { // don&apos;t copy WWW-Authenticate header
    } else {
        httpServletResponse.setHeader(header.getName(), header.getValue());
    }
}
&lt;/pre&gt;
&lt;p&gt;I&apos;m not sure how to suppress the browser prompt when not using the ProxyServlet. If you have a solution, please
&lt;a href=&quot;http://raibledesigns.com/rd/entry/integrating_gwt_with_spring_security#comments&quot;&gt;let me know&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Basic Authentication works well for GWT applications because you don&apos;t need additional logic to retain the
authenticated state after the initial login. While Basic Authentication over SSL might offer a decent solution,
the downside is you can&apos;t logout. Form-based Authentication allows you to logout.&lt;/p&gt;
&lt;strong&gt;Form-based Authentication&lt;/strong&gt;&lt;br/&gt;
&lt;p&gt;Before I show you how to implement form-based authentication, you should be aware that Google does not recommend this.
Below is a warning from their LoginSecurityFAQ.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Do &lt;i&gt;NOT&lt;/i&gt; attempt to use the &lt;code&gt;Cookie&lt;/code&gt; header to transfer the sessionID from GWT to the server; it is
fraught with security issues that will become clear in the rest of this article. You &lt;strong&gt;MUST&lt;/strong&gt; transfer
the sessionID in the payload of the request. For an example of why this can fail, see CrossSiteRequestForgery.
&lt;/p&gt;
&lt;p&gt;In my experiment, I didn&apos;t want to change the server-side Spring Security configuration, so I ignored this
warning. If you know how to configure Spring Security so it looks for the sessionID in the payload of the request
(rather than in a cookie), I&apos;d love to hear about it. The upside of the example below is it should work with 
container-managed authentication as well.&lt;/p&gt;
&lt;p&gt;
The LoginRequest class for form-based authentication is similar to the previous one, except it has a different URL and
sends the user&apos;s credentials in the request body.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
private class LoginRequest {
    public LoginRequest(RequestCallback callback) {
        String url = &quot;/services/j_spring_security_check&quot;;

        RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, url);
        rb.setHeader(&quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot;);
        rb.setRequestData(&quot;j_username=&quot; + URL.encode(username.getValue()) +
                    &quot;&amp;amp;j_password=&quot; + URL.encode(password.getValue()));

        rb.setCallback(callback);
        try {
            rb.send();
        } catch (RequestException e) {
            Window.alert(e.getMessage());
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;If you deploy your GWT application in the same WAR your services are hosted in, this is all you&apos;ll need to do. If
you&apos;re using the ProxyServlet, there&apos;s a couple of changes you&apos;ll need to make in order to set/send cookies when
running in hosted mode.
&lt;/p&gt;
&lt;p&gt;
First of all, you&apos;ll need to make sure you&apos;ve configured the servlet to follow redirects (by subclassing or simply modifying its default).
After that, add the following logic on line 358 (or just look for &quot;&lt;code&gt;if (followRedirects)&lt;/code&gt;&quot;) to expose the sessionID to the client. The most important part is setting the cookie&apos;s path to &quot;/&quot; so the client (running at localhost:8888) can see it.&lt;/p&gt;
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
if (followRedirects) {
    // happens on first login attempt
    if (stringLocation.contains(&quot;jsessionid&quot;)) { 
        Cookie cookie = new Cookie(&quot;JSESSIONID&quot;,
                stringLocation.substring(stringLocation.indexOf(&quot;jsessionid=&quot;) + 11));
        cookie.setPath(&quot;/&quot;);
        httpServletResponse.addCookie(cookie);
    // the following happens if you refresh your GWT app after already logging in once
    } else if (httpMethodProxyRequest.getResponseHeader(&quot;Set-Cookie&quot;) != null) {
        Header header = httpMethodProxyRequest.getResponseHeader(&quot;Set-Cookie&quot;);
        String[] cookieDetails = header.getValue().split(&quot;;&quot;);
        String[] nameValue = cookieDetails[0].split(&quot;=&quot;);

        Cookie cookie = new Cookie(nameValue[0], nameValue[1]);
        cookie.setPath(&quot;/&quot;);
        httpServletResponse.addCookie(cookie);
    }
    httpServletResponse.sendRedirect(stringLocation.replace(getProxyHostAndPort() +
            this.getProxyPath(), stringMyHostName));
    return;
}
&lt;/pre&gt;
&lt;p style=&quot;font-style: italic&quot;&gt;Click &lt;a href=&quot;http://www.flickr.com/photos/mraible/3794558459/sizes/l/&quot;&gt;here&lt;/a&gt; to see a screenshot of the diff of the ProxyServlet after this code has been added.&lt;/p&gt;
&lt;p&gt;Figuring out that headers needed to be parsed &lt;strong&gt;after&lt;/strong&gt; authenticating successfully and &lt;strong&gt;before&lt;/strong&gt; redirecting was the hardest part for me. If you grab the JSESSIONID from
the &quot;Set-Cookie&quot; header anywhere else, the JSESSIONID is one that hasn&apos;t been authenticated. While the login will work,
subsequent calls to services will fail.&lt;/p&gt;
&lt;p&gt;To make subsequent calls with the cookie in the header, you&apos;ll need to make an additional modification to ProxyServlet to 
send cookies as headers. First of all, add a &lt;em&gt;setProxyRequestCookies()&lt;/em&gt; method:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
/**
 * Retrieves all of the cookies from the servlet request and sets them on
 * the proxy request
 *
 * @param httpServletRequest The request object representing the client&apos;s
 *                            request to the servlet engine
 * @param httpMethodProxyRequest The request that we are about to send to
 *                                the proxy host
 */
@SuppressWarnings(&quot;unchecked&quot;)
private void setProxyRequestCookies(HttpServletRequest httpServletRequest, 
                                    HttpMethod httpMethodProxyRequest) {
    // Get an array of all of all the cookies sent by the client
    Cookie[] cookies = httpServletRequest.getCookies();
    if (cookies == null) {
        return;
    }
    
    for (Cookie cookie : cookies) {
        cookie.setDomain(stringProxyHost);
        cookie.setPath(httpServletRequest.getServletPath());
        httpMethodProxyRequest.setRequestHeader(&quot;Cookie&quot;, cookie.getName() +  
                &quot;=&quot; + cookie.getValue() + &quot;; Path=&quot; + cookie.getPath());
    }
}
&lt;/pre&gt;
&lt;p&gt;Next, in the &lt;em&gt;doGet()&lt;/em&gt; and &lt;em&gt;doPost()&lt;/em&gt; methods, add the following line just after the call to &lt;em&gt;setProxyRequestHeaders()&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
setProxyRequestCookies(httpServletRequest, getMethodProxyRequest);
&amp;nbsp;
&lt;/pre&gt;
&lt;p&gt;After making these modifications to ProxyServlet, you can create LoginRequest and attempt to authenticate. To detect a failed attempt, I&apos;m looking for text in Spring Security&apos;s &quot;authentication-failure-url&quot; page.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
new LoginRequest(new RequestCallback() {

    public void onResponseReceived(Request request, Response response) {
        if (response.getStatusCode() != Response.SC_OK) {
            onError(request, new RequestException(response.getStatusText() + &quot;:\n&quot; + response.getText()));
            return;
        }
        
        if (response.getText().contains(&quot;Access Denied&quot;)) {
            Window.alert(&quot;You have entered an incorrect username or password. Please try again.&quot;);
        } else {
            // authentication worked, show a fancy dashboard screen
        }
    }

    public void onError(Request request, Throwable throwable) {
        Window.alert(throwable.getMessage());
    }
});
&lt;/pre&gt;
&lt;p&gt;After making these changes, you should be able to authenticate with Spring Security&apos;s form-based configuration. While this example doesn&apos;t show how to logout, it should be easy enough to do by 1) deleting the JSESSIONID cookie or 2) calling the Logout URL you have configured in your services WAR.&lt;/p&gt;
&lt;p&gt;Hopefully this howto gives you enough information to configure your GWT application to talk to Spring Security
without modifying your existing backend application. It&apos;s entirely possible that Spring Security offers a more GWT-friendly
authentication mechanism. If you know of a better way to integrate GWT with Spring Security, I&apos;d love to hear about it.&lt;/p&gt;
&lt;p id=&quot;update&quot;&gt;&lt;strong&gt;Update on October 7, 2009&lt;/strong&gt;: I did some additional work on this and got Remember Me working when using form-based authentication. I found I didn&apos;t need as much fancy logic in my ProxyServlet and was able to reduce the &quot;followRequests&quot; logic to the following:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
if (followRedirects) {
    if (httpMethodProxyRequest.getResponseHeader(&quot;Set-Cookie&quot;) != null) {
        Header[] headers = httpMethodProxyRequest.getResponseHeaders(&quot;Set-Cookie&quot;);
        if (headers.length == 1) {
            extractCookieFromHeader(httpServletResponse, headers[0]);
        } else {
            // ignore the first header since there always seems two jsessionid headers
            // and the 2nd is the valid one
            for (int i = 1; i &lt; headers.length; i++) {
                extractCookieFromHeader(httpServletResponse, headers[i]);
            }
        }
    }
    httpServletResponse.sendRedirect(
            stringLocation.replace(getProxyHostAndPort() + getProxyPath(), stringMyHostName));
    return;
}
&lt;/pre&gt;
&lt;p&gt;I was also able to remove the &lt;em&gt;setProxyRequestCookies()&lt;/em&gt; method completely as it no longer seems necessary.&lt;/p&gt;
&lt;p&gt;Next, I&apos;d like to figure out how to make Spring Security more Ajax-friendly where it can read an authentication token in the request body or header (instead of from a cookie). Also, it&apos;d be sweet if I could convince it to return error codes instead of the login page (for example, when a certain header is present). </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/how_to_do_cross_domain</guid>
    <title>How to do cross-domain GWT RPC with a ProxyServlet</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/how_to_do_cross_domain</link>
        <pubDate>Wed, 5 Aug 2009 16:06:12 -0600</pubDate>
    <category>Java</category>
    <category>servlet</category>
    <category>java</category>
    <category>rpc</category>
    <category>gwt</category>
            <description>Last week, I started working on a new project using GWT. On my &lt;a href=&quot;http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt&quot;&gt;last project&lt;/a&gt;, we used GWT &lt;a href=&quot;http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&amp;s=google-web-toolkit-doc-1-5&amp;t=DevGuideHttp&quot;&gt;HTTP Calls&lt;/a&gt; and my new project is using &lt;a href=&quot;http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&amp;s=google-web-toolkit-doc-1-5&amp;t=DevGuideRemoteProcedureCalls&quot;&gt;RPC&lt;/a&gt;. We&apos;ll likely migrate to a JSON backend eventually, but in the meantime, I wanted to be able to develop in hosted mode (localhost:8888) and call services on another host (localhost:8080), where the services are running in a JSF/Spring webapp.
&lt;/p&gt;
&lt;p&gt;At first, I thought it&apos;d be easy thanks to the handy-dandy ProxyServlet I mentioned in &lt;a href=&quot;http://raibledesigns.com/rd/entry/implementing_oauth_with_gwt&quot;&gt;Implementing OAuth with GWT&lt;/a&gt;. However, when I tried to hook it in and use it, I saw the following error in my server-side logs.&lt;/p&gt;
&lt;pre&gt;
java.lang.NullPointerException
        at javax.servlet.GenericServlet.getServletName(GenericServlet.java:322)
        at javax.servlet.GenericServlet.log(GenericServlet.java:277)
        at com.google.gwt.user.server.rpc.RemoteServiceServlet.doGetSerializationPolicy(RemoteServiceServlet.java:219)
        at com.google.gwt.user.server.rpc.RemoteServiceServlet.getSerializationPolicy(RemoteServiceServlet.java:117)
        at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.prepareToRead(ServerSerializationStreamReader.java:429)
        at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:234)
&lt;/pre&gt;
&lt;p&gt;Looking at RemoteServiceServlet.java:219, there&apos;s a logging call that fails for some reason (at least in my application).
&lt;p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
/*
 * Check that the module path must be in the same web app as the servlet
 * itself. If you need to implement a scheme different than this, override
 * this method.
 */
if (modulePath == null || !modulePath.startsWith(contextPath)) {
  String message = &quot;ERROR: The module path requested, &quot;
      + modulePath
      + &quot;, is not in the same web application as this servlet, &quot;
      + contextPath
      + &quot;.  Your module may not be properly configured or your client and server code maybe out of date.&quot;;
  log(message, null);
}
&lt;/pre&gt;&lt;p&gt;In the above code, you might notice that GWT is checking to make sure the client is hosted in the same application as the server. After I figured this out, it was pretty easy to modify my ProxyServlet to trick GWT RPC into thinking the client was in the same web application. In the ProxyServlet&apos;s &lt;em&gt;handleContentPost&lt;/em&gt; method, I added the following code to replace &quot;localhost:8888/&quot; with &quot;localhost:8080/services/&quot; (in the content of the post to the server).
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
if (contentType.startsWith(&quot;text/x-gwt-rpc&quot;)) {
    String clientHost = httpServletRequest.getLocalName();
    if (clientHost.equals(&quot;127.0.0.1&quot;)) {
        clientHost = &quot;localhost&quot;;
    }

    int clientPort = httpServletRequest.getLocalPort();
    String clientUrl = clientHost + ((clientPort != 80) ? &quot;:&quot; + 
                       clientPort : &quot;&quot;);
    String serverUrl = stringProxyHost + ((intProxyPort != 80) ? &quot;:&quot; + 
                       intProxyPort : &quot;&quot;) + httpServletRequest.getServletPath();
    postContent = postContent.replace(clientUrl , serverUrl);
}
&lt;/pre&gt;&lt;p&gt;After manipulating the posted content, I was successfully able to use GWT RPC cross-domain. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Woo hoo!&lt;/em&gt; 
&lt;/p&gt;
&lt;p&gt;
For your convenience, the full &lt;em&gt;handleContentPost()&lt;/em&gt; method is listed below.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
private void handleContentPost(PostMethod postMethodProxyRequest, 
                               HttpServletRequest httpServletRequest) 
            throws IOException, ServletException {
    StringBuilder content = new StringBuilder();
    BufferedReader reader = httpServletRequest.getReader();
    for (;;) {
        String line = reader.readLine();
        if (line == null) break;
        content.append(line);
    }

    String contentType = httpServletRequest.getContentType();
    String postContent = content.toString();

    if (contentType.startsWith(&quot;text/x-gwt-rpc&quot;)) {
        String clientHost = httpServletRequest.getLocalName();
        if (clientHost.equals(&quot;127.0.0.1&quot;)) {
            clientHost = &quot;localhost&quot;;
        }

        int clientPort = httpServletRequest.getLocalPort();
        String clientUrl = clientHost + ((clientPort != 80) ? &quot;:&quot; + 
                           clientPort : &quot;&quot;);
        String serverUrl = stringProxyHost + ((intProxyPort != 80) ? &quot;:&quot; + 
                           intProxyPort : &quot;&quot;) + httpServletRequest.getServletPath();
        postContent = postContent.replace(clientUrl , serverUrl);
    }

    String encoding = httpServletRequest.getCharacterEncoding();
    debug(&quot;POST Content Type: &quot; + contentType + &quot; Encoding: &quot; + encoding,
          &quot;Content: &quot; + postContent);
    StringRequestEntity entity;
    try {
        entity = new StringRequestEntity(postContent, contentType, encoding);
    } catch (UnsupportedEncodingException e) {
        throw new ServletException(e);
    }
    // Set the proxy request POST data
    postMethodProxyRequest.setRequestEntity(entity);
}
&lt;/pre&gt;
&lt;a name=&quot;proxyServlet&quot;&gt;&lt;/a&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; In the comments, Ganesh asked for more details, so I figured it&apos;d be a good idea to post the full source code. First of all, &lt;a href=&quot;http://raibledesigns.com/rd/entry/how_to_do_cross_domain#proxyServlet&quot; onclick=&quot;($(&apos;#proxyServletCode&apos;).is(&apos;:visible&apos;) ? $(&apos;#proxyServletCode&apos;).hide() : $(&apos;#proxyServletCode&apos;).show()); return false&quot;&gt;click here&lt;/a&gt; to see the code for the ProxyServlet:
&lt;/p&gt;
&lt;div style=&quot;display: none&quot; id=&quot;proxyServletCode&quot;&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;

/**
 * ProxyServlet from http://edwardstx.net/wiki/attach/HttpProxyServlet/ProxyServlet.java
 * (This seems to be a derivative of Noodle -- http://noodle.tigris.org/)
 * 
 * Patched to skip &quot;Transfer-Encoding: chunked&quot; headers, avoid double slashes
 * in proxied URLs, handle GZip and allow GWT RPC.
 */
public class ProxyServlet extends HttpServlet {

    private static final int FOUR_KB = 4196;

    /**
     * Serialization UID.
     */
    private static final long serialVersionUID = 1L;
    /**
     * Key for redirect location header.
     */
    private static final String STRING_LOCATION_HEADER = &quot;Location&quot;;
    /**
     * Key for content type header.
     */
    private static final String STRING_CONTENT_ENGINE_HEADER_NAME = &quot;Content-Type&quot;;
    /**
     * Key for content length header.
     */
    private static final String STRING_CONTENT_LENGTH_HEADER_NAME = &quot;Content-Length&quot;;
    /**
     * Key for host header
     */
    private static final String STRING_HOST_HEADER_NAME = &quot;Host&quot;;
    /**
     * The directory to use to temporarily store uploaded files
     */
    private static final File FILE_UPLOAD_TEMP_DIRECTORY = new File(System.getProperty(&quot;java.io.tmpdir&quot;));

    // Proxy host params
    /**
     * The host to which we are proxying requests. Default value is &quot;localhost&quot;.
     */
    private String stringProxyHost = &quot;localhost&quot;;
    /**
     * The port on the proxy host to wihch we are proxying requests. Default value is 80.
     */
    private int intProxyPort = 80;
    /**
     * The (optional) path on the proxy host to wihch we are proxying requests. Default value is &quot;&quot;.
     */
    private String stringProxyPath = &quot;&quot;;
    /**
     * Setting that allows removing the initial path from client. Allows specifying /twitter/* as synonym for twitter.com.
     */
    private boolean removePrefix;
    /**
     * The maximum size for uploaded files in bytes. Default value is 5MB.
     */
    private int intMaxFileUploadSize = 5 * 1024 * 1024;
    private boolean isSecure;
    private boolean followRedirects;

    /**
     * Initialize the &amp;lt;code&amp;gt;ProxyServlet&amp;lt;/code&amp;gt;
     * @param servletConfig The Servlet configuration passed in by the servlet container
     */
    public void init(ServletConfig servletConfig) {
        // Get the proxy host
        String stringProxyHostNew = servletConfig.getInitParameter(&quot;proxyHost&quot;);
        if (stringProxyHostNew == null || stringProxyHostNew.length() == 0) {
            throw new IllegalArgumentException(&quot;Proxy host not set, please set init-param &apos;proxyHost&apos; in web.xml&quot;);
        }
        this.setProxyHost(stringProxyHostNew);
        // Get the proxy port if specified
        String stringProxyPortNew = servletConfig.getInitParameter(&quot;proxyPort&quot;);
        if (stringProxyPortNew != null &amp;amp;&amp;amp; stringProxyPortNew.length() &amp;gt; 0) {
            this.setProxyPort(Integer.parseInt(stringProxyPortNew));
        }
        // Get the proxy path if specified
        String stringProxyPathNew = servletConfig.getInitParameter(&quot;proxyPath&quot;);
        if (stringProxyPathNew != null &amp;amp;&amp;amp; stringProxyPathNew.length() &amp;gt; 0) {
            this.setProxyPath(stringProxyPathNew);
        }
        // Get the maximum file upload size if specified
        String stringMaxFileUploadSize = servletConfig.getInitParameter(&quot;maxFileUploadSize&quot;);
        if (stringMaxFileUploadSize != null &amp;amp;&amp;amp; stringMaxFileUploadSize.length() &amp;gt; 0) {
            this.setMaxFileUploadSize(Integer.parseInt(stringMaxFileUploadSize));
        }
    }

    /**
     * Performs an HTTP GET request
     * @param httpServletRequest The {@link HttpServletRequest} object passed
     *                            in by the servlet engine representing the
     *                            client request to be proxied
     * @param httpServletResponse The {@link HttpServletResponse} object by which
     *                             we can send a proxied response to the client
     */
    public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws IOException, ServletException {
        // Create a GET request
        String destinationUrl = this.getProxyURL(httpServletRequest);
        debug(&quot;GET Request URL: &quot; + httpServletRequest.getRequestURL(),
              &quot;Destination URL: &quot; + destinationUrl);
        GetMethod getMethodProxyRequest = new GetMethod(destinationUrl);
        // Forward the request headers
        setProxyRequestHeaders(httpServletRequest, getMethodProxyRequest);
        setProxyRequestCookies(httpServletRequest, getMethodProxyRequest);
        // Execute the proxy request
        this.executeProxyRequest(getMethodProxyRequest, httpServletRequest, httpServletResponse);
    }

    /**
     * Performs an HTTP POST request
     * @param httpServletRequest The {@link HttpServletRequest} object passed
     *                            in by the servlet engine representing the
     *                            client request to be proxied
     * @param httpServletResponse The {@link HttpServletResponse} object by which
     *                             we can send a proxied response to the client
     */
    public void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws IOException, ServletException {
        // Create a standard POST request
        String contentType = httpServletRequest.getContentType();
        String destinationUrl = this.getProxyURL(httpServletRequest);
        debug(&quot;POST Request URL: &quot; + httpServletRequest.getRequestURL(),
              &quot;    Content Type: &quot; + contentType,
              &quot; Destination URL: &quot; + destinationUrl);
        PostMethod postMethodProxyRequest = new PostMethod(destinationUrl);
        // Forward the request headers
        setProxyRequestHeaders(httpServletRequest, postMethodProxyRequest);
        setProxyRequestCookies(httpServletRequest, postMethodProxyRequest);
        // Check if this is a mulitpart (file upload) POST
        if (ServletFileUpload.isMultipartContent(httpServletRequest)) {
            this.handleMultipartPost(postMethodProxyRequest, httpServletRequest);
        } else {
            if (contentType == null || PostMethod.FORM_URL_ENCODED_CONTENT_ENGINE.equals(contentType)) {
                this.handleStandardPost(postMethodProxyRequest, httpServletRequest);
            } else {
                this.handleContentPost(postMethodProxyRequest, httpServletRequest);
            }
        }
        // Execute the proxy request
        this.executeProxyRequest(postMethodProxyRequest, httpServletRequest, httpServletResponse);
    }

    /**
     * Sets up the given {@link PostMethod} to send the same multipart POST
     * data as was sent in the given {@link HttpServletRequest}
     * @param postMethodProxyRequest The {@link PostMethod} that we are
     *                                configuring to send a multipart POST request
     * @param httpServletRequest The {@link HttpServletRequest} that contains
     *                            the mutlipart POST data to be sent via the {@link PostMethod}
     */
    @SuppressWarnings(&quot;unchecked&quot;)
    private void handleMultipartPost(PostMethod postMethodProxyRequest, HttpServletRequest httpServletRequest)
            throws ServletException {
        // Create a factory for disk-based file items
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        // Set factory constraints
        diskFileItemFactory.setSizeThreshold(this.getMaxFileUploadSize());
        diskFileItemFactory.setRepository(FILE_UPLOAD_TEMP_DIRECTORY);
        // Create a new file upload handler
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
        // Parse the request
        try {
            // Get the multipart items as a list
            List&amp;lt;FileItem&amp;gt; listFileItems = (List&amp;lt;FileItem&amp;gt;) servletFileUpload.parseRequest(httpServletRequest);
            // Create a list to hold all of the parts
            List&amp;lt;Part&amp;gt; listParts = new ArrayList&amp;lt;Part&amp;gt;();
            // Iterate the multipart items list
            for (FileItem fileItemCurrent : listFileItems) {
                // If the current item is a form field, then create a string part
                if (fileItemCurrent.isFormField()) {
                    StringPart stringPart = new StringPart(
                            fileItemCurrent.getFieldName(), // The field name
                            fileItemCurrent.getString() // The field value
                            );
                    // Add the part to the list
                    listParts.add(stringPart);
                } else {
                    // The item is a file upload, so we create a FilePart
                    FilePart filePart = new FilePart(
                            fileItemCurrent.getFieldName(), // The field name
                            new ByteArrayPartSource(
                            fileItemCurrent.getName(), // The uploaded file name
                            fileItemCurrent.get() // The uploaded file contents
                            ));
                    // Add the part to the list
                    listParts.add(filePart);
                }
            }
            MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(
                    listParts.toArray(new Part&amp;#91;&amp;#93;{}),
                    postMethodProxyRequest.getParams());
            postMethodProxyRequest.setRequestEntity(multipartRequestEntity);
            // The current content-type header (received from the client) IS of
            // type &quot;multipart/form-data&quot;, but the content-type header also
            // contains the chunk boundary string of the chunks. Currently, this
            // header is using the boundary of the client request, since we
            // blindly copied all headers from the client request to the proxy
            // request. However, we are creating a new request with a new chunk
            // boundary string, so it is necessary that we re-set the
            // content-type string to reflect the new chunk boundary string
            postMethodProxyRequest.setRequestHeader(STRING_CONTENT_ENGINE_HEADER_NAME, multipartRequestEntity.getContentType());
        } catch (FileUploadException fileUploadException) {
            throw new ServletException(fileUploadException);
        }
    }

    /**
     * Sets up the given {@link PostMethod} to send the same standard POST
     * data as was sent in the given {@link HttpServletRequest}
     * @param postMethodProxyRequest The {@link PostMethod} that we are
     *                                configuring to send a standard POST request
     * @param httpServletRequest The {@link HttpServletRequest} that contains
     *                            the POST data to be sent via the {@link PostMethod}
     */
    @SuppressWarnings(&quot;unchecked&quot;)
    private void handleStandardPost(PostMethod postMethodProxyRequest, HttpServletRequest httpServletRequest) {
        // Get the client POST data as a Map
        Map&amp;lt;String, String&amp;#91;&amp;#93;&amp;gt; mapPostParameters = (Map&amp;lt;String, String&amp;#91;&amp;#93;&amp;gt;) httpServletRequest.getParameterMap();
        // Create a List to hold the NameValuePairs to be passed to the PostMethod
        List&amp;lt;NameValuePair&amp;gt; listNameValuePairs = new ArrayList&amp;lt;NameValuePair&amp;gt;();
        // Iterate the parameter names
        for (String stringParameterName : mapPostParameters.keySet()) {
            // Iterate the values for each parameter name
            String&amp;#91;&amp;#93; stringArrayParameterValues = mapPostParameters.get(stringParameterName);
            for (String stringParamterValue : stringArrayParameterValues) {
                // Create a NameValuePair and store in list
                NameValuePair nameValuePair = new NameValuePair(stringParameterName, stringParamterValue);
                listNameValuePairs.add(nameValuePair);
            }
        }
        // Set the proxy request POST data
        postMethodProxyRequest.setRequestBody(listNameValuePairs.toArray(new NameValuePair&amp;#91;&amp;#93;{}));
    }

    /**
     * Sets up the given {@link PostMethod} to send the same content POST
     * data (JSON, XML, etc.) as was sent in the given {@link HttpServletRequest}
     * @param postMethodProxyRequest The {@link PostMethod} that we are
     *                                configuring to send a standard POST request
     * @param httpServletRequest The {@link HttpServletRequest} that contains
     *                            the POST data to be sent via the {@link PostMethod}
     */
    private void handleContentPost(PostMethod postMethodProxyRequest, HttpServletRequest httpServletRequest) throws IOException, ServletException {
        StringBuilder content = new StringBuilder();
        BufferedReader reader = httpServletRequest.getReader();
        for (;;) {
            String line = reader.readLine();
            if (line == null) break;
            content.append(line);
        }

        String contentType = httpServletRequest.getContentType();
        String postContent = content.toString();

        if (contentType.startsWith(&quot;text/x-gwt-rpc&quot;)) {
            String clientHost = httpServletRequest.getLocalName();
            if (clientHost.equals(&quot;127.0.0.1&quot;)) {
                clientHost = &quot;localhost&quot;;
            }

            int clientPort = httpServletRequest.getLocalPort();
            String clientUrl = clientHost + ((clientPort != 80) ? &quot;:&quot; + clientPort : &quot;&quot;);
            String serverUrl = stringProxyHost + ((intProxyPort != 80) ? &quot;:&quot; + intProxyPort : &quot;&quot;) + httpServletRequest.getServletPath();
            //debug(&quot;Replacing client (&quot; + clientUrl + &quot;) with server (&quot; + serverUrl + &quot;)&quot;);
            postContent = postContent.replace(clientUrl , serverUrl);
        }

        String encoding = httpServletRequest.getCharacterEncoding();
        debug(&quot;POST Content Type: &quot; + contentType + &quot; Encoding: &quot; + encoding,
              &quot;Content: &quot; + postContent);
        StringRequestEntity entity;
        try {
            entity = new StringRequestEntity(postContent, contentType, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new ServletException(e);
        }
        // Set the proxy request POST data
        postMethodProxyRequest.setRequestEntity(entity);
    }

    /**
     * Executes the {@link HttpMethod} passed in and sends the proxy response
     * back to the client via the given {@link HttpServletResponse}
     * @param httpMethodProxyRequest An object representing the proxy request to be made
     * @param httpServletResponse An object by which we can send the proxied
     *                             response back to the client
     * @throws IOException Can be thrown by the {@link HttpClient}.executeMethod
     * @throws ServletException Can be thrown to indicate that another error has occurred
     */
    private void executeProxyRequest(
            HttpMethod httpMethodProxyRequest,
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse)
            throws IOException, ServletException {
        // Create a default HttpClient
        HttpClient httpClient = new HttpClient();
        httpMethodProxyRequest.setFollowRedirects(false);
        // Execute the request
        int intProxyResponseCode = httpClient.executeMethod(httpMethodProxyRequest);
        String response = httpMethodProxyRequest.getResponseBodyAsString();

        // Check if the proxy response is a redirect
        // The following code is adapted from org.tigris.noodle.filters.CheckForRedirect
        // Hooray for open source software
        if (intProxyResponseCode &amp;gt;= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */ &amp;amp;&amp;amp; intProxyResponseCode &amp;lt; HttpServletResponse.SC_NOT_MODIFIED /* 304 */) {
            String stringStatusCode = Integer.toString(intProxyResponseCode);
            String stringLocation = httpMethodProxyRequest.getResponseHeader(STRING_LOCATION_HEADER).getValue();
            if (stringLocation == null) {
                throw new ServletException(&quot;Received status code: &quot; + stringStatusCode + &quot; but no &quot; + STRING_LOCATION_HEADER + &quot; header was found in the response&quot;);
            }
            // Modify the redirect to go to this proxy servlet rather that the proxied host
            String stringMyHostName = httpServletRequest.getServerName();
            if (httpServletRequest.getServerPort() != 80) {
                stringMyHostName += &quot;:&quot; + httpServletRequest.getServerPort();
            }
            stringMyHostName += httpServletRequest.getContextPath();
            if (followRedirects) {
                if (stringLocation.contains(&quot;jsessionid&quot;)) {
                    Cookie cookie = new Cookie(&quot;JSESSIONID&quot;, stringLocation.substring(stringLocation.indexOf(&quot;jsessionid=&quot;) + 11));
                    cookie.setPath(&quot;/&quot;);
                    httpServletResponse.addCookie(cookie);
                    //debug(&quot;redirecting: set jessionid (&quot; + cookie.getValue() + &quot;) cookie from URL&quot;);
                } else if (httpMethodProxyRequest.getResponseHeader(&quot;Set-Cookie&quot;) != null) {
	                Header header = httpMethodProxyRequest.getResponseHeader(&quot;Set-Cookie&quot;);
                    String&amp;#91;&amp;#93; cookieDetails = header.getValue().split(&quot;;&quot;);
					String&amp;#91;&amp;#93; nameValue = cookieDetails&amp;#91;0&amp;#93;.split(&quot;=&quot;);

					Cookie cookie = new Cookie(nameValue&amp;#91;0&amp;#93;, nameValue&amp;#91;1&amp;#93;);
					cookie.setPath(&quot;/&quot;);
					//debug(&quot;redirecting: setting cookie: &quot; + cookie.getName() + &quot;:&quot; + cookie.getValue() + &quot; on &quot; + cookie.getPath());
					httpServletResponse.addCookie(cookie);
                }
                httpServletResponse.sendRedirect(stringLocation.replace(getProxyHostAndPort() + this.getProxyPath(), stringMyHostName));
                return;
            }
        } else if (intProxyResponseCode == HttpServletResponse.SC_NOT_MODIFIED) {
            // 304 needs special handling.  See:
            // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304
            // We get a 304 whenever passed an &apos;If-Modified-Since&apos;
            // header and the data on disk has not changed; server
            // responds w/ a 304 saying I&apos;m not going to send the
            // body because the file has not changed.
            httpServletResponse.setIntHeader(STRING_CONTENT_LENGTH_HEADER_NAME, 0);
            httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            return;
        }

        // Pass the response code back to the client
        httpServletResponse.setStatus(intProxyResponseCode);

        // Pass response headers back to the client
        Header&amp;#91;&amp;#93; headerArrayResponse = httpMethodProxyRequest.getResponseHeaders();
        for (Header header : headerArrayResponse) {
            if (header.getName().equals(&quot;Transfer-Encoding&quot;) &amp;amp;&amp;amp; header.getValue().equals(&quot;chunked&quot;) ||
                    header.getName().equals(&quot;Content-Encoding&quot;) &amp;amp;&amp;amp; header.getValue().equals(&quot;gzip&quot;) || // don&apos;t copy gzip header
                    header.getName().equals(&quot;WWW-Authenticate&quot;)) { // don&apos;t copy WWW-Authenticate header so browser doesn&apos;t prompt on failed basic auth
                // proxy servlet does not support chunked encoding
            } else {
                httpServletResponse.setHeader(header.getName(), header.getValue());
            }
        }

        List&amp;lt;Header&amp;gt; responseHeaders = Arrays.asList(headerArrayResponse);

        if (isBodyParameterGzipped(responseHeaders)) {
            debug(&quot;GZipped: true&quot;);
            if (!followRedirects &amp;amp;&amp;amp; intProxyResponseCode == HttpServletResponse.SC_MOVED_TEMPORARILY) {
                response = httpMethodProxyRequest.getResponseHeader(STRING_LOCATION_HEADER).getValue();
                httpServletResponse.setStatus(HttpServletResponse.SC_OK);
                intProxyResponseCode = HttpServletResponse.SC_OK;
                httpServletResponse.setHeader(STRING_LOCATION_HEADER, response);
            } else {
                response = new String(ungzip(httpMethodProxyRequest.getResponseBody()));
            }
            httpServletResponse.setContentLength(response.length());
        }

        // Send the content to the client
        debug(&quot;Received status code: &quot; + intProxyResponseCode,
              &quot;Response: &quot; + response);

        httpServletResponse.getWriter().write(response);
    }


    /**
     * The response body will be assumed to be gzipped if the GZIP header has been set.
     *
     * @param responseHeaders of response headers
     * @return true if the body is gzipped
     */
    private boolean isBodyParameterGzipped(List&amp;lt;Header&amp;gt; responseHeaders) {
        for (Header header : responseHeaders) {
            if (header.getValue().equals(&quot;gzip&quot;)) {
                return true;
            }
        }
        return false;
    }

    /**
     * A highly performant ungzip implementation. Do not refactor this without taking new timings.
     * See ElementTest in ehcache for timings
     *
     * @param gzipped the gzipped content
     * @return an ungzipped byte&amp;#91;&amp;#93;
     * @throws java.io.IOException when something bad happens
     */
    private byte&amp;#91;&amp;#93; ungzip(final byte&amp;#91;&amp;#93; gzipped) throws IOException {
        final GZIPInputStream inputStream = new GZIPInputStream(new ByteArrayInputStream(gzipped));
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(gzipped.length);
        final byte&amp;#91;&amp;#93; buffer = new byte&amp;#91;FOUR_KB&amp;#93;;
        int bytesRead = 0;
        while (bytesRead != -1) {
            bytesRead = inputStream.read(buffer, 0, FOUR_KB);
            if (bytesRead != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
        }
        byte&amp;#91;&amp;#93; ungzipped = byteArrayOutputStream.toByteArray();
        inputStream.close();
        byteArrayOutputStream.close();
        return ungzipped;
    }

    public String getServletInfo() {
        return &quot;GWT Proxy Servlet&quot;;
    }

    /**
     * Retrieves all of the headers from the servlet request and sets them on
     * the proxy request
     *
     * @param httpServletRequest The request object representing the client&apos;s
     *                            request to the servlet engine
     * @param httpMethodProxyRequest The request that we are about to send to
     *                                the proxy host
     */
    @SuppressWarnings(&quot;unchecked&quot;)
    private void setProxyRequestHeaders(HttpServletRequest httpServletRequest, HttpMethod httpMethodProxyRequest) {
        // Get an Enumeration of all of the header names sent by the client
        Enumeration enumerationOfHeaderNames = httpServletRequest.getHeaderNames();
        while (enumerationOfHeaderNames.hasMoreElements()) {
            String stringHeaderName = (String) enumerationOfHeaderNames.nextElement();
            if (stringHeaderName.equalsIgnoreCase(STRING_CONTENT_LENGTH_HEADER_NAME)) {
                continue;
            }
            // As per the Java Servlet API 2.5 documentation:
            //		Some headers, such as Accept-Language can be sent by clients
            //		as several headers each with a different value rather than
            //		sending the header as a comma separated list.
            // Thus, we get an Enumeration of the header values sent by the client
            Enumeration enumerationOfHeaderValues = httpServletRequest.getHeaders(stringHeaderName);
            while (enumerationOfHeaderValues.hasMoreElements()) {
                String stringHeaderValue = (String) enumerationOfHeaderValues.nextElement();
                // In case the proxy host is running multiple virtual servers,
                // rewrite the Host header to ensure that we get content from
                // the correct virtual server
                if (stringHeaderName.equalsIgnoreCase(STRING_HOST_HEADER_NAME)) {
                    stringHeaderValue = getProxyHostAndPort();
                }
                Header header = new Header(stringHeaderName, stringHeaderValue);
                // Set the same header on the proxy request
                httpMethodProxyRequest.setRequestHeader(header);
            }
        }
    }

    /**
     * Retrieves all of the cookies from the servlet request and sets them on
     * the proxy request
     *
     * @param httpServletRequest The request object representing the client&apos;s
     *                            request to the servlet engine
     * @param httpMethodProxyRequest The request that we are about to send to
     *                                the proxy host
     */
    @SuppressWarnings(&quot;unchecked&quot;)
    private void setProxyRequestCookies(HttpServletRequest httpServletRequest, HttpMethod httpMethodProxyRequest) {
        // Get an array of all of all the cookies sent by the client
        Cookie&amp;#91;&amp;#93; cookies = httpServletRequest.getCookies();
        if (cookies == null) {
            return;
        }

        for (Cookie cookie : cookies) {
            cookie.setDomain(stringProxyHost);
            cookie.setPath(httpServletRequest.getServletPath());
            httpMethodProxyRequest.setRequestHeader(&quot;Cookie&quot;, cookie.getName() + &quot;=&quot; + cookie.getValue() + &quot;; Path=&quot; + cookie.getPath());
        }
    }

    // Accessors
    private String getProxyURL(HttpServletRequest httpServletRequest) {
        // Set the protocol to HTTP
        String protocol = (isSecure) ? &quot;https://&quot; : &quot;http://&quot;;
        String stringProxyURL = protocol + this.getProxyHostAndPort();

        // simply use whatever servlet path that was part of the request as opposed to getting a preset/configurable proxy path
        if (!removePrefix) {
            stringProxyURL += httpServletRequest.getServletPath();
        }
        stringProxyURL += &quot;/&quot;;
        
        // Handle the path given to the servlet
        String pathInfo = httpServletRequest.getPathInfo();
        if (pathInfo != null &amp;amp;&amp;amp; pathInfo.startsWith(&quot;/&quot;)) {
            if (stringProxyURL != null &amp;amp;&amp;amp; stringProxyURL.endsWith(&quot;/&quot;)) {
                // avoid double &apos;/&apos;
                stringProxyURL += pathInfo.substring(1);
            }
        } else {
            stringProxyURL += httpServletRequest.getPathInfo();
        }
        // Handle the query string
        if (httpServletRequest.getQueryString() != null) {
            stringProxyURL += &quot;?&quot; + httpServletRequest.getQueryString();
        }
        
        return stringProxyURL;
    }

    private String getProxyHostAndPort() {
        if (this.getProxyPort() == 80) {
            return this.getProxyHost();
        } else {
            return this.getProxyHost() + &quot;:&quot; + this.getProxyPort();
        }
    }

    protected String getProxyHost() {
        return this.stringProxyHost;
    }

    protected void setProxyHost(String stringProxyHostNew) {
        this.stringProxyHost = stringProxyHostNew;
    }

    protected int getProxyPort() {
        return this.intProxyPort;
    }

    protected void setSecure(boolean secure) {
        this.isSecure = secure;
    }
    
    protected void setFollowRedirects(boolean followRedirects) {
        this.followRedirects = followRedirects;
    }

    protected void setProxyPort(int intProxyPortNew) {
        this.intProxyPort = intProxyPortNew;
    }

    protected String getProxyPath() {
        return this.stringProxyPath;
    }

    protected void setProxyPath(String stringProxyPathNew) {
        this.stringProxyPath = stringProxyPathNew;
    }

    protected void setRemovePrefix(boolean removePrefix) {
        this.removePrefix = removePrefix;
    }

    protected int getMaxFileUploadSize() {
        return this.intMaxFileUploadSize;
    }

    protected void setMaxFileUploadSize(int intMaxFileUploadSizeNew) {
        this.intMaxFileUploadSize = intMaxFileUploadSizeNew;
    }

    private void debug(String ... msg) {
        for (String m : msg) {
            System.out.println(&quot;&amp;#91;DEBUG&amp;#93; &quot; + m);
        }
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I generally subclass ProxyServlet to provide my own configuration:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class MyProxyServlet extends ProxyServlet {

    @Override
    public void init(ServletConfig servletConfig) {
        setFollowRedirects(true);
        setRemovePrefix(false);
        setProxyPort(8080);
    }
}
&lt;/pre&gt;
&lt;p&gt;Here&apos;s another example that reads configuration settings from web.xml and proxies to a different domain name:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class AlternateHostProxyServlet extends ProxyServlet {

    @Override
    public void init(ServletConfig servletConfig) {

        setProxyHost(servletConfig.getInitParameter(&quot;proxyHost&quot;));

        String secure = servletConfig.getInitParameter(&quot;secure&quot;);
        if (secure != null) {
            setSecure(Boolean.valueOf(secure));
        }

        setFollowRedirects(false);
        setRemovePrefix(true);
        setProxyPort(80);
    }
}
&lt;/pre&gt;
&lt;p&gt;After you&apos;ve added these to your project, simply map the servlet (and its path) in your *.gwt.xml file (if you&apos;re using GWT) and your web.xml.</description>          </item>
    <item>
    <guid isPermaLink="true">https://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>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/how_to_use_gwt_2</link>
        <pubDate>Thu, 25 Jun 2009 23:45:04 -0600</pubDate>
    <category>Java</category>
    <category>gwt-maven-plugin</category>
    <category>runasync</category>
    <category>maven</category>
    <category>soyc</category>
    <category>gwt</category>
            <description>One of the most interesting features coming in GWT 2.0 is &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting&quot;&gt;code splitting&lt;/a&gt; and the ability to use GWT.runAsync() to reduce the size of your application&apos;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=&quot;http://code.google.com/webtoolkit/makinggwtbetter.html#compiling&quot;&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=&quot;margin-top: 5px&quot;&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=&quot;margin-bottom: 5px; text-align: right&quot;&gt;&lt;em&gt;Thanks to &lt;a href=&quot;http://groups.google.com/group/codehaus-mojo-gwt-maven-plugin-users/browse_thread/thread/83e860b1de4565f5&quot;&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=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;gwt-maven-plugin&lt;/a&gt; from Codehaus. Of course, you&apos;ll need to modify the &amp;lt;runTarget&amp;gt; to fit your project.
&lt;pre class=&quot;brush: xml&quot;&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=&quot;brush: xml&quot;&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&apos;s code splitting documentation, it mentions &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting#The_Story_of_Your_Compile_(SOYC)&quot;&gt;The Story of Your Compile (SOYC)&lt;/a&gt;. From the documentation:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&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=&quot;http://jira.codehaus.org/browse/MGWT-92&quot;&gt;created a patch for it&lt;/a&gt;. 
&lt;/p&gt;
&lt;p style=&quot;margin-left: 20px; color: #666&quot;&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&apos;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=&quot;http://mojo.codehaus.org/exec-maven-plugin/&quot;&gt;exec-maven-plugin&lt;/a&gt;. Here&apos;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&apos;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&apos;s 5 of each these files and I&apos;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=&quot;brush: xml&quot;&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&apos;t seem to be much documentation on SOYC. &lt;a href=&quot;http://www.slideshare.net/fredsa/gwt-overview-and-feature-preview-sv-web-jug-june-16-2009&quot;&gt;Fred Sauer&apos;s recent presentation&lt;/a&gt; talks a bit about SOYC and GWT.runAsync(), but that&apos;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=&quot;http://raibledesigns.com/rd/entry/gxt_s_mvc_framework&quot;&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&apos;s controllers so their &lt;em&gt;handleEvent()&lt;/em&gt; methods changed from this:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void handleEvent(AppEvent&lt;?&gt; event) {
    onViewHome(event);
}
&lt;/pre&gt;
&lt;p&gt;To this:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&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 &quot;Leftovers code&quot; consisted of 63,175 KB. I&apos;m sure there&apos;s better ways to split my project using GWT.runAsync(), but I&apos;m happy to see I was able to reduce the initial download by 50%. &lt;/p&gt;
&lt;p&gt;If you&apos;d like to try GWT 2.0, you can can &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-mvc-1.1.zip&quot;&gt;download my gwt-mvc example project&lt;/a&gt;. To build/run this project, you&apos;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&apos;s pretty cool that you can try out GWT 2.0 features while they&apos;re still being developed.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/json_parsing_with_javascript_overlay</guid>
    <title>JSON Parsing with JavaScript Overlay Types in GWT</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/json_parsing_with_javascript_overlay</link>
        <pubDate>Wed, 24 Jun 2009 09:52:49 -0600</pubDate>
    <category>Java</category>
    <category>twitter</category>
    <category>javascript</category>
    <category>json</category>
    <category>gwt</category>
    <category>overlaytypes</category>
    <category>requestbuilder</category>
            <description>A reader recently &lt;a href=&quot;http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt#comment-1245137914000&quot;&gt;asked&lt;/a&gt;:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&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&apos;t know how to do this &quot;reading&quot; dynamically at runtime.&lt;/p&gt;
&lt;p&gt;If you&apos;re not familiar with GWT&apos;s Overlay Types (added in 1.5), see &lt;a href=&quot;http://googlewebtoolkit.blogspot.com/2008/08/getting-to-really-know-gwt-part-2.html&quot;&gt;Getting to really know GWT, Part 2: JavaScript Overlay Types&lt;/a&gt;. In our project, we&apos;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=&quot;brush: java&quot;&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 &apos;{&quot;foo&quot;:&quot;bar&quot;,&quot;number&quot;:123}&apos;
     *
     * @return a populated JSOModel object
     */
    public static native JSOModel fromJson(String jsonString) /*-{
        return eval(&apos;(&apos; + jsonString + &apos;)&apos;);
    }-*/;

    /**
     * Convert a JSON encoded string into an array of JSOModel instance.
     * &amp;lt;p/&amp;gt;
     * Expects a JSON string structured like &apos;&amp;#91;{&quot;foo&quot;:&quot;bar&quot;,&quot;number&quot;:123}, {...}&amp;#93;&apos;
     *
     * @return a populated JsArray
     */
    public static native JsArray&amp;lt;JSOModel&amp;gt; arrayFromJson(String jsonString) /*-{
        return eval(&apos;(&apos; + jsonString + &apos;)&apos;);
    }-*/;

    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 &quot;&quot; + this&amp;#91;key&amp;#93;;
    }-*/;

    public final native String get(String key, String defaultValue) /*-{
        return this&amp;#91;key&amp;#93; ? (&quot;&quot; + 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&apos;s an example of parsing &lt;a href=&quot;http://twitter.com/statuses/user_timeline.json&quot;&gt;Twitter&apos;s User Timeline&lt;/a&gt; in my &lt;a href=&quot;http://raibledesigns.com/rd/entry/implementing_oauth_with_gwt&quot;&gt;OAuth with GWT&lt;/a&gt; application.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&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(&quot;text&quot;) + &quot;\n\n&quot;);
            }
            
            Label success = new Label(&quot;API call successful!&quot;);
            success.setStyleName(&quot;success&quot;);
            form.add(success);
        } else {
            onError(request, new RequestException(response.getText()));
        }
    }

    public void onError(Request request, Throwable throwable) {
        Window.alert(&quot;Calling API failed. &quot; + OAuthPage.STANDARD_ERROR + &quot;\n\n&quot; + 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=&quot;brush: java&quot;&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; &quot;null&quot;.equals(val) || &quot;undefined&quot;.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=&quot;brush: java&quot;&gt;
public class Status extends BaseModel {
    
    public Status(JSOModel data) {
        super(data);
    }

    public String getText() {
        return get(&quot;text&quot;);
    }
}
&lt;/pre&gt;
&lt;p&gt;Then I could change my JSON parsing in TwitterApiCallback to be:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&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() + &quot;\n\n&quot;);
            }

            Label success = new Label(&quot;API call successful!&quot;);
            success.setStyleName(&quot;success&quot;);
            form.add(success);
        } else {
            onError(request, new RequestException(response.getText()));
        }
    }

    public void onError(Request request, Throwable throwable) {
        Window.alert(&quot;Calling API failed. &quot; + OAuthPage.STANDARD_ERROR + &quot;\n\n&quot; + throwable.getMessage());
    }
}
&lt;/pre&gt;
&lt;p&gt;That&apos;s how we&apos;re doing lightweight JSON parsing with GWT. I&apos;ve updated my &lt;a href=&quot;http://demo.raibledesigns.com/gwt-oauth/&quot;&gt;GWT with OAuth demo&lt;/a&gt; with this code. You can also &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-oauth-1.1.zip&quot;&gt;download the source&lt;/a&gt;. Please let me know if you have any questions. &lt;/p&gt;
&lt;p id=&quot;update1&quot;&gt;&lt;strong&gt;Update October 20, 2009:&lt;/strong&gt; I recently had to enhance the JSOModel and BaseModel classes in my project to handle nested objects and arrays. In my project, I have a Conversation object that has a Channel and a List of Task objects. These objects are available in the JSOModel of my BaseModel, I just needed to grab them a bit differently. 
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public Channel getChannel() {
    return new Channel(data.getObject(&quot;channel&quot;));
}

public List&amp;lt;Task&amp;gt; getTasks() {
    JsArray&amp;lt;JSOModel&amp;gt; array = data.getArray(&quot;tasks&quot;);
    List&amp;lt;Task&amp;gt; tasks = new ArrayList&amp;lt;Task&amp;gt;(array.length());

    for (int i = 0; i &amp;lt; array.length(); i++) {
        Task task = new Task(array.get(i));
        tasks.add(task);
    }
    
    return tasks;
}
&lt;/pre&gt;
&lt;p&gt;To set a Channel, it&apos;s as simple as:
&lt;pre class=&quot;brush: java&quot;&gt;
data.set(&quot;channel&quot;, channel.toJson().toString());
&lt;/pre&gt;
&lt;p&gt;
To allow setting Lists, I had to enhance JSOModel by adding the following two methods:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public final void set(String key, List&amp;lt;JSOModel&amp;gt; values) {
    JsArray&amp;lt;JSOModel&amp;gt; array = JavaScriptObject.createArray().cast();
    for (int i=0; i &amp;lt; values.size(); i++) {
        array.set(i, values.get(i));
    }
    setArray(key, array);
}

protected final native void setArray(String key, JsArray&amp;lt;JSOModel&amp;gt; values) /*-{
    this&amp;#91;key&amp;#93; = values;
}-*/;
&lt;/pre&gt;
&lt;p&gt;After making this change, I was able to convert my List&lt;Task&gt; to List&lt;JSOModel&gt; and set it on the underlying JSOModel.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void setTasks(List&amp;lt;Task&amp;gt; tasks) {
    List&amp;lt;JSOModel&amp;gt; values = new ArrayList&amp;lt;JSOModel&amp;gt;();
    for (Task task : tasks) {
        values.add(task.getModel());
    }

    data.set(&quot;tasks&quot;, values);
}
&lt;/pre&gt;
&lt;p&gt;To allow the task.getModel() method to work, I added a getter to BaseModel to allow retrieving the underlying JSOModel. Currently, I&apos;m using a homegrown JSON.java class to produce JSON from my BaseModel objects. It all seems to work great and I&apos;m pumped I can receive and send all my JSON using overlay types.
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/implementing_oauth_with_gwt</guid>
    <title>Implementing OAuth with GWT</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/implementing_oauth_with_gwt</link>
        <pubDate>Thu, 18 Jun 2009 13:59:13 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>oauth</category>
    <category>google</category>
    <category>javascript</category>
            <description>I&apos;ve heard about &lt;a href=&quot;http://oauth.net/&quot;&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=&quot;http://oauth.net/about&quot;&gt;Introduction&lt;/a&gt;. Here&apos;s an excerpt: &lt;/p&gt;
&lt;p class=&quot;quote&quot;&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=&quot;http://code.google.com/apis/contacts/&quot;&gt;Google Contacts API&lt;/a&gt;. I&apos;ve always hated how sites make you import all your contacts from Gmail. I wanted to develop a system that&apos;d let you simply read your contacts from Google in real-time.
&lt;/p&gt;
&lt;p&gt;Since the &lt;a href=&quot;http://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt&quot;&gt;application I&apos;m working on uses GWT&lt;/a&gt;, I chose to implement an OAuth client in GWT. After googling for &quot;&lt;a href=&quot;http://www.google.com/search?q=gwt+oauth&quot;&gt;gwt oauth&lt;/a&gt;&quot;, I found &lt;a href=&quot;http://code.google.com/p/gwt-examples/wiki/oAuth&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;www.sergimansilla.com/blog/?p=75&quot;&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&apos;s right folks, I created a solution that only works 50% of the time. I&apos;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=&quot;http://code.google.com/p/oauth/&quot;&gt;oauth on Google Code&lt;/a&gt;. However, you&apos;ll notice that there is no JavaScript implementation listed on the homepage. I did look at the &lt;a href=&quot;http://oauth.googlecode.com/svn/code/java/&quot;&gt;Java&lt;/a&gt; implementation, but quickly realized it wouldn&apos;t be usable in GWT. Therefore, I opted for the &lt;a href=&quot;http://oauth.googlecode.com/svn/code/javascript/&quot;&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=&quot;text-align: center&quot;&gt;
&lt;a href=&quot;http://farm4.static.flickr.com/3384/3638983340_e353831f5c_o.png&quot; title=&quot;OAuth Authentication Flow&quot; rel=&quot;lightbox[gwt-oauth]&quot;&gt;&lt;img src=&quot;//farm4.static.flickr.com/3384/3638983340_4d939fd820.jpg&quot; width=&quot;500&quot; height=&quot;368&quot; alt=&quot;OAuth Authentication Flow&quot; /&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&apos;s OAuth service, you&apos;ll likely need to start by registering your application. For Google, &lt;a href=&quot;http://code.google.com/apis/accounts/docs/OAuth.html&quot;&gt;OAuth Authentication for Web Applications&lt;/a&gt; is an excellent resource. Google&apos;s &lt;a href=&quot;http://googlecodesamples.com/oauth_playground/&quot;&gt;OAuth Playground&lt;/a&gt; is a great way to with the Google Data APIs after you&apos;ve registered.
&lt;/p&gt;
&lt;p&gt;
Now that you know how OAuth works, let&apos;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=&quot;brush: xml&quot;&gt;
&amp;lt;script src=&quot;//oauth.googlecode.com/svn/code/javascript/oauth.js&quot;/&amp;gt;
&amp;lt;script src=&quot;//oauth.googlecode.com/svn/code/javascript/sha1.js&quot;/&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Next, I needed a way to sign the request. I tried to use Sergi Mansilla&apos;s &lt;a href=&quot;http://sergimansilla.com/public/flyqlr/flyqlr/src/com/sergi/client/OAuth.java&quot;&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&apos;s &lt;a href=&quot;http://paul.donnelly.org/2008/10/31/2-legged-oauth-javascript-function-for-yql/&quot;&gt;makeSignedRequest function&lt;/a&gt; instead. By adding this to my application&apos;s HTML page, I&apos;m able to call it using the following JSNI method:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&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&apos;s RequestBuilder and created a &lt;em&gt;send()&lt;/em&gt; method:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&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&apos;s &lt;a href=&quot;https://www.google.com/accounts/OAuthGetRequestToken&quot;&gt;Request Token URL&lt;/a&gt; in GWT&apos;s hosted mode, nothing will happen. Compile/browse to Safari and you&apos;ll still see nothing. Try it in Firefox and you&apos;ll see the following.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;//farm3.static.flickr.com/2437/3639119788_b675d86360_o.png&quot; width=&quot;400&quot; alt=&quot;SOP Error&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;To workaround browsers&apos; &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/FAQ_SOP&quot;&gt;Same Origin Policy&lt;/a&gt;, I added a proxy servlet to send the requests. I started with Jason Edwards&apos;s &lt;a href=&quot;http://edwardstx.net/wiki/attach/HttpProxyServlet/ProxyServlet.java&quot;&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=&quot;brush: xml&quot;&gt;
&amp;lt;servlet path=&quot;/google/&quot; class=&quot;org.appfuse.gwt.servlet.AlternateHostProxyServlet&quot;/&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=&quot;brush:java&quot;&gt;
public void getToken(RequestCallback cb) {
    String url = signRequest(provider.getConsumerKey(), 
                             provider.getConsumerSecret(), 
                             &quot;&quot;, provider.getRequestTokenURL());
    url = url.replace(&quot;https://www.google.com/&quot;, &quot;/google/&quot;);
    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=&quot;brush: java&quot;&gt;
public static String[] createOAuthCookies(String data) {
    String oauth_token = data.substring(data.indexOf(&quot;oauth_token=&quot;) + 12);
    oauth_token = oauth_token.substring(0, oauth_token.indexOf(&quot;&amp;&quot;));

    String oauth_token_secret = data.substring(data.indexOf(&quot;oauth_token_secret=&quot;) + 19);

    Cookies.setCookie(&quot;oauth_token&quot;, URL.decode(oauth_token));
    Cookies.setCookie(&quot;oauth_token_secret&quot;, 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&apos;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&apos;d return an HTML page with a &lt;code&gt;&amp;lt;meta http-equiv=&quot;refresh&quot; ...&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&apos;m using. &lt;a href=&quot;http://gwt-widget.sourceforge.net/docs/xref/org/gwtwidgets/client/util/WindowUtils.html&quot;&gt;WindowUtils&lt;/a&gt; is a class I got from Robert Hanson and the &lt;a href=&quot;http://gwt-widget.sourceforge.net/&quot;&gt;gwt-widget&lt;/a&gt; project.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void onResponseReceived(Request request, Response response) {
    String text = response.getText();
    if (response.getStatusCode() == 200 &amp;&amp; response.getText().startsWith(&quot;http&quot;)) {
        WindowUtils.changeLocation(response.getText());
    } else {
        // look for meta-tag that refreshes and grab its URL
        if (text.contains(&quot;&lt;meta http-equiv=\&quot;refresh\&quot;&quot;)) {
            String tokenToStartWith = &quot;url=&amp;#39;&quot;;
            String tokenToEndWith = &quot;&amp;#39;\&quot;&gt;&quot;;
            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(&quot;$1&quot;, OAuthRequest.getAuthToken());
                url = url.replace(&quot;$2&quot;, DefaultRequest.getCurrentLocation());
                WindowUtils.changeLocation(url);
            } else {
                onError(request, new RequestException(text));
            }
        }
    }
}

public void onError(Request request, Throwable caught) {
    Window.alert(&quot;Calling authorize token failed. &quot; + OAuthPage.STANDARD_ERROR + &quot;\n\n&quot; + 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 &quot;oauth_token_secret&quot; value when signing the request.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&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=&quot;brush: java&quot;&gt;
public class ContactsRequest extends DefaultRequest {
    private static final String GOOGLE_CONTACTS_URL = 
        &quot;http://www.google.com/m8/feeds/contacts/default/thin?oauth_token=$1&quot;;
    private OAuthProvider provider;

    public ContactsRequest(OAuthProvider provider) {
        this.provider = provider;
    }

    public void getContacts(RequestCallback cb) {
        String url = GOOGLE_CONTACTS_URL.replace(&quot;$1&quot;, getAuthToken());
        url = signRequest(provider.getConsumerKey(), provider.getConsumerSecret(), 
                          getAuthTokenSecret(), url);

        String proxiedURLPrefix = &quot;/contacts/&quot;;
        // allow for deploying at /gwt-oauth context
        if (WindowUtils.getLocation().getPath().contains(&quot;gwt-oauth&quot;)) {
            proxiedURLPrefix = &quot;/gwt-oauth&quot; + proxiedURLPrefix;
        }

        url = url.replace(&quot;http://www.google.com/&quot;, proxiedURLPrefix);

        send(cb, url);
    }
}&lt;/pre&gt;
&lt;p&gt;If all goes well, the response contains the data you requested and it&apos;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=&quot;http://groups.google.com/group/oauth/browse_thread/thread/e180000f5bd9dc2c&quot;&gt;a message&lt;/a&gt; to the OAuth Google Group explaining the issues I&apos;ve had.
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
I&apos;m trying to use the JavaScript API to authenticate with OAuth from a
GWT application. I&apos;ve got it working with both Google and Twitter&apos;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=&quot;http://groups.google.com/group/oauth/msg/ba2cb1bed6eecceb&quot;&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&apos;s interpretation of it, or that OAuth isn&apos;t as mature as it appears to be. I&apos;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=&quot;http://static.raibledesigns.com/downloads/gwt-oauth-1.0.zip&quot;&gt;download&lt;/a&gt; or &lt;a href=&quot;http://demo.raibledesigns.com/gwt-oauth&quot;&gt;view online&lt;/a&gt;. Please keep in mind the demo is likely to be flakey. If you&apos;re persistent and try enough times, it&apos;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.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt</guid>
    <title>Enhancing Evite.com with GWT and Grails</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/enhancing_evite_com_with_gwt</link>
        <pubDate>Mon, 15 Jun 2009 07:41:37 -0600</pubDate>
    <category>Java</category>
    <category>sofea</category>
    <category>grails</category>
    <category>memcached</category>
    <category>gxt</category>
    <category>java</category>
    <category>rest</category>
    <category>gwt</category>
    <category>evite</category>
            <description>&lt;a href=&quot;http://www.evite.com&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/evite-logo.png&quot; width=&quot;144&quot; height=&quot;93&quot; alt=&quot;Evite.com&quot; class=&quot;picture&quot; style=&quot;border: 1px solid silver&quot; /&gt;&lt;/a&gt;
On my &lt;a href=&quot;http://www.linkedin.com/in/mraible&quot;&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=&quot;quote&quot;&gt;
SOFEA Consultant, Stealth Mode Startup, Los Angeles, CA. December 2008 -- Present.
&lt;/p&gt;
&lt;p&gt;
OK, I lied. It&apos;s not a startup, it&apos;s a well-known company that helps you plan parties.
For the last 5+ months, my &lt;a href=&quot;http://raibledesigns.com/rd/entry/what_s_next&quot;&gt;UI team from LinkedIn&lt;/a&gt; has been working with &lt;a href=&quot;http://www.evite.com&quot;&gt;Evite.com&lt;/a&gt; to enhance portions of their site with a &lt;a href=&quot;http://raibledesigns.com/rd/entry/re_life_above_the_service&quot;&gt;SOFEA architecture&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;In January, we started &lt;a href=&quot;http://raibledesigns.com/rd/entry/choosing_an_ajax_framework&quot;&gt;evaluating Ajax Frameworks&lt;/a&gt; and came to the conclusion that &lt;a href=&quot;http://raibledesigns.com/rd/entry/ajax_framework_analysis_results&quot;&gt;GWT was right for us&lt;/a&gt;. After we chose the UI framework, other team members chose &lt;a href=&quot;http://grails.org&quot;&gt;Grails&lt;/a&gt; and &lt;a href=&quot;http://www.danga.com/memcached/&quot;&gt;memcached&lt;/a&gt; to develop scalable RESTful services. The architecture we implemented involves using GWT&apos;s &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/http/client/RequestBuilder.html&quot;&gt;RequestBuilder&lt;/a&gt; to talk to Grails&apos; 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&apos;s &lt;a href=&quot;http://www.evite.com/party/invitations&quot;&gt;Design Gallery&lt;/a&gt;. I personally worked on this feature and very much enjoyed becoming a GWT aficionado in the process. GWT&apos;s zero-turnaround feature made doing pure client-side work a lot of fun. It&apos;s definitely something I&apos;d like to continuing doing at my next gig. &lt;/p&gt;
&lt;p&gt;Everyone from Evite is very happy with what we&apos;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&apos;ve learned to scale the client by using out-of-the-box GWT components. We&apos;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&apos;ll be spending a few weeks at my family&apos;s cabin in Montana and then it&apos;s on to the next big thing. What&apos;s the next big thing? I&apos;m not sure yet, hence the reason for writing this. If you&apos;re looking to develop a GWT application, introduce a SOFEA architecture at your company, or simply adopt some open source frameworks, I&apos;d love to help out. &lt;a href=&quot;http://raibledesigns.com/contact.jsp&quot;&gt;Drop me a line&lt;/a&gt; and let&apos;s start a conversation. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/creating_a_facebook_style_autocomplete</guid>
    <title>Creating a Facebook-style Autocomplete with GWT</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/creating_a_facebook_style_autocomplete</link>
        <pubDate>Fri, 5 Jun 2009 07:05:10 -0600</pubDate>
    <category>Java</category>
    <category>autocomplete</category>
    <category>facebook</category>
    <category>linkedin</category>
    <category>jquery</category>
    <category>gwt-autocomplete</category>
    <category>gwt</category>
            <description>Have you used the &quot;To:&quot; widget on on Facebook or LinkedIn when composing a message? It&apos;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=&quot;text&quot;&amp;gt;), but wraps the contact name to allow you to easily delete it. Here&apos;s a screenshot of what Facebook&apos;s widget looks like.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;//farm3.static.flickr.com/2468/3595186177_5334fff971.jpg&quot; width=&quot;500&quot; height=&quot;233&quot; alt=&quot;Facebook Autocomplete&quot; /&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=&quot;
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/627687a4b607ce02&quot;&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&apos;s &lt;a href=&quot;http://loopj.com/2009/04/25/jquery-plugin-tokenizing-autocomplete-text-entry/&quot;&gt;Tokenizing Autocomplete jQuery Plugin&lt;/a&gt;. I used its &lt;a href=&quot;http://loopj.com/tokeninput/demo.html&quot;&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&apos;s &lt;a href=&quot;http://gwt.google.com/samples/Showcase/Showcase.html#CwSuggestBox&quot;&gt;SelectBox&lt;/a&gt; allows you to easily create an autocompleter. However, &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/issues/detail?id=3044&amp;amp;can=5&quot;&gt;it doesn&apos;t have support for multiple values&lt;/a&gt; (for example, a comma-delimited list). The good news is it&apos;s not difficult to add this functionality using &lt;a href=&quot;http://ljvjonok.blogspot.com/2008/10/gwt-suggestbox-how-to-make-multiple.html&quot;&gt;Viktor Zaprudnev&apos;s HowTo&lt;/a&gt;. Another feature you might want in a SelectBox is to populate it with POJOs. &lt;a href=&quot;http://eggsylife.co.uk/2008/08/25/gwt-suggestbox-backed-by-dto-model/&quot;&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=&quot;http://demo.raibledesigns.com/gwt-autocomplete&quot;&gt;view the demo&lt;/a&gt; or &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-autocomplete-1.0.zip&quot;&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=&quot;brush:xml&quot;&gt;
&amp;lt;ul class=&quot;token-input-list-facebook&quot;&amp;gt;
    &amp;lt;li class=&quot;token-input-input-token-facebook&quot;&amp;gt;
        &amp;lt;input type=&quot;text&quot; style=&quot;outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;&quot;/&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=&quot;brush:java&quot;&gt;
final BulletList list = new BulletList();
list.setStyleName(&quot;token-input-list-facebook&quot;);

final ListItem item = new ListItem();
item.setStyleName(&quot;token-input-input-token-facebook&quot;);

final TextBox itemBox = new TextBox();
itemBox.getElement().setAttribute(&quot;style&quot;, 
        &quot;outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;&quot;);

final SuggestBox box = new SuggestBox(getSuggestions(), itemBox);
box.getElement().setId(&quot;suggestion_box&quot;);

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 &quot;x&quot; to delete it. After adding a couple items, the HTML is as follows:&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;ul class=&quot;token-input-list-facebook&quot;&amp;gt;
    &amp;lt;li class=&quot;token-input-token-facebook&quot;&amp;gt;
        &amp;lt;p&amp;gt;What&apos;s New Scooby-Doo?&amp;lt;/p&amp;gt;
        &amp;lt;span class=&quot;token-input-delete-token-facebook&quot;&amp;gt;x&amp;lt;/span&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li class=&quot;token-input-token-facebook&quot;&amp;gt;
        &amp;lt;p&amp;gt;Fear Factor&amp;lt;/p&amp;gt;
        &amp;lt;span class=&quot;token-input-delete-token-facebook&quot;&amp;gt;x&amp;lt;/span&amp;gt;
     &amp;lt;/li&amp;gt;
     &amp;lt;li class=&quot;token-input-input-token-facebook&quot;&amp;gt;
         &amp;lt;input type=&quot;text&quot; style=&quot;outline-color: -moz-use-text-color; outline-style: none; outline-width: medium;&quot;/&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=&quot;brush:java&quot;&gt;
private void deselectItem(final TextBox itemBox, final BulletList list) {
    if (itemBox.getValue() != null &amp;&amp; !&quot;&quot;.equals(itemBox.getValue().trim())) {
        /** Change to the following structure:
         * &amp;lt;li class=&quot;token-input-token-facebook&quot;&amp;gt;
         * &amp;lt;p&amp;gt;What&apos;s New Scooby-Doo?&amp;lt;/p&amp;gt;
         * &amp;lt;span class=&quot;token-input-delete-token-facebook&quot;&amp;gt;x&amp;lt;/span&amp;gt;
         * &amp;lt;/li&amp;gt;
         */

        final ListItem displayItem = new ListItem();
        displayItem.setStyleName(&quot;token-input-token-facebook&quot;);
        Paragraph p = new Paragraph(itemBox.getValue());

        displayItem.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                displayItem.addStyleName(&quot;token-input-selected-token-facebook&quot;);
            }
        });

        Span span = new Span(&quot;x&quot;);
        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(&quot;&quot;);
        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=&quot;brush:java&quot;&gt;
box.addSelectionHandler(new SelectionHandler&amp;lt;SuggestOracle.Suggestion&amp;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&apos;s the handler that calls &lt;code&gt;deselectItem()&lt;/code&gt; and allows deleting with backspace:&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;&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(&quot;@&quot;))
                deselectItem(itemBox, list);
        }
        // handle backspace
        if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {
            if (&quot;&quot;.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&apos;m happy with the results, and grateful for the &lt;a href=&quot;http://loopj.com/tokeninput/token-input-facebook.css&quot;&gt;jQuery plugin&apos;s CSS&lt;/a&gt;. However, it still has one issue that I haven&apos;t been able to solve: I&apos;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&apos;m unable to give focus to the list item. Here&apos;s the code that highlights the item and you can see the commented-out code that doesn&apos;t work.
&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;&gt;
displayItem.addClickHandler(new ClickHandler() {
    public void onClick(ClickEvent clickEvent) {
        displayItem.addStyleName(&quot;token-input-selected-token-facebook&quot;);
    }
});

/** 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(&quot;token-input-selected-token-facebook&quot;);
    }
});
*/
&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&apos;d love to see this as a native widget in GWT. In the meantime, here&apos;s the &lt;a href=&quot;http://demo.raibledesigns.com/gwt-autocomplete&quot;&gt;GWT Facebook-style Autocomplete demo&lt;/a&gt; and &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-autocomplete-1.0.zip&quot;&gt;code&lt;/a&gt;.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/ajax_framework_analysis_results</guid>
    <title>Ajax Framework Analysis Results</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/ajax_framework_analysis_results</link>
        <pubDate>Thu, 23 Apr 2009 20:34:44 -0600</pubDate>
    <category>Java</category>
    <category>ajax</category>
    <category>gxt</category>
    <category>jquery</category>
    <category>smartgwt</category>
    <category>dojo</category>
    <category>yui</category>
    <category>java</category>
    <category>gwt</category>
    <category>extjs</category>
            <description>Way back in January, I wrote about how my colleagues and I were &lt;a href=&quot;http://raibledesigns.com/rd/entry/choosing_an_ajax_framework&quot;&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=&quot;http://spreadsheets.google.com/ccc?key=p2SLd279MTmShLQdCjfi0OQ&amp;hl=en&quot;&gt;view this matrix online&lt;/a&gt; or see below for a summary.
&lt;/p&gt;

&lt;iframe width=&apos;520&apos; height=&apos;500&apos; frameborder=&apos;0&apos; src=&apos;http://spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;output=html&amp;gid=0&amp;single=true&amp;widget=true&apos; style=&apos;margin: 0 auto&apos;&gt;&lt;/iframe&gt;

&lt;p style=&quot;text-align: left&quot;&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=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;//spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=1&amp;amp;output=image&quot; width=&quot;320&quot; alt=&quot;Number of Committers&quot;/&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;!--img src=&quot;//spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=2&amp;amp;output=image&quot; width=&quot;320&quot; alt=&quot;Mailing List Traffic&quot;/&gt;
&lt;br/&gt;&lt;br/--&gt;
&lt;img src=&quot;//spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=3&amp;amp;output=image&quot; width=&quot;320&quot; alt=&quot;Books on Amazon&quot;/&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=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;//spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=4&amp;amp;output=image&quot; width=&quot;320&quot; alt=&quot;Ranking with equal criteria weights&quot;/&gt;
&lt;/p&gt;
&lt;p&gt;Even after applying the weighted criteria, the evenness doesn&apos;t change a whole lot. &lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;//spreadsheets.google.com/pub?key=p2SLd279MTmShLQdCjfi0OQ&amp;amp;oid=5&amp;amp;output=image&quot; width=&quot;320&quot; alt=&quot;Ranking with weighted criteria&quot; /&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&apos;re developing with Dojo or YUI, chances are you&apos;re &lt;em&gt;dressing up&lt;/em&gt; existing HTML and possibly using &lt;a href=&quot;http://www.alistapart.com/articles/understandingprogressiveenhancement&quot;&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=&quot;http://www.jetbrains.com/idea/features/javascript_editor.html&quot;&gt;JavaScript Editor&lt;/a&gt; that provides many of the same features as its Java editor. &lt;a href=&quot;http://www.aptana.com/studio&quot;&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&apos;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=&quot;http://extjs.com/products/gxt&quot;&gt;GXT&lt;/a&gt;: a GWT version of Ext JS&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/smartgwt&quot;&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&apos;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 &quot;pop&quot;, 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&apos;s over a 50% reduction in size!&lt;a href=&quot;http://raibledesigns.com/rd/entry/ajax_framework_analysis_results#footnote-gxtmvc&quot;&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 &quot;pop&quot; with GWT, as long as you stick to the core - close-to-the-metal - components. For those applications that can afford an initial &quot;loading...&quot; state, I&apos;d definitely recommend looking at GXT and SmartGWT.
&lt;/p&gt;
&lt;p style=&quot;font-size: 90%&quot;&gt;&lt;a name=&quot;footnote-gxtmvc&quot;&gt;*&lt;/a&gt; To make refactoring easier, I copied &lt;a href=&quot;http://raibledesigns.com/rd/entry/gxt_s_mvc_framework&quot;&gt;GXT MVC&lt;/a&gt; into our source tree and modified all imports.&lt;/p&gt;
&lt;p&gt;















</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/optimizing_a_gwt_application_with</guid>
    <title>Optimizing a GWT Application with Multiple EntryPoints</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/optimizing_a_gwt_application_with</link>
        <pubDate>Wed, 25 Mar 2009 16:00:37 -0600</pubDate>
    <category>Java</category>
    <category>gzip</category>
    <category>webframeworks</category>
    <category>gwt-maven</category>
    <category>optimization</category>
    <category>gwt</category>
    <category>entrypoint</category>
    <category>maven</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&apos;s finished. One of the most important things I&apos;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&apos;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&apos;re going to &lt;em&gt;release early, release often&lt;/em&gt; with GWT, chances are you&apos;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&apos;t require &lt;a href=&quot;http://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt&quot;&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&apos;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&apos;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&apos;m not too worried about it. A possible workaround is to create different WAR names when a feature&apos;s profile is activated. I believe the true &quot;Maven way&quot; would be to make the &quot;kitchen sink&quot; 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?</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt</guid>
    <title>Modularizing GWT Applications with GWT-Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt</link>
        <pubDate>Mon, 23 Mar 2009 10:36:08 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>gwt-maven-plugin</category>
    <category>gwt-maven</category>
    <category>maven</category>
            <description>Last week, I spent some time modularizing the GWT application I&apos;m working on. By &lt;em&gt;modularizing&lt;/em&gt;, I mean splitting the code from one GWT module into a &quot;core&quot; and &quot;webapp&quot; module. The reason for doing this was so the &quot;core&quot; module could be used by another GWT application. Creating &lt;a href=&quot;http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&amp;s=google-web-toolkit-doc-1-5&amp;t=DevGuideModules&quot;&gt;GWT Modules&lt;/a&gt; is fairly straightforward, but it wasn&apos;t as intuitive as expected when using the &lt;a href=&quot;http://code.google.com/p/gwt-maven/&quot;&gt;gwt-maven-plugin&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;The hardest part of moving the code was figuring out how to run tests in the new &quot;core&quot; module. After getting it all working, it seems easy enough. Hopefully this post will make it easy for others. Here&apos;s the steps I&apos;d recommend:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Convert your GWT project into a multi-module project where you have a top-level pom.xml and two sub-modules (e.g. gwt-core and gwt-webapp).&lt;/li&gt;
&lt;li&gt;Do the normal single-to-multi-project Maven stuff like declaring the &amp;lt;parent&amp;gt; element in the modules and moving plugins/dependencies to the top-level pom.xml.&lt;/li&gt;
&lt;li&gt;Refactor your gwt-webapp project to push down all shared classes (and their tests) to gwt-core.&lt;/li&gt;
&lt;li&gt;In the gwt-core project, include *.xml and *.java in your JAR so GWT can extract/compile the source code when building gwt-webapp.
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;resources&amp;gt;
    &amp;lt;resource&amp;gt;
        &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
            &amp;lt;include&amp;gt;**/*.xml&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
    &amp;lt;/resource&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;gwt-core/src/main/java&lt;/code&gt;, create a &lt;code&gt;Core.gwt.xml&lt;/code&gt; that references the modules you&apos;d like to use in all your applications. For example:
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;module&gt;
    &amp;lt;inherits name=&quot;com.google.gwt.user.User&quot;/&gt;
    &amp;lt;inherits name=&quot;com.google.gwt.i18n.I18N&quot;/&gt;
    &amp;lt;inherits name=&quot;com.extjs.gxt.ui.GXT&quot;/&gt;
    &amp;lt;inherits name=&quot;pl.rmalinowski.gwt2swf.GWT2SWF&quot;/&gt;
&amp;lt;/module&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Now the tricky part begins, mostly because of how the gwt-maven plugin currently works. In &lt;code&gt;src/test/java&lt;/code&gt;, create a &lt;code&gt;NoOpEntryPoint.gwt.xml&lt;/code&gt; that inherits your Core module and defines an EntryPoint.
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;module&amp;gt;
    &amp;lt;inherits name=&quot;com.company.app.Core&quot;/&amp;gt;
    &amp;lt;entry-point class=&quot;com.company.app.NoOpEntryPoint&quot;/&amp;gt;
&amp;lt;/module&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;NoOpEntryPoint.java&lt;/code&gt; class in the same directory as &lt;code&gt;NoOpEntryPoint.gwt.xml&lt;/code&gt;.&lt;/pre&gt;
&lt;pre class=&quot;brush:java&quot;&gt;
public class NoOpEntryPoint implements EntryPoint {
    
    public void onModuleLoad() {
        // do nothing
    }
}
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;In any class that extends GWTTestCase (I usually create a parent class for all tests), reference the NoOpEntryPoint in the &lt;code&gt;getModuleName()&lt;/code&gt; method.
&lt;pre class=&quot;brush:java&quot;&gt;
    @Override
    public String getModuleName() {
        return &quot;com.company.app.NoOpEntryPoint&quot;;
    }
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Lastly, in the gwt-maven plugin&apos;s configuration (in gwt-core/pom.xml), reference the NoOpEntryPoint in &amp;lt;compileTargets&amp;gt;, a non-existent file in &amp;lt;runTarget&amp;gt; and only the &quot;test&quot; goal in the executions.
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;com.totsp.gwt&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-googlewebtoolkit2-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.0-beta26&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;compileTargets&amp;gt;
            &amp;lt;value&amp;gt;com.company.app.NoOpEntryPoint&amp;lt;/value&amp;gt;
        &amp;lt;/compileTargets&amp;gt;
        &amp;lt;runTarget&amp;gt;com.company.app.NoOpEntryPoint/doesntexist.html&amp;lt;/runTarget&amp;gt;
        &amp;lt;logLevel&amp;gt;INFO&amp;lt;/logLevel&amp;gt;
        &amp;lt;style&amp;gt;OBF&amp;lt;/style&amp;gt;
        &amp;lt;noServer&amp;gt;false&amp;lt;/noServer&amp;gt;
        &amp;lt;extraJvmArgs&amp;gt;-Xmx512m&amp;lt;/extraJvmArgs&amp;gt;
        &amp;lt;gwtVersion&amp;gt;${gwtVersion}&amp;lt;/gwtVersion&amp;gt;
        &amp;lt;testFilter&amp;gt;*GwtTestSuite.java&amp;lt;/testFilter&amp;gt;
        &amp;lt;testSkip&amp;gt;${skipTests}&amp;lt;/testSkip&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;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;/ol&gt;
&lt;p&gt;The results of modularizing your application are beneficial (shared code) and detrimental (you have to &lt;code&gt;mvn install&lt;/code&gt; gwt-core whenever you make changes in shared classes). If you know of a way to configure the gwt-maven plugin to read sources from both gwt-core and gwt-webapp in hosted mode, I&apos;d love to hear about it. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gxt_s_mvc_framework</guid>
    <title>GXT&apos;s MVC Framework</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gxt_s_mvc_framework</link>
        <pubDate>Fri, 13 Mar 2009 11:48:41 -0600</pubDate>
    <category>Java</category>
    <category>gxt</category>
    <category>gwt</category>
    <category>mvc</category>
    <category>navigation</category>
            <description>For the past couple of months, I&apos;ve been developing a GWT application using a mix of &lt;a href=&quot;http://gwt.google.com/samples/Showcase/Showcase.html&quot;&gt;plain ol&apos; GWT&lt;/a&gt; and &lt;a href=&quot;http://extjs.com/explorer/#overview&quot;&gt;GXT&lt;/a&gt; widgets. When I first started developing it, I didn&apos;t know how to best organize my code and separate the logic. The solution I came up with was to adopt some sort of MVC framework. Since I was already using GXT, I opted for GXT&apos;s &lt;a href=&quot;http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/mvc/package-summary.html&quot;&gt;lightweight MVC implementation&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;As mentioned in &lt;a href=&quot;http://raibledesigns.com/rd/entry/testing_gwt_applications&quot;&gt;Testing GWT Applications&lt;/a&gt;, GXT&apos;s MVC &lt;a href=&quot;http://extjs.net/forum/showthread.php?t=55064&quot;&gt;doesn&apos;t have much documentation&lt;/a&gt;. The best reference documentation seems to be &lt;a href=&quot;http://christianposta.com/blog/?p=6&quot;&gt;Christian&apos;s Getting started with Ext-GWT: The Mail reference application&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Page Transitioning with Dispatcher&lt;/strong&gt;&lt;br/&gt;
After working with GXT MVC for a couple months, I&apos;m still not sure I fully understand how navigation and event dispatching works. The biggest point of confusion for me is how to best use GXT&apos;s &lt;a href=&quot;http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/mvc/Dispatcher.html&quot;&gt;Dispatcher&lt;/a&gt; class.&lt;/p&gt;
&lt;p&gt;The problem with Dispatcher is it has a two methods that seem to do the same thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;forwardEvent&lt;/code&gt; (4 variations)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dispatch&lt;/code&gt; (3 variations)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to these methods in Dispatcher, there&apos;s two &lt;code&gt;fireEvent&lt;/code&gt; methods in GXT&apos;s &lt;a href=&quot;http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/mvc/View.html&quot;&gt;View&lt;/a&gt; class. According to my calculations, that means there&apos;s 9 different options for transitioning from one view to the next. Which one is best to use?
&lt;/p&gt;
&lt;p&gt;
From what I&apos;ve learned, I think it&apos;s best to use &lt;code&gt;fireEvent&lt;/code&gt; in Views and &lt;code&gt;forwardEvent&lt;/code&gt; in Controllers and other widgets. IMO, &lt;code&gt;dispatcher&lt;/code&gt; should never be used except in your HistoryListener&apos;s implementation &lt;code&gt;onHistoryChanged&lt;/code&gt; method.

The important thing to realize about this method is it &lt;em&gt;should&lt;/em&gt; only work if the View&apos;s Controller is registered for the event. 
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
  protected void fireEvent(AppEvent event) {
    Controller c = controller;
    while (c != null) {
      if (c.canHandle(event)) {
        c.handleEvent(event);
      }
      c = c.parent;
    }
  }
&lt;/pre&gt;
&lt;p&gt;However, &lt;code&gt;fireEvent&lt;/code&gt; seems to work even when the View&apos;s Controller isn&apos;t registered for that event. This is because &lt;code&gt;onHistoryChanged&lt;/code&gt; gets called in the EntryPoint. For experienced GXT MVC users, does this navigation handling mesh with your findings?&lt;/p&gt;
&lt;p&gt;The most important thing for navigation to work successfully is enabling History support. The next section talks about how to do this effectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enabling History Support&lt;/strong&gt;&lt;br/&gt;
To help explain things better, I created a simple GWT MVC Example application and used Maven to create an archetype with it. You can create a project from the archetype using the following command:
&lt;/p&gt;
&lt;pre&gt;
mvn archetype:create -DarchetypeGroupId=org.appfuse.archetypes \
-DarchetypeArtifactId=gwt-mvc -DarchetypeVersion=1.0-SNAPSHOT \
-DgroupId=com.mycompany.app -DartifactId=myproject \
-DremoteRepositories=http://oss.sonatype.org/content/repositories/appfuse-snapshots
&lt;/pre&gt;
&lt;p&gt;To enable history support in this application, I implemented &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/user/client/HistoryListener.html&quot;&gt;HistoryListener&lt;/a&gt; in my EntryPoint (Application.java) and added the following logic to initialize:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
// If the application starts with no history token, redirect to &apos;home&apos; state
String initToken = History.getToken();
if (initToken.length() == 0) {
    History.newItem(HistoryTokens.HOME);
}

// Add history listener
History.addHistoryListener(this);

// Now that we&apos;ve setup our listener, fire the initial history state.
History.fireCurrentHistoryState();
&lt;/pre&gt;
&lt;p&gt;In this example, HistoryTokens is a class that contains all the URLs of the &quot;views&quot; in the application.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class HistoryTokens {
    public static final String HOME = &quot;home&quot;;
    public static final String CALENDAR = &quot;calendar&quot;;
    public static final String NOTES = &quot;notes&quot;;
    public static final String SEARCH = &quot;search&quot;;
}
&lt;/pre&gt;
&lt;p&gt;In order to make URLs like http://localhost:8080/#calendar go to the calendar view, the following logic exists in the &lt;code&gt;onHistoryChanged&lt;/code&gt; method.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
        Dispatcher dispatcher = Dispatcher.get();

        if (historyToken != null) {
            if (historyToken.equals(HistoryTokens.HOME)) {
                dispatcher.dispatch(AppEvents.GoHome);
            } else if (historyToken.equals(HistoryTokens.CALENDAR)) {
                dispatcher.dispatch(AppEvents.Calendar);
            } else if (historyToken.equals(HistoryTokens.NOTES)) {
                dispatcher.dispatch(AppEvents.Notes);
            } else if (historyToken.equals(HistoryTokens.SEARCH)) {
                dispatcher.dispatch(AppEvents.Search);
            } else {
                GWT.log(&quot;HistoryToken &apos;&quot; + historyToken + &quot;&apos; not found!&quot;, null);
            }
        }
&lt;/pre&gt;
&lt;p&gt;Controllers are registered in the EntryPoint as follows:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
        final Dispatcher dispatcher = Dispatcher.get();
        dispatcher.addController(new CalendarController());
        dispatcher.addController(new HomeController());
        dispatcher.addController(new NotesController());
        dispatcher.addController(new SearchController());
&lt;/pre&gt;
&lt;p&gt;Controllers respond to events they&apos;re registered for. This is done in their constructor:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
    public CalendarController() {
        registerEventTypes(AppEvents.Calendar);
    }
&lt;/pre&gt;
&lt;p&gt;In order for navigation to work, you have to create links with history tokens&lt;sup&gt;1&lt;/sup&gt;. For example, here&apos;s a link from the &lt;code&gt;HomeView&lt;/code&gt; class:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
	Hyperlink notesLink = new Hyperlink(&quot;Notes&quot;, HistoryTokens.NOTES);
	notesLink.addClickListener(new ClickListener() {
	    public void onClick(Widget widget) {
	        Dispatcher.get().fireEvent(AppEvents.Notes);
	    }
	});
&lt;/pre&gt;
&lt;p&gt;You&apos;ll notice in this example, I&apos;m using Dispatcher&apos;s &lt;code&gt;fireEvent&lt;/code&gt; method. If I wanted to pass some data with your event, you&apos;ll need to use &lt;code&gt;forwardEvent&lt;/code&gt;. Here&apos;s an example from &lt;code&gt;CalendarView&lt;/code&gt;:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
    Button submit = new Button(&quot;Submit&quot;);

    submit.addSelectionListener(new SelectionListener&amp;lt;ButtonEvent&gt;() {
        public void componentSelected(ButtonEvent ce) {
            AppEvent&amp;lt;Date&gt; event = 
                new AppEvent&amp;lt;Date&gt;(AppEvents.GoHome, date.getValue(), HistoryTokens.HOME);
            Dispatcher.forwardEvent(event);
        }
    });
&lt;/pre&gt;
&lt;p&gt;
In this example, you could also use &lt;code&gt;Dispatcher.dispatcher()&lt;/code&gt;, but I believe this will cause the transition to happen twice because the &lt;code&gt;onHistoryChanged&lt;/code&gt; method gets called too. This doesn&apos;t matter for the most part, except when you start to use &lt;a href=&quot;http://extjs.com/deploy/gxtdocs/com/extjs/gxt/ui/client/mvc/DispatcherListener.html&quot;&gt;DispatcherListener&lt;/a&gt;s. 
&lt;/p&gt;
&lt;p&gt;Hopefully this article has helped you understand how GXT&apos;s MVC framework works. I&apos;m interested in learning how other GWT MVC frameworks work. If you&apos;ve used one, I&apos;d love to hear about your experience.&lt;/p&gt;
&lt;p class=&quot;smokey&quot;&gt;&lt;strong&gt;Friday Fun Test&lt;/strong&gt;&lt;br/&gt;
Here&apos;s a test for those interested in digging into the GXT MVC example. There&apos;s a bug in this application that prevents something from happening. I&apos;ll &lt;a href=&quot;http://www.givereal.com/&quot;&gt;buy a drink&lt;/a&gt; for the person that finds the bug and I&apos;ll buy two drinks for the person that comes up with a solution. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;&lt;/p&gt; 
&lt;p&gt;
&lt;em&gt;1. If you use the default constructor on Hyperlink and use &lt;code&gt;setText()&lt;/code&gt;, make sure to call &lt;code&gt;setTargetHistoryToken()&lt;/code&gt; too. If you don&apos;t, a blank history token will be used and # causes the browser to scroll to the top before a page transition happens.&lt;/em&gt;&lt;/p&gt;
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gwt_and_appfuse</guid>
    <title>GWT and AppFuse</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gwt_and_appfuse</link>
        <pubDate>Wed, 4 Mar 2009 22:50:26 -0700</pubDate>
    <category>Java</category>
    <category>rest</category>
    <category>appfuse</category>
    <category>gwt</category>
    <category>java</category>
            <description>Someone recently sent me the following e-mail asking about GWT integration in &lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
I see from your blog that you&apos;re spending some time with GWT at the moment. What&apos;s your plan, are you going to integrate GWT as another UI Option for AppFuse?
&lt;br/&gt;&lt;br/&gt;
The reason I&apos;m asking is that I actually checked out all of the AppFuse code from the svn repository yesterday, with the intention of starting off adding some GWT stuff in there. My intention was to start by getting a basic Maven archetype together for GWT as an AppFuse UI.
&lt;br/&gt;&lt;br/&gt;
However, if you&apos;re planning on doing this yourself in the near future, then there&apos;s no point in me starting doing it, I&apos;d have to learn how to write archetype&apos;s for a start (not that it looks too difficult) but you&apos;d obviously do it much quicker.
&lt;/p&gt;
&lt;p&gt;Being a good open-source developer, I moved the discussion to the developer mailing list and &lt;a href=&quot;http://www.nabble.com/Re%3A-GWT---Appfuse-to22184159s2369.html&quot;&gt;replied there&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;quote&quot; style=&quot;margin-left: 0; margin-bottom: 10px&quot;&gt;
&lt;p&gt;It&apos;s likely I&apos;ll create a version of AppFuse Light with GWT, but I 
doubt I&apos;ll do it in the near future. I hope to release AppFuse 2.1 
first (which will include &quot;light&quot; archetypes). I wouldn&apos;t get your 
hopes up in waiting for me to do the work. However, I&apos;d be happy to 
assist you in doing it. AppFuse Light is now modular and uses the 
AppFuse backend. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_light_converted_to_maven&quot;&gt;http://raibledesigns.com/rd/entry/appfuse_light_converted_to_maven&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Here&apos;s how I believe GWT should be integrated: 
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create an appfuse-ws archetype that serves up RESTful services 
(&lt;a href=&quot;http://issues.appfuse.org/browse/APF-897&quot;&gt;http://issues.appfuse.org/browse/APF-897&lt;/a&gt;). &lt;/li&gt;
&lt;li&gt; Create an appfuse-gwt archetype that consumes those services. This 
archetype would contain a proxy servlet that allows #1 to be on a 
separate host/port. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
In addition to #1, I hope to convert the Struts 2 and Spring MVC 
archetypes to use those frameworks&apos; REST support. 
&lt;/p&gt;
&lt;p style=&quot;margin-bottom: 0&quot;&gt;
For #2, we could use SmartGWT or GXT. SmartGWT might be better since 
Sanjiv is a committer on this project. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I know I&apos;ve been slacking on AppFuse development, but it &lt;em&gt;is&lt;/em&gt; ski season and running to work seems to drain my late-night coding ambitions. With that being said, I&apos;m committed to getting AppFuse 2.1 released by JavaOne (hopefully sooner). I figure it&apos;s a good week&apos;s worth of work and I&apos;ll probably have to do it late at night to find the time. That&apos;s OK though, I usually really start to enjoy it once I get into it.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gwttestsuite_makes_builds_faster_but</guid>
    <title>GWTTestSuite makes builds faster, but requires JUnit 4.1</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gwttestsuite_makes_builds_faster_but</link>
        <pubDate>Fri, 27 Feb 2009 11:58:12 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>junit</category>
    <category>gwt</category>
    <category>gwt-maven</category>
    <category>hudson</category>
    <category>gwttestsuite</category>
            <description>Earlier this week, I spent some time implementing &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/junit/tools/GWTTestSuite.html&quot;&gt;GWTTestSuite&lt;/a&gt; to speed up my project&apos;s build process. In Hudson, the project was taking around 15 minutes to build, locally it was only taking 5 minutes for &lt;em&gt;mvn test&lt;/em&gt;. 
In IDEA, I could run all the tests in under a minute. While 15 minutes isn&apos;t a long time for a build to execute, a co-worker expressed some concern:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Does Maven have to run GWT test and individual Java processes? (See target/gwtTest/*.sh) This arrangement and the overhead of JVM launches is another reason why builds take so long. As we add more GWT tests we are going to test that LinkedIn record for the slowest build ever.
&lt;/p&gt;
&lt;p&gt;
After this comment, I started looking into GWTTestSuite using &lt;a href=&quot;http://development.lombardi.com/?p=409&quot;&gt;Olivier Modica&apos;s blog entry&lt;/a&gt; as a guide. It was very easy to get things working in IDEA. However, when I&apos;d run &lt;em&gt;mvn test&lt;/em&gt;, I&apos;d get the following error:
&lt;/p&gt;
&lt;pre&gt;
Error: java.lang.ClassCastException
&lt;/pre&gt;
&lt;p&gt;No line numbers. No class information. Zilch. After comparing my project&apos;s pom.xml with the one from the default &lt;a href=&quot;http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/archetype.html&quot;&gt;gwt-maven archetype&lt;/a&gt;, I noticed the default used JUnit 4.1, while I had the latest-and-supposedly-greatest JUnit 4.4. Reverting to JUnit 4.1 fixed the problem. Now Hudson takes 3:15 to execute the build instead of 15 minutes.
&lt;/p&gt;
&lt;p&gt;
The reason for this blog post is this doesn&apos;t seem to be documented anywhere. Hopefully other developers will find this entry when googling for this issue.&lt;/p&gt;
&lt;p&gt;Related to making GWT faster, I also added the following line to my Application.gwt.xml file:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;set-property name=&quot;user.agent&quot; value=&quot;safari&quot; /&gt;
&lt;/pre&gt; 
&lt;p&gt;This dropped the &lt;code&gt;gwt:compile&lt;/code&gt; time from 1 minute to 25 seconds. As &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/FAQ_CompileOnePermutation&quot;&gt;explained in the documentation&lt;/a&gt;, you can use the &quot;user.agent&quot; setting to only generate one JS file for your app instead of 4. The strange thing about adding this setting was I pretty much forgot about it since everything seemed to work fine on both Safari and Firefox. When I started testing things in IE6, I started seeing a lot of JavaScript errors. After debugging for an hour or so, I realized this setting was there, removed it, and everything started working great in all browsers.
&lt;/p&gt;
&lt;p&gt;Now if I could just figure out how to use safari-only for development, but remove the line when building the WAR. Suggestions welcome.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/enhancing_your_gwt_application_with</guid>
    <title>Enhancing your GWT Application with the UrlRewriteFilter</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/enhancing_your_gwt_application_with</link>
        <pubDate>Mon, 23 Feb 2009 17:02:29 -0700</pubDate>
    <category>Java</category>
    <category>gwt-maven-plugin</category>
    <category>maven</category>
    <category>gwt</category>
    <category>urlrewritefilter</category>
            <description>Last week, I spent some time trying to &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-4/wiki/FAQ_ChangeLocationGWTApplicationFiles&quot;&gt;change the location of my cache/nocache HTML files&lt;/a&gt; in my GWT project. I started the project with the &lt;a href=&quot;http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/archetype.html&quot;&gt;gwt-maven-plugin&apos;s archetype&lt;/a&gt;. The &lt;a href=&quot;http://groups.google.com/group/gwt-maven/browse_thread/thread/a46f540ca823e3d3&quot;&gt;message&lt;/a&gt; I posted to the gwt-maven Google Group is below.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Rather than having my application&apos;s HTML file in
src/main/java/com/mycompany/Application.html, I&apos;d like to move it to
src/main/webapp/index.html. I tried copying the HTML and adding the
following to my index.html, but no dice:
&lt;br/&gt;&lt;br/&gt;
&amp;lt;meta name=&quot;gwt:module&quot; content=&quot;com.mycompany.Application&quot;/&gt;
&lt;br/&gt;&lt;br/&gt;
Is this possible with the gwt-maven-plugin? I&apos;d like to have my main
HTML and CSS at the root of my application.
&lt;/p&gt;
&lt;p&gt;
The good news is I figured out a solution using the &lt;a href=&quot;http://tuckey.org/urlrewrite/&quot;&gt;UrlRewriteFilter&lt;/a&gt; that 1) allows hosted mode to work as usual and 2) allows your app to be served up from the root URL (/ instead of /com.company.Module/Application.html). Here&apos;s the urlrewrite.xml that makes it all possible.&lt;/p&gt;
&lt;pre&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCENGINE urlrewrite PUBLIC &quot;-//tuckey.org//DTD UrlRewrite 3.0//EN&quot;
        &quot;http://tuckey.org/res/dtds/urlrewrite3.0.dtd&quot;&amp;gt;

&amp;lt;urlrewrite&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/com.mycompany.app.Application/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;/index.html&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/com.mycompany.app.Application/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;-- This last rule is necessary for JS and CSS files --&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/(.*)\.(.*)$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot;&amp;gt;/com.mycompany.app.Application/$1.$2&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/urlrewrite&amp;gt;
&lt;/pre&gt;
&lt;p&gt; 
If you&apos;re using the gwt-maven plugin, this file goes in &lt;code&gt;src/main/webapp/WEB-INF&lt;/code&gt;. In addition, you&apos;ll need to add the following to your web.xml.
&lt;/p&gt;
&lt;pre&gt;
    &amp;lt;filter&amp;gt;
        &amp;lt;filter-name&amp;gt;rewriteFilter&amp;lt;/filter-name&amp;gt;
        &amp;lt;filter-class&amp;gt;org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&amp;lt;/filter-class&amp;gt;
    &amp;lt;/filter&amp;gt;

    &amp;lt;filter-mapping&amp;gt;
        &amp;lt;filter-name&amp;gt;rewriteFilter&amp;lt;/filter-name&amp;gt;
        &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
    &amp;lt;/filter-mapping&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Finally, add the UrlRewriteFilter dependency in your pom.xml:
&lt;/p&gt;
&lt;pre&gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.tuckey&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;urlrewritefilter&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;3.1.0&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Please let me know if you have any questions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;http://www.nofluffjuststuff.com/conference/speaker/jeff_genender.html&quot;&gt;Jeff&lt;/a&gt; posted an &lt;a href=&quot;http://groups.google.com/group/gwt-maven/msg/28146682e6ab510d&quot;&gt;alternative configuration&lt;/a&gt; that allows you to eliminate the last rule in urlrewrite.xml, as well as use the beloved &lt;strong&gt;mvn jetty:run&lt;/strong&gt; command. To use cleaner WAR packaging and the Jetty plugin, add the following to your pom.xml:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;webappDirectory&amp;gt;
            ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
        &amp;lt;/webappDirectory&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;6.1.14&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;webAppConfig&amp;gt;
            &amp;lt;contextPath&amp;gt;/&amp;lt;/contextPath&amp;gt;
            &amp;lt;baseResource implementation=&quot;org.mortbay.resource.ResourceCollection&quot;&amp;gt;
                &amp;lt;resourcesAsCSV&amp;gt;
                    ${basedir}/src/main/webapp,
                    ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
                &amp;lt;/resourcesAsCSV&amp;gt;
            &amp;lt;/baseResource&amp;gt;
        &amp;lt;/webAppConfig&amp;gt;
        &amp;lt;scanIntervalSeconds&amp;gt;3&amp;lt;/scanIntervalSeconds&amp;gt;
        &amp;lt;scanTargets&amp;gt;
            &amp;lt;scanTarget&amp;gt;${basedir}/src/main/resources&amp;lt;/scanTarget&amp;gt;
            &amp;lt;scanTarget&amp;gt;${basedir}/src/main/webapp/WEB-INF&amp;lt;/scanTarget&amp;gt;
            &amp;lt;scanTarget&amp;gt;
                ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
            &amp;lt;/scanTarget&amp;gt;
        &amp;lt;/scanTargets&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Then you can trim your urlrewrite.xml down to:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;urlrewrite&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;/index.html&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/urlrewrite&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Of course, you could also change the welcome-file in your web.xml or use index.html and the &amp;lt;meta http-equiv=&quot;REFRESH&quot;&amp;gt; option. Personally, I have so much affection for the UrlRewriteFilter that I like having it in my project. I&apos;m sure I&apos;ll need it someday.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks Jeff!&lt;/em&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/testing_gwt_applications</guid>
    <title>Testing GWT Applications</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/testing_gwt_applications</link>
        <pubDate>Mon, 9 Feb 2009 15:27:36 -0700</pubDate>
    <category>Java</category>
    <category>codecoverage</category>
    <category>gwttestcase</category>
    <category>idea</category>
    <category>gwt</category>
    <category>extjs</category>
    <category>eclipse</category>
    <category>emma</category>
    <category>testing</category>
    <category>junit</category>
    <category>gxt</category>
            <description>Last week, I did some research on GWT, how to test it and code coverage options for tests that extend &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/junit/client/GWTTestCase.html&quot;&gt;GWTTestCase&lt;/a&gt;. The reason I did this is because I&apos;ve found that most of the GWT tests I write have to extend GWTTestCase and I&apos;d like to have code coverage reports. Read below for more information on my findings for testing GWT classes.
&lt;/p&gt;
&lt;p&gt;There are quite a few articles about testing GWT applications. Here are a few samples:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://blog.danielwellman.com/2008/11/test-first-gwt-article-in-november-2008-better-software-magazine.html&quot;&gt;Test-First GWT&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://robvanmaris.jteam.nl/2008/03/09/test-driven-development-for-gwt-ui-code/&quot;&gt;Test driven development for GWT UI code&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://robvanmaris.jteam.nl/2008/04/22/test-driven-development-for-gwt-ui-code-with-asynchronous-rpc/&quot;&gt;Test driven development for GWT UI code with asynchronous RPC&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://blog.springsource.com/2008/02/19/enabling-test-driven-development-in-gwt-client-code/&quot;&gt;Enabling Test Driven Development in GWT client code&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/10f8b38455e4102a&quot;&gt;JUnit tests for widgets&lt;/a&gt; - thread about which components to test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main gist of these articles is that you should structure your code to make the core functionality of your application testable without having to depend on GWTTestCase.&lt;/p&gt;

&lt;p&gt;All of them also advocate using an MVC or MVP (Model View Presenter) pattern. Currently, I&apos;m using &lt;a href=&quot;http://extjs.com/products/gxt/&quot;&gt;GXT&lt;/a&gt; and its MVC Framework. Unfortunately, GXT&apos;s MVC &lt;a href=&quot;http://extjs.net/forum/showthread.php?t=55064&quot;&gt;doesn&apos;t have much documentation&lt;/a&gt;. The good news is there is a &lt;a href=&quot;http://christianposta.com/blog/?p=6&quot;&gt;good article&lt;/a&gt; that explained enough that I was able to refactor my project to use it.&lt;/p&gt;

&lt;p&gt;The unfortunate side of this refactoring was I discovered that classes that extend GXT&apos;s MVC Framework &lt;a href=&quot;http://extjs.net/forum/showthread.php?t=58837&quot;&gt;have to be tested with GWTTestCase&lt;/a&gt;. The downside to extending GWTTestCase is there is it&apos;s difficult to create code coverage reports.&lt;/p&gt;

&lt;p&gt;GWT&apos;s &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/issues/detail?id=779&quot;&gt;issue 799&lt;/a&gt; has some patches that should make code coverage possible. I tried to implement code coverage with Eclipse and &lt;a href=&quot;http://www.eclemma.org/&quot;&gt;EclEmma&lt;/a&gt; using &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/source/browse/tools/redist/emma/README.txt&quot;&gt;this README&lt;/a&gt;, but failed. In the process, I discovered &lt;a href=&quot;http://tinyurl.com/al8rke&quot;&gt;an issue with Eclipse 3.4 and JUnit on OS X&lt;/a&gt;. Reverting to Eclipse 3.3 solved this problem, but I was &lt;a href=&quot;http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/c05d331decd2405e/94d738c3134efb30?#94d738c3134efb30&quot;&gt;still unable to make EclEmma work with GWT&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After failing with Eclipse, I tried to use the emma-maven-plugin. I was also unable to get this to work, with my findings documented in &lt;a href=&quot;http://groups.google.com/group/gwt-maven/browse_thread/thread/de736df5c99a58e6&quot;&gt;this thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, I did have some luck with getting IDEA&apos;s built-in code coverage feature working. However, after getting it to work once, it failed to work for the rest of the day and I haven&apos;t had success since.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Code Coverage and GWT&lt;/b&gt;&lt;br&gt;
Because of these issues with GWT 1.5 and code coverage, I think I&apos;ll wait until GWT 1.6 to worry about it. The good news is &lt;a href=&quot;http://www.ongwt.com/post/2009/02/07/GWT-16-M1&quot;&gt;1.6 M1 was released last Friday&lt;/a&gt;. If continuing to use GWTTestCase becomes an issue, I may write my own MVC Framework that doesn&apos;t use classes that call native JavaScript. Hopefully GXT MVC&apos;s framework will provide a good example.&lt;/p&gt;

&lt;p&gt;In addition to trying to get code coverage working, I used the internets to figure out how run GWT tests inside of Eclipse and IDEA. I don&apos;t remember the resources I used, but hopefully this up-to-date documentation will help others. The nice thing about using an IDE to run these tests is they typically execute much faster.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Running GWT Tests in Eclipse&lt;/strong&gt;&lt;br/&gt;
You should be able to run most of your GWT tests from within Eclipse using the following steps.
&lt;ol&gt;
&lt;li&gt;Right-click on a test that extends GWTTestCase and go to &lt;strong&gt;Run As&lt;/strong&gt; &gt; &lt;strong&gt;JUnit Test&lt;/strong&gt;. It&apos;s likely you will see the error message below.
&lt;pre style=&quot;color: red; margin-top: 5px&quot;&gt;Invalid launch configuration: -XstartOnFirstThread not specified.

On Mac OS X, GWT requires that the Java virtual machine be invoked with the
-XstartOnFirstThread VM argument.

Example:
  java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
To fix this error, go to &lt;strong&gt;Run&lt;/strong&gt; &gt; &lt;strong&gt;Open Run Dialog&lt;/strong&gt;. Click on the &lt;strong&gt;Arguments&lt;/strong&gt; tab and add the following values. The 2nd value is to increase the amount of memory available to the test and avoid an OOM error.
&lt;pre style=&quot;margin-top: 5px&quot;&gt;-XstartOnFirstThread -Xmx512M&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;When you re-run the test, you will probably see the following error:
&lt;pre style=&quot;margin-top: 5px&quot;&gt;com.google.gwt.junit.JUnitFatalLaunchException: The test class &apos;org.richresume.client.home.HomeControllerGwtTest&apos; 
was not found in module &apos;org.richresume.client.Application&apos;; no compilation unit for that type was seen
  at com.google.gwt.junit.JUnitShell.checkTestClassInCurrentModule(JUnitShell.java:193)
  at com.google.gwt.junit.JUnitShell.runTestImpl(JUnitShell.java:628)
  at com.google.gwt.junit.JUnitShell.runTest(JUnitShell.java:150)
  at com.google.gwt.junit.client.GWTTestCase.runTest(GWTTestCase.java:219)
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;To fix this, open the Run Dialog again, click on the &lt;strong&gt;Classpath&lt;/strong&gt; tab and click on &lt;strong&gt;User Entries&lt;/strong&gt;. Click on the &lt;strong&gt;Advanced&lt;/strong&gt; button and select &lt;strong&gt;Add Folders&lt;/strong&gt;. In the Folder Selection dialog, select your source and test directories (e.g. &lt;code&gt;src/main/java&lt;/code&gt; and &lt;code&gt;src/test/java&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Run the test again and you should see a green bar in your JUnit tab.&lt;/li&gt;
&lt;li&gt;To create a JUnit configuration that runs all tests, duplicate the previously mentioned run configuration. Then change the name to &quot;All Tests&quot; and select the 2nd radio button to run all tests in the project. &lt;/li&gt;
&lt;li&gt;Click Run to execute all the tests in the project.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Running GWT Tests in IDEA&lt;/strong&gt;&lt;br/&gt;
You should be able to run your GWT tests from within IDEA using the following steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Right-click on a test that extends GWTTestCase and go to &lt;strong&gt;Run &quot;&lt;em&gt;TestName&lt;/em&gt;GwtTes...&quot;&lt;/strong&gt;. It&apos;s likely you will see the error message below.
&lt;pre style=&quot;color: red; margin-top: 5px&quot;&gt;Invalid launch configuration: -XstartOnFirstThread not specified.

On Mac OS X, GWT requires that the Java virtual machine be invoked with the
-XstartOnFirstThread VM argument.

Example:
  java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell
&lt;/pre&gt;	
&lt;/li&gt;
&lt;li&gt;If you get a compiler error instead, you may need to add the GWT Facet to your project. To do this, right-click on your project&apos;s top-most folder in the left pane. Select &lt;strong&gt;Module Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Facets&lt;/strong&gt; and enable GWT for your module. &lt;/li&gt;
&lt;li&gt;To fix the &lt;code&gt;-XstartOnFirstThread&lt;/code&gt; issue, go to &lt;strong&gt;Run&lt;/strong&gt; &amp;gt; &lt;strong&gt;Edit Configurations&lt;/strong&gt;. Add the following values to the VM Arguments field. The 2nd value is to increase the amount of memory available to the test and avoid an OOM error. 
&lt;pre style=&quot;margin-top: 5px; margin-bottom: 5px&quot;&gt;-XstartOnFirstThread -Xmx512M&lt;/pre&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; If you still get a compiler error, see &lt;a href=&quot;http://www.jetbrains.net/devnet/docs/DOC-1114&quot;&gt;this page&lt;/a&gt; for a possible solution.&lt;/li&gt;
&lt;li&gt;Run the test again and you should see a green bar in your Run tab.&lt;/li&gt;
&lt;li&gt;To create a JUnit configuration that runs all tests, duplicate the previously mentioned run configuration. Then change the name to &quot;All Tests&quot; and change the Test configuration to search for tests in the whole project.&lt;/li&gt;
&lt;li&gt;Run the new configuration to execute all the tests in the project.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Testing GWT applications isn&apos;t as straightforward as writing JUnit tests, but I do believe it&apos;s getting better. If you have any additional tips and tricks, please let me know.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/choosing_an_ajax_framework</guid>
    <title>Choosing an Ajax Framework</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/choosing_an_ajax_framework</link>
        <pubDate>Thu, 8 Jan 2009 21:36:22 -0700</pubDate>
    <category>Java</category>
    <category>comparison</category>
    <category>extjs</category>
    <category>gwt</category>
    <category>webframeworks</category>
    <category>dojo</category>
    <category>ajax</category>
    <category>yui</category>
    <category>frameworks</category>
            <description>This past week, my colleagues and I have been researching Ajax Frameworks. We&apos;re working on a project that&apos;s following SOFEA-style architecture principles and we want the best framework for our needs. I&apos;m writing this post to see 1) if you, the community, agree with our selection process and 2) to learn about your experiences with the frameworks we&apos;re evaluating. Below is the process we&apos;re following to make our choice.
&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 (with demos) and recommendation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For #1, we chose  &lt;a href=&quot;http://extjs.com/products/extjs/&quot;&gt;Ext JS&lt;/a&gt;, &lt;a href=&quot;http://dojotoolkit.org/&quot;&gt;Dojo&lt;/a&gt;, &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt; and &lt;a href=&quot;http://code.google.com/intl/nl/webtoolkit/&quot;&gt;GWT&lt;/a&gt; because we feel these Ajax libraries offer the most UI widgets. We also considered Prototype/Scriptaculous, jQuery and MooTools, but decided against them because of their lack of UI widgets.&lt;/p&gt;
&lt;p&gt;For #2, we time-boxed ourselves to 3 days of development. In addition to basic functionality, we added several features (i.e. edit in place, drag and drop, calendar widgets, transitions, charts, grid) that might be used in the production application. We all were able to complete most of the functionality of the application. Of course, there&apos;s still some code cleanup as well as styling to make each app look good for the demo. The nice thing about doing this is we&apos;re able to look at each others code and see how the same thing is done in each framework. None of us are experts in any of the frameworks, so it&apos;s possible we could do things better. However, I think it&apos;s good we all started somewhat green because it shows what&apos;s possible for someone relatively new to the frameworks.&lt;/p&gt;
&lt;p&gt;For #3, we&apos;re creating a document with the following outline:&lt;/p&gt;
&lt;pre style=&quot;font-family: inherit; background: #CDFFCC; border: 1px solid #54FF52; width: 250px; padding-left: 20px&quot;&gt;
Introduction

Ajax Framework Candidates
(intro and explanation)

  Project Information
  (history)
  (license / cost)
  (number of committers)
  (support options)
  (mailing list traffic (nov/dec 2008))

Matrix and Notes

Conclusion
&lt;/pre&gt;
&lt;p&gt;For the Matrix referenced in the outline above, we&apos;re using a table with weights and ranks:&lt;/p&gt;

&lt;table class=&quot;comparison&quot; style=&quot;width: 500px&quot;&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;th&gt;Weight&lt;/th&gt;
        &lt;th&gt;Criteria&lt;/th&gt;
        &lt;th&gt;Dojo&lt;/th&gt;
        &lt;th&gt;YUI&lt;/th&gt;
        &lt;th&gt;GWT&lt;/th&gt;
        &lt;th style=&quot;white-space: nowrap&quot;&gt;Ext JS&lt;/th&gt;
        &lt;th&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;#&lt;/td&gt;
        &lt;td&gt;Important Criteria for Customer&lt;/td&gt;
        &lt;td&gt;0..1&lt;/td&gt;
        &lt;td&gt;0..1&lt;/td&gt;
        &lt;td&gt;0..1&lt;/td&gt;
        &lt;td&gt;0..1&lt;/td&gt;
        &lt;td&gt;Notes about rankings&lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Our strategy for filling in this matrix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Customer adjusts the weight for each criteria (removing/adding as needed) so all weights add up to 1.&lt;/li&gt;
&lt;li&gt;We rank each framework with 0, .5 or 1 where 0 = doesn&apos;t satisfy criteria, .5 = partially satisfies, 1 = satisfies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The list of criteria provided to us by our client is as follows (in no particular order).&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Quality of Documentation/Tutorials/Self Help&lt;/li&gt;
&lt;li&gt;Browser support (most important browsers/versions based on web stats)&lt;/li&gt;
&lt;li&gt;Testability (esp. Selenium compatibility)&lt;/li&gt;
&lt;li&gt;Licensing&lt;/li&gt;
&lt;li&gt;Project health/adoption&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Flexibility/extensibility&lt;/li&gt;
&lt;li&gt;Productivity (app dev, web dev)&lt;/li&gt;
&lt;li&gt;Richness of widget/component library&lt;/li&gt;
&lt;li&gt;Charting capability&lt;/li&gt;
&lt;li&gt;Ability to create new widgets&lt;/li&gt;
&lt;li&gt;Match to existing Java team skill-set&lt;/li&gt;
&lt;li&gt;Ease of deployment (on Ops, QA, Users)&lt;/li&gt;
&lt;li&gt;Degree of risk generally&lt;/li&gt;
&lt;li&gt;Ability to integrate with existing site (which includes Prototype)&lt;/li&gt;
&lt;li&gt;Easy to style with CSS&lt;/li&gt;
&lt;li&gt;Validation (esp. marking form elements invalid)&lt;/li&gt;
&lt;li&gt;Component Theme-ing/Decoration&lt;/li&gt;
&lt;li&gt;CDN Availability (i.e. Google&apos;s Ajax Libraries API or Ext CDN)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What do you think? How could this process be improved? Of course, if you have framework answers (0, .5 or 1) for our matrix, we&apos;d love to hear your opinions.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/restful_web_applications_with_subbu</guid>
    <title>RESTful Web Applications with Subbu Allamaraju</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/restful_web_applications_with_subbu</link>
        <pubDate>Fri, 24 Oct 2008 09:52:02 -0600</pubDate>
    <category>Java</category>
    <category>jsf</category>
    <category>webframeworks</category>
    <category>sofea</category>
    <category>appcelerator</category>
    <category>softwaresummit</category>
    <category>gwt</category>
    <category>java</category>
    <category>rest</category>
    <category>servlets</category>
            <description>Subbu works at Yahoo! developing standards, patterns and practices for HTTP web languages. In the past, he was a web service and Java developer. He was also a standards contributor at BEA and an author of books on Java EE. His current passion is HTTP and REST. Subbu confesses that he&apos;s not a web developer, has no interest in the internals of programming models used for web frameworks and he&apos;s only interested in the visible aspects of the architecture.
&lt;/p&gt;
&lt;p&gt;&quot;The Web is Mostly Restful&quot;&lt;/p&gt;
&lt;p&gt;Being RESTful in an abstract sense means:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Resources are named by URIs&lt;/li&gt;
&lt;li&gt;Resources have representations (Atom, HTML, JSON, XML)&lt;/li&gt;
&lt;li&gt;Resources contain contextual links to allow navigation of state&lt;/li&gt;
&lt;li&gt;There&apos;s a Uniform Interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In the web today, some resources and URIs are personalized, but most are not. Some depend on sessions, but most do not. The consequence of a personalized UI with a non-unique URI is you cannot rely on browser caching. &lt;/p&gt;
&lt;p&gt;The web is full of different representations (HTML, XML, JS, PDF, CSS, Flash). The problem with HTML is you can&apos;t tell links that you want a particular representation based of a link. The links are hard-coded to be a particular content-type. However, some media types on responses are ignored. This is often a problem with browsers and whether the user has plugins installed.&lt;/p&gt;
&lt;p&gt;The Uniform Interface for the web is HTML and primarily links and forms (GET and POST). There&apos;s still some misconceptions (e.g. POST is secure). However, it&apos;s not about security, it&apos;s about idempotency and safety. You need to make sure you only use POST when you&apos;re changing data. POSTs are not repeatable. GET URIs are not always refreshable, which is quite unfortunate. Users shouldn&apos;t have to fight the back button.&lt;/p&gt;
&lt;p&gt;Caching is a fundamental aspect of the web. Even in a personalized site, most of the content can be cached. The web is read-only for the most part. However, many enterprise web applications don&apos;t take advantage of caching. This is fine when there&apos;s not that many users, but it&apos;s bad when you want to scale to thousands of users. There&apos;s several frameworks that use cache-busting and prefer backend caching over HTTP caching. These frameworks are not using the web like they should.&lt;/p&gt;
&lt;p&gt;Backend caching (e.g. Memcached) uses a non-uniform interface and you need to explicitly program to it. Frontend/HTTP caching has a uniform interface that&apos;s pluggable. Backend caching is generally more expensive to develop and deploy. There are cases where data should be cached on the backend, but you shouldn&apos;t focus all on backend caching w/o doing some frontend caching.
&lt;/p&gt;
&lt;p&gt;With Ajax, you get more opportunities to be RESTful. XMLHttpRequest is another HTTP client that can be programmed to. It has full support for the uniform interface, which allows content negotiation, optimistic concurrency and caching. Cross-domain hacks can be done with &amp;lt;script&gt; and &amp;lt;iframe&gt; to tunnel requests over GET. The W3C has been working for the last two years on how to do cross-domain Ajax w/o using hacks. The problem with current cross-domain implementations is they often use GET for everything, which isn&apos;t very RESTful. Subbu recommends using a proxy on the same domain if you do need to talk to other domains. This will allow your Ajax code to remain RESTful.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web Frameworks&lt;/strong&gt;&lt;br/&gt;
Web development is hard because of all the moving pieces that exist. Because of this, many web frameworks have been created to solve the various problems. In 1997, there were servlets. They provided basic plumbing and closely reflected HTTP/1.1. Servlets provided a poor programming model, but it allowed a lot of frameworks to be built on top of it. We don&apos;t use servlets to write applications, only to write application frameworks. The second era came about in 2001 when Action-oriented frameworks became popular. In 2004, JSF and friends came to play. JSF is a component-based framework with known limitations (complex, slow, uses POST for almost everything, Ajax is difficult). These limitations have resulted in a number of third-party patches being developed to solve these issues.&lt;/p&gt;
&lt;p&gt;JSF was designed to use the request to create a component tree that maintains state. Unfortunately, the state is not something the developer has control over. It&apos;s not the state of the application, it&apos;s the state of the components. The client&apos;s knowledge of the state is mentioned with a cookie and the server keeps the state in the session. The problem with JSF is you don&apos;t have a choice of state in your application - you can&apos;t write stateless applications like you can with servlets.
&lt;/p&gt;
&lt;p&gt;JSF uses overloaded URIs for its resources. When you have one URI with multiple representations, there&apos;s no way to tell how a representation was chosen. JSF&apos;s compromise is to allow client-side state saving. However, they do this by putting hidden field in the form and requiring POST for navigation. 
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JSF vs. REST&lt;/strong&gt;&lt;br/&gt;
Basically, these two are at opposite extremes. JSF is focused heavily on a UI component model. The people that developed it misinterpreted how the web works and made some fundamental questionable choices. You can patch it, but you can not fix it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web 2.0 Frameworks&lt;/strong&gt;&lt;br/&gt;
GWT is a cross-compilation based framework. You write Java to generate JavaScript (b/c everyone hates writing JavaScript). It mashes client and server code into a single source. These layers communicate using GWT-RPC. Typical RPC concerns do not apply since code generation handles coupling and the client is downloaded from the same application. GWT-PRC does POSTs to the server and uses HTTP like a transport layer. To be fair, GWT does allow you to use a RequestBuilder to use the web like it should be used.
This class allows more control over HTTP requests, it supports GET and POST and it allows so-called RESTful layers (GWT-REST and GET-Restlet). GWT is focused heavily on ease-of-use, which is good. It&apos;s modeled after RPC and breaks the uniform interface and focuses on backend caching. Unlike JSF, GWT is fixable, but the community tends to use RPC instead of RequestBuilder.
&lt;/p&gt;
&lt;p&gt;SOFEA has a central promise of SOA. Business logic is a reusable service that changes less often. The presentation application calls those services and changes more often. The nice thing about this type of architecture is it allows a separation of concerns and loose coupling. However, it doesn&apos;t embrace REST like it should. Appcelerator is an implementation of SOFEA that has a Ruby on Rails-like usability. However, it uses a SOAP/HTTP style with messaging and POSTs to a single URI. Appcelerator is interesting, but it introduces a different style of coupling. It breaks URI opacity and client deals with POX instead of links. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br/&gt;
Don&apos;t fight the architecture of the web. Innovate and enhance instead of breaking. If nothing else, break judiciously. As developers, we should demand more from our frameworks and make sure they use the web and HTTP like it should be used.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/building_rich_applications_with_appcelerator</guid>
    <title>Building Rich Applications with Appcelerator</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/building_rich_applications_with_appcelerator</link>
        <pubDate>Wed, 22 Oct 2008 16:18:42 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>appcelerator</category>
    <category>softwaresummit</category>
    <category>webframeworks</category>
    <category>ria</category>
    <category>flex</category>
    <category>presentation</category>
            <description>This afternoon, I delivered my &lt;a href=&quot;http://softwaresummit.com/2008/speakers/raible.htm&quot;&gt;Building Rich Applications with Appcelerator&lt;/a&gt; talk for the 3rd time at Colorado Software Summit. When I first proposed this topic, I hadn&apos;t used &lt;a href=&quot;http://appcelerator.org&quot;&gt;Appcelerator&lt;/a&gt; and saw this as a good opportunity to learn more about it. I&apos;m glad I did.
&lt;/p&gt;
&lt;p&gt;
IMO, Appcelerator is a lot like Dojo in how it parses pages and turns HTML with special attributes into JavaScript widgets. I can&apos;t help but think a pre-compilation step would be nice to speed things up. I like Appcelerator&apos;s extensive &lt;a href=&quot;http://doc.appcelerator.org/reference/widget_reference/index.html&quot;&gt;Widget Library&lt;/a&gt;, and I especially like that they re-use many widgets rather than re-creating their own. Finally, I really dig the &quot;SOA in a browser&quot; approach where everything is a message and you can easily publish and subscribe to events - on the client and server. Below is my presentation, please let me know if you have any questions.
&lt;/p&gt;
&lt;div style=&quot;text-align: center&quot;&gt;&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=building-rich-applications-with-appcelerator-12002&amp;stripped_title=building-rich-applications-with-appcelerator&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;//static.slideshare.net/swf/ssplayer2.swf?doc=building-rich-applications-with-appcelerator-12002&amp;stripped_title=building-rich-applications-with-appcelerator&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style=&quot;font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;&quot;&gt;&lt;a style=&quot;text-decoration:underline;&quot; href=&quot;http://www.slideshare.net/mraible/building-rich-applications-with-appcelerator?type=powerpoint&quot; title=&quot;View Building Rich Applications with Appcelerator on SlideShare&quot;&gt;View on Slideshare&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/xebia_ria_framework_contest</guid>
    <title>Xebia RIA Framework Contest</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/xebia_ria_framework_contest</link>
        <pubDate>Tue, 7 Oct 2008 08:06:48 -0600</pubDate>
    <category>Java</category>
    <category>webframeworks</category>
    <category>silverlight</category>
    <category>echo3</category>
    <category>javafx</category>
    <category>flex</category>
    <category>ria</category>
    <category>gwt</category>
    <category>comparison</category>
            <description>Last year, I blogged about the &lt;a href=&quot;http://raibledesigns.com/rd/entry/xebia_web_framework_contest&quot;&gt;Xebia Web Framework Contest&lt;/a&gt; where Struts 2, GWT, Wicket and MyFaces (JSF) were all used to develop the same applications. It seems they&apos;ve done it again this year, &lt;a href=&quot;http://blog.xebia.fr/2008/10/03/ria-contest-flex-silverlight-gwt-echo3-javafx/&quot;&gt;comparing RIA frameworks&lt;/a&gt; (&lt;a href=&quot;http://translate.google.com/translate?u=http://blog.xebia.fr/2008/10/03/ria-contest-flex-silverlight-gwt-echo3-javafx/&amp;amp;hl=fr&amp;amp;ie=UTF-8&amp;amp;sl=fr&amp;amp;tl=en&quot;&gt;English translation&lt;/a&gt;) this time. 
&lt;/p&gt;
&lt;div style=&quot;margin-left: 0; margin-bottom: 10px&quot; class=&quot;quote&quot;&gt;
&lt;p&gt;Five teams were formed, five frameworks have been selected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flex 3 Flex 3&lt;/li&gt;
&lt;li&gt;Silverlight 2.0 beta 2 Silverlight 2.0 beta 2&lt;/li&gt;
&lt;li&gt;Google GWT 1.5 Google GWT 1.5&lt;/li&gt;
&lt;li&gt;Echo3 Echo3&lt;/li&gt;
&lt;li&gt;JavaFX Preview SDK JavaFX SDK Preview&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;margin-bottom: 0&quot;&gt;The number of teams is limited, the list of frameworks is also selected, and we have therefore necessarily set aside some frameworks that would have certainly had their place in the contest. Examples Ext JS, Yahoo! UI, Curl, XUL, ZK or OpenLaszlo. If you have experience on one of these frameworks, feel free to share in the comments on this article! [&lt;a href=&quot;http://blog.xebia.fr/2008/10/03/ria-contest-flex-silverlight-gwt-echo3-javafx/&quot;&gt;Read More &amp;raquo;&lt;/a&gt;]&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The winner? &lt;strong&gt;Flex&lt;/strong&gt; - which doesn&apos;t surprise me a whole lot.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
After this day, the Flex team, has clearly demarcated from its competitors. After two sprints of development and ownership, it could devote the third and final sprint to get rich quick and easy application, focusing only on the features and user experience. It is thanks to the wealth of high-level components, the wealth of documentation available and a maturity framework that the team has made the Flex application&apos;s most successful.
&lt;/p&gt;
&lt;p&gt;Good stuff - thanks Xebia!</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/presenting_web_frameworks_of_the</guid>
    <title>Presenting Web Frameworks of the Future Tomorrow in Denver</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/presenting_web_frameworks_of_the</link>
        <pubDate>Wed, 30 Jul 2008 21:56:17 -0600</pubDate>
    <category>Open Source</category>
    <category>opensource</category>
    <category>rest</category>
    <category>webframeworks</category>
    <category>grails</category>
    <category>rails</category>
    <category>oscon</category>
    <category>flex</category>
    <category>gwt</category>
            <description>Tomorrow (Thursday) night, I&apos;ll be doing an encore presentation of my &lt;a href=&quot;http://raibledesigns.com/rd/entry/oscon_2008_web_frameworks_of&quot;&gt;Web Frameworks of the Future&lt;/a&gt; at &lt;a href=&quot;http://groups.google.com/group/derailed&quot;&gt;DeRailed&lt;/a&gt;. If you&apos;re in Denver and would like to hear me ramble while drinking a beer, join us at &lt;a href=&quot;http://www.forestroom5.com/&quot;&gt;Forestroom 5&lt;/a&gt; at 6:30.&lt;/p&gt;
&lt;p&gt;After the &lt;a href=&quot;http://raibledesigns.com/rd/entry/the_oscon_aftermath&quot;&gt;last few days&lt;/a&gt;, I&apos;m happy to report I should be in good enough condition to pull this off. If you&apos;re curious to learn more about my experience at OSCON and this presentation, please see &lt;a href=&quot;http://blog.linkedin.com/blog/2008/07/oscon-2008-and.html&quot;&gt;my writeup on the LinkedIn Blog&lt;/a&gt;.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/oscon_2008_web_frameworks_of</guid>
    <title>[OSCON 2008] Web Frameworks of the Future: Flex, GWT, Grails and Rails</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/oscon_2008_web_frameworks_of</link>
        <pubDate>Wed, 23 Jul 2008 16:25:23 -0600</pubDate>
    <category>Open Source</category>
    <category>rails</category>
    <category>oscon</category>
    <category>rest</category>
    <category>gwt</category>
    <category>oscon08</category>
    <category>flex</category>
    <category>grails</category>
    <category>opensource</category>
    <category>webframeworks</category>
            <description>Below is the presentation I&apos;m &lt;a href=&quot;http://en.oreilly.com/oscon2008/public/schedule/speaker/6444&quot;&gt;delivering at OSCON&lt;/a&gt; today. Unfortunately, I had to remove slides on GWT and Flex to fit w/in the 45 minute time limit. I hope to expand this presentation in the future, as well as continue to develop the side project I&apos;m working on using these technologies.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=webframeworksofthefutureflexgwtrailsandgrails-1216842992390310-9&quot;/&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;//static.slideshare.net/swf/ssplayer2.swf?doc=webframeworksofthefutureflexgwtrailsandgrails-1216842992390310-9&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;div style=&quot;font-size: .9em; text-align: center&quot;&gt;
&lt;a href=&quot;http://www.slideshare.net/mraible/web-frameworks-of-the-future-flex-gwt-grail-and-rails-525747?src=embed&quot; title=&quot;View Web Frameworks of the Future: Flex, GWT, Grail, and Rails on SlideShare&quot;&gt;view on slideshare&lt;/a&gt; | 
&lt;a href=&quot;http://www.slideshare.net/mraible/web-frameworks-of-the-future-flex-gwt-grail-and-rails-525747/download&quot;&gt;download&lt;/a&gt;&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gwt_and_rest</guid>
    <title>GWT and REST</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gwt_and_rest</link>
        <pubDate>Mon, 21 Jul 2008 10:31:58 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>rest</category>
            <description>I&apos;ve posted two message to the &lt;a href=&quot;http://groups.google.com/group/Google-Web-Toolkit&quot;&gt;GWT Google Group&lt;/a&gt; in the last couple of days. However, &lt;a href=&quot;http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/0dbb7f08915229e5&quot;&gt;new member messages are moderated&lt;/a&gt; and neither has shown up yet. I&apos;m reposting my questions here in hopes of getting some answers.
&lt;/p&gt;
&lt;div class=&quot;smokey&quot; style=&quot;margin-bottom: 10px&quot;&gt;
&lt;p&gt;
Is there a way to easily use a REST backend with GWT? I tried &lt;a href=&quot;http://code.google.com/p/gwt-rest/&quot;&gt;GWT-REST&lt;/a&gt;. It works, but it seems to be centered towards Rails (I&apos;m using Grails) and it suffers from the &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/FAQ_SOP&quot;&gt;SOP issue&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://www.gwtsite.com/how-to-access-web-services-with-gwt/&quot;&gt;JSONRequest&lt;/a&gt; looks promising for cross-domain support, but I can&apos;t
get it to work either. The provided examples work, but not my simple
hello world that returns:
&lt;/p&gt;
&lt;pre&gt;
{&quot;response&quot;:&quot;Hello World!&quot;}
&lt;/pre&gt;
&lt;p&gt;
Also, the example implementation only has GET support, not PUT, DELETE
or POST. I can post my REST backend on the public internet if anyone
is interested in seeing the issues I&apos;m having.
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Thanks in advance for any advice.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/re_what_s_a_good</guid>
    <title>RE: What&apos;s a good RIA to develop in 20 hours?</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/re_what_s_a_good</link>
        <pubDate>Wed, 11 Jun 2008 11:02:23 -0600</pubDate>
    <category>Java</category>
    <category>webframeworks</category>
    <category>grails</category>
    <category>flex</category>
    <category>rails</category>
    <category>gwt</category>
            <description>Thanks to everyone who commented on my &lt;a href=&quot;http://raibledesigns.com/rd/entry/what_s_a_good_ria&quot;&gt;previous post&lt;/a&gt; and offered recommendations for  RIAs to develop in 20 hours or less. In order to narrow down my choices, I&apos;ve created a survey on &lt;a href=&quot;http://www.surveymonkey.com/&quot;&gt;SurveyMonkey.com&lt;/a&gt;. Here&apos;s a list of the application ideas I received from comments and e-mails:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lightweight CMS&lt;/li&gt;
&lt;li&gt;MP3 Player&lt;/li&gt;
&lt;li&gt;Resume Editor/Publisher&lt;/li&gt;
&lt;li&gt;Meal/Calorie Tracker&lt;/li&gt;
&lt;li&gt;Contact Management&lt;/li&gt;
&lt;li&gt;Planning Application&lt;/li&gt;
&lt;li&gt;Timesheet Application&lt;/li&gt;
&lt;li&gt;DB/SQL Client&lt;/li&gt;
&lt;li&gt;Status Updater/Aggregator (LinkedIn, Twitter and Facebook)&lt;/li&gt;
&lt;li&gt;Online File Explorer (browser-based FTP interface)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I like #3 (Resume) and #9 (Status) because I may be able to tie those into LinkedIn&apos;s RESTful API.&lt;/p&gt;
&lt;p style=&quot;padding-left: 10px&quot;&gt;&lt;a href=&quot;http://www.surveymonkey.com/s.aspx?sm=n5VGjN3BjL_2f_2bUks_2fY9mR6Q_3d_3d&quot;&gt;Click here to vote for the application you&apos;d like me to develop &amp;raquo; &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Voting ends at noon on Friday (Mountain Time).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; My co-workers had a good suggestion at lunch today: &lt;a href=&quot;http://www.pitchersacrossamerica.com&quot;&gt;pitchersacrossamerica.com&lt;/a&gt;. It seems it&apos;s kinda difficult to find bars that serve pitchers these days (at least in Denver). Create an app that allows people to enter in bars and restaurants that serve pitchers and show them on a map. Seems simple and fun. If enough people like the idea, I&apos;ll restart the survey with this as an option. In the meantime, the current (Wednesday night) numbers are &lt;a href=&quot;http://farm4.static.flickr.com/3169/2572286046_faf8675f72_o.png&quot; title=&quot;Wednesday Evening Survey Results&quot; rel=&quot;lightbox&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; &lt;a href=&quot;http://farm4.static.flickr.com/3262/2573930525_5e006701f4_o.png&quot; rel=&quot;lightbox&quot;&gt;Here&apos;s the results&lt;/a&gt; as of Thursday night. Only 15.5 more hours to vote!
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 3:&lt;/strong&gt; &lt;a href=&quot;http://farm4.static.flickr.com/3054/2576516036_0cd006f275_o.png&quot; rel=&quot;lightbox&quot; title=&quot;Final Results&quot;&gt;Final Results&lt;/a&gt;. Thanks to everyone who voted! I&apos;m traveling a lot next week (Mountain View followed by Boston), but I&apos;ll try to write an entry on next steps.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/what_s_a_good_ria</guid>
    <title>What&apos;s a good RIA to develop in 20 hours?</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/what_s_a_good_ria</link>
        <pubDate>Mon, 9 Jun 2008 21:56:30 -0600</pubDate>
    <category>Java</category>
    <category>grails</category>
    <category>rails</category>
    <category>gwt</category>
    <category>flex</category>
            <description>&lt;a href=&quot;http://en.oreilly.com/oscon2008/&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/oscon-logo-2008.gif&quot; width=&quot;96&quot; height=&quot;111&quot; alt=&quot;OSCON 2008&quot; class=&quot;picture&quot; style=&quot;border: 0&quot; /&gt;&lt;/a&gt;
In less than two months, I&apos;m making my annual trek to Portland, Oregon to &lt;a href=&quot;http://raibledesigns.com/rd/entry/proposal_accepted_for_oscon_2008&quot;&gt;speak&lt;/a&gt; at &lt;a href=&quot;http://en.oreilly.com/oscon2008/public/content/home&quot;&gt;OSCON&lt;/a&gt;. To prepare for my talk, I&apos;d like to develop the same application with two different combinations: Flex + Rails and GWT + Grails.
&lt;/p&gt;
&lt;p&gt;As luck would have it, I&apos;m having a hard time coming up with a good application to write. I&apos;d like to time-box it so I only spend 10 hours on the backend (for each) and 10 hours on the front-end, for a total of 40 hours for both applications. 
&lt;/p&gt;
&lt;p&gt;
Can you think of any good applications that would warrant a rich front-end and wouldn&apos;t take too long to create? I&apos;d like to put both applications in production and generate enough traffic to be faced with scalability issues.&lt;/p&gt;
&lt;p&gt;Over the next several weeks, I hope to start creating the applications and blog about what I&apos;ve learned along the way. At some point, I hope to post an outline and a rough draft. With your help, I believe this can be an excellent presentation. If the presentation and applications are as good as I hope they&apos;ll be, it&apos;s likely I&apos;ll open source them for everyone to use.&lt;/p&gt;
&lt;p&gt;Thanks in advance for any advice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Thanks for all the great feedback. I&apos;ve posted a &lt;a href=&quot;http://raibledesigns.com/rd/entry/re_what_s_a_good&quot;&gt;survey&lt;/a&gt; to narrow the choices.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/proposal_accepted_for_oscon_2008</guid>
    <title>Proposal accepted for OSCON 2008</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/proposal_accepted_for_oscon_2008</link>
        <pubDate>Mon, 17 Mar 2008 19:21:10 -0600</pubDate>
    <category>Open Source</category>
    <category>grails</category>
    <category>portland</category>
    <category>conference</category>
    <category>travel</category>
    <category>gwt</category>
    <category>oscon</category>
    <category>rails</category>
    <category>flex</category>
            <description>&lt;a href=&quot;http://en.oreilly.com/oscon2008/&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/oscon-logo-2008.gif&quot; width=&quot;96&quot; height=&quot;111&quot; alt=&quot;OSCON 2008&quot; class=&quot;picture&quot; style=&quot;border: 0&quot; /&gt;&lt;/a&gt;
From an e-mail I received earlier this afternoon:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
We are pleased to accept the following proposal for &lt;a href=&quot;http://en.oreilly.com/oscon2008/&quot;&gt;OSCON 2008&lt;/a&gt;.
&lt;br/&gt;&lt;br/&gt;
* Web Frameworks of the Future: Flex, GWT, Grails and Rails
&lt;br/&gt;&lt;br/&gt;
It has been scheduled for 16:30 on 23 Jul 2008.
&lt;/p&gt;
&lt;p&gt;My Abstract:&lt;/p&gt;
&lt;p class=&quot;smokey&quot;&gt;
What if the choices in web framework was reduced to 4? If RIA are the way of the future, it&apos;s possible that these 4 frameworks are the best choices for this development paradigm. This session will explore these frameworks, as well as entertain many other&apos;s opinions on the future of web development.
&lt;br/&gt;&lt;br/&gt;
RESTful backends are easy to create with both Rails and Grails. Ajax frontends are simple to create and maintain with GWT. Flex gives you flash and a pretty UI. If you&apos;re an HTML developer, Rails allows you to quickly develop MVC applications. If you&apos;re a Java Developer, GWT + Grails might be a match made in heaven. This session is designed to help you learn more about each framework and decide which combination is best for your project.
&lt;/p&gt;
&lt;p&gt;I&apos;m really looking forward to learning about GWT and Flex in the coming months. If you have any experience (or opinions) about the abstract above, I&apos;d love to hear it. The louder the better.&lt;/p&gt;
&lt;p&gt;For those who haven&apos;t been, OSCON is one of those truly special conferences. Possible reasons:
&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;It&apos;s only an hour from my parent&apos;s house
&lt;/li&gt;
&lt;li&gt;It&apos;s &lt;a href=&quot;http://raibledesigns.com/rd/entry/oscon_a_beautiful_time_of&quot;&gt;a beautiful time of year in Portland&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;It&apos;s always the same weekend as the &lt;a href=&quot;http://www.oregonbrewfest.com/&quot;&gt;Oregon Brewers Festival&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;It&apos;s a kickass conference with the greatest diversity of Open Source Committers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;m going for all 4 reasons and even made a reservation to stay at &lt;a href=&quot;http://www.kennedyschool.com/index.php?loc=57&amp;amp;category=Location%20Homepage&quot;&gt;The Kennedy School&lt;/a&gt;. Should be a fun show.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gwt_presentation_with_bob_vawter</guid>
    <title>GWT Presentation with Bob Vawter</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gwt_presentation_with_bob_vawter</link>
        <pubDate>Tue, 15 Jan 2008 21:26:09 -0700</pubDate>
    <category>Java</category>
    <category>java</category>
    <category>gwt</category>
            <description>Tonight I&apos;m in Mountain View attending the &lt;a href=&quot;http://sv-gtug.org/event/2008-01-15.html&quot;&gt;inaugural meeting&lt;/a&gt; for the new Silicon Valley Google Technology User Group (&lt;a href=&quot;http://sv-gtug.org&quot;&gt;SV-GTUG&lt;/a&gt;). The good news about this meeting is Bob plans to discuss some of the new features in the GWT 1.5
release. Although it is not available yet, it sounds like they are putting the finishing touches on the 1.5 release and that it will be available soon.&lt;/p&gt;
&lt;p&gt;The first ting I&apos;ve learned is that GWT is actually pronounced &quot;gwit&quot;. Bob is a member of the GWT team and he&apos;s the only one that&apos;s not based out of Atlanta. GWT has a very Swing-like programming model. It has widgets, panels and windows and operates very much like a traditional UI programming API. To create an application, you create a class that implements &lt;a class=&quot;external&quot; href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.4/com/google/gwt/core/client/EntryPoint.html&quot;&gt;EntryPoint&lt;/a&gt;&lt;img class=&quot;outlink&quot; src=&quot;http://raibledesigns.com/wiki/images/out.png&quot; alt=&quot;&quot; /&gt;. Below is an example Hello World application.
&lt;p&gt;

&lt;!-- ======================================================== --&gt;
&lt;!-- = Java Sourcecode to HTML automatically converted code = --&gt;
&lt;!-- =   Java2Html Converter 5.0 [2006-02-26] by Markus Gebhard  markus@jave.de   = --&gt;
&lt;!-- =     Further information: http://www.java2html.de     = --&gt;
&lt;div align=&quot;left&quot; class=&quot;java&quot;&gt;
&lt;table border=&quot;0&quot; cellpadding=&quot;3&quot; cellspacing=&quot;0&quot; bgcolor=&quot;#ffffff&quot;&gt;
   &lt;tr&gt;
  &lt;!-- start source code --&gt;
   &lt;td nowrap=&quot;nowrap&quot; valign=&quot;top&quot; align=&quot;left&quot;&gt;
    &lt;code&gt;
&lt;font color=&quot;#3f5fbf&quot;&gt;/**&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#3f5fbf&quot;&gt;*&amp;nbsp;HelloWorld&amp;nbsp;application.&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#3f5fbf&quot;&gt;*/&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;public&amp;nbsp;class&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;Hello&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;implements&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;EntryPoint&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;{&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;public&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;onModuleLoad&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;()&amp;nbsp;{&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;Button&amp;nbsp;b&amp;nbsp;=&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;new&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;Button&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;(&lt;/font&gt;&lt;font color=&quot;#2a00ff&quot;&gt;&amp;#34;Click&amp;nbsp;me&amp;#34;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;,&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;new&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;ClickListener&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;()&amp;nbsp;{&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;public&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#7f0055&quot;&gt;&lt;b&gt;void&amp;nbsp;&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;onClick&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;(&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;Widget&amp;nbsp;sender&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;)&amp;nbsp;{&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;Window.alert&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;(&lt;/font&gt;&lt;font color=&quot;#2a00ff&quot;&gt;&amp;#34;Hello,&amp;nbsp;AJAX&amp;#34;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;)&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;})&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;RootPanel.get&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;()&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;.add&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;(&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;b&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;)&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;;&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#000000&quot;&gt;}&lt;/font&gt;&lt;br /&gt;
&lt;font color=&quot;#ffffff&quot;&gt;&lt;/font&gt;&lt;font color=&quot;#ffffff&quot;&gt;
&lt;/font&gt;&lt;/code&gt;
    
   &lt;/td&gt;
  &lt;!-- end source code --&gt;
   &lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;!-- =       END of automatically generated HTML code       = --&gt;
&lt;!-- ======================================================== --&gt;


&lt;/p&gt;
&lt;p&gt;One of the really nice things about GWT is that you can easily debug your application in your favorite Java IDE. GWT doesn&apos;t prevent you from writing JavaScript - you can insert native JavaScript into your code using a special /*-{ script here }-*/.
&lt;/p&gt;
&lt;p&gt;When you compile a GWT application, you get a whole bunch of stuff. When trying to develop cross-browser JavaScript code, you often end up with &quot;if soup&quot; to handle the different browsers. GWT does the same thing, but it creates different versions of the application for the different browsers. The naming of these files is an MD5 hash that&apos;s bootstrapped by a simple JS file. GWT files are all static and the file sizes are ~40KB/each for the Hello World application.
&lt;/p&gt;
&lt;p&gt;If you have to write fewer than 100 lines of code, it&apos;s likely that GWT will be overkill - you can do it with JavaScript easier. Once you get more lines of code and larger teams, Java&apos;s tools do all the heavy lifting. Yes, you can create large applications with large teams with scripting languages, but Java is the clear winner when you have large teams of developers working on projects. 
&lt;/p&gt;
&lt;p&gt;GWT provides a RemoteService for client code and a RemoteServiceServlet for server-side code that you can use to implement RPC calls. For more information, see the &lt;a class=&quot;external&quot; href=&quot;http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html&quot;&gt;Remote Procedure Calls&lt;/a&gt;&lt;img class=&quot;outlink&quot; src=&quot;http://raibledesigns.com/wiki/images/out.png&quot; alt=&quot;&quot; /&gt; documentation.
&lt;/p&gt;
&lt;p&gt;&lt;p class=&quot;smokey&quot;&gt;At this point, we&apos;re 45 minutes into the presentation and it&apos;s pretty disappointing. This is likely because there&apos;s no presentation and Bob doesn&apos;t seem to have any sort of agenda. I think this type of presentation would work well if folks had experience with GWT and were asking lots of questions. However, it seems that most folks haven&apos;t used GWT - so the questions (and his resulting answers) aren&apos;t very meaty.&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;One attendee asked about making GWT applications SEO-able. Bob&apos;s suggested solution is to continue to use Servlet or JSPs to render the page, but then use GWT to for the user interaction that needs to happen within the page. The RootPanel class has a get(String id) method that can be used to put the GWT application into a particular div or other placeholder.
&lt;/p&gt;
&lt;p&gt;Google Base and Google Checkout are currently using GWT. There&apos;s also a lot of Google internal development that uses GWT. Apparently, there&apos;s quite a few applications built with GWT that haven&apos;t launched yet.
&lt;/p&gt;
&lt;p&gt;Has anyone used the &lt;a class=&quot;external&quot; href=&quot;http://gwtforge.com/&quot;&gt;Maven Gwt Plugin&lt;/a&gt;&lt;img class=&quot;outlink&quot; src=&quot;http://raibledesigns.com/wiki/images/out.png&quot; alt=&quot;&quot; /&gt;? It sounds like it might be pretty nice as it contains the GWT compiler with no OS-dependent Google tooling.
&lt;/p&gt;
&lt;p&gt;The main new feature in GWT 1.5 is Java 5 support. There&apos;s also a &lt;a class=&quot;external&quot; href=&quot;http://code.google.com/p/google-web-toolkit-incubator/&quot;&gt;GWT Incubator&lt;/a&gt;&lt;img class=&quot;outlink&quot; src=&quot;http://raibledesigns.com/wiki/images/out.png&quot; alt=&quot;&quot; /&gt; that&apos;s used to host GWT features that may go into GWT&apos;s core. You can &lt;a class=&quot;external&quot; href=&quot;http://google-web-toolkit-incubator.googlecode.com/svn/trunk/demo/&quot;&gt;view the demos online&lt;/a&gt;&lt;img class=&quot;outlink&quot; src=&quot;http://raibledesigns.com/wiki/images/out.png&quot; alt=&quot;&quot; /&gt;.
&lt;/p&gt;
&lt;p&gt;GWT&apos;s mission statement:
&lt;/p&gt;
&lt;p&gt;&lt;p class=&quot;quote&quot;&gt;
GWT&apos;s mission is to radically improve the web experience for users by enabling developers to use existing Java tools to build no-compromise AJAX for any modern browser.
&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;GWT&apos;s competition according to Bob - Visual Studio.&lt;/p&gt;
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/action_packed_week_in_california</guid>
    <title>Action Packed Week in California</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/action_packed_week_in_california</link>
        <pubDate>Tue, 15 Jan 2008 08:33:13 -0700</pubDate>
    <category>General</category>
    <category>gwt</category>
    <category>apple</category>
    <category>meetup</category>
    <category>california</category>
    <category>google</category>
            <description>&lt;div style=&quot;float: right; margin-left: 10px; margin-bottom: 10px;&quot;&gt;
 &lt;a href=&quot;http://www.flickr.com/photos/52148551@N00/2192997236/&quot; title=&quot;photo sharing&quot;&gt;&lt;img src=&quot;//farm3.static.flickr.com/2321/2192997236_575c50490b_m.jpg&quot; alt=&quot;&quot; style=&quot;border: solid 1px #000000;&quot; /&gt;&lt;/a&gt;
 &lt;br /&gt;
 &lt;span style=&quot;font-size: 0.9em; margin-top: 0px;&quot;&gt;
  &lt;a href=&quot;http://www.flickr.com/photos/52148551@N00/2192997236/&quot;&gt;Morning light on the Golden Gate Bridge&lt;/a&gt;
  &lt;br /&gt;
  Originally uploaded by &lt;a href=&quot;http://www.flickr.com/people/52148551@N00/&quot;&gt;TravelnFotog&lt;/a&gt;
 &lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;
This week is shaping up to be quite the action-packed week in California. First of all, the MacWorld 2008 Keynote is happening today. This is the event where new Apple products are announced and everyone yawns. I hope they announce some interesting stuff, but I&apos;m not getting my hopes up. The only thing I&apos;d likely buy is a screaming laptop with 8 GB of RAM. &lt;/p&gt;
&lt;p&gt;Tonight, there&apos;s a &lt;a href=&quot;https://sv-web-jug.dev.java.net/servlets/NewsItemView?newsItemID=5504&quot;&gt;presentation on GWT at Google&lt;/a&gt;. Since this is only a few blocks from LinkedIn, I&apos;m going to try to make the meeting and checkout the &quot;Googleplex&quot; for the first time.&lt;/p&gt;
&lt;p&gt;Finally, tomorrow night a bunch of us are getting together for a Silicon Valley Tech Meetup at &lt;a href=&quot;http://www.oldpropa.com/&quot;&gt;The Old Pro&lt;/a&gt; in Palo Alto. Start time is 6:30.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/comparing_jvm_web_frameworks_presentation</guid>
    <title>Comparing JVM Web Frameworks Presentation</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/comparing_jvm_web_frameworks_presentation</link>
        <pubDate>Wed, 14 Nov 2007 15:14:53 -0700</pubDate>
    <category>Java</category>
    <category>wicket</category>
    <category>struts2</category>
    <category>gwt</category>
    <category>seam</category>
    <category>flex</category>
    <category>apachecon</category>
    <category>grails</category>
    <category>webframeworks</category>
            <description>Early this morning, I assembled a &lt;strong&gt;Comparing JVM Web Frameworks&lt;/strong&gt; presentation in preparation for &lt;a href=&quot;http://us.apachecon.com/us2007/program/talk/1994&quot;&gt;my talk tomorrow at ApacheCon&lt;/a&gt;. As &lt;a href=&quot;http://raibledesigns.com/rd/entry/comparing_web_frameworks_time_for&quot;&gt;mentioned on Monday&lt;/a&gt;, this presentation compares Flex, Grails, GWT, Seam, Struts 2 and Wicket. While I think this presentation would be fun to deliver, I don&apos;t believe it has as much &lt;em&gt;meat&lt;/em&gt; as the original talk I was planning to give. My original talk compares JSF, Spring MVC, Stripes, Struts 2, Tapestry and Wicket. Since I&apos;ve used all these frameworks, I&apos;m able to compare them more on their technical features. Since I haven&apos;t used Flex, GWT or Seam, there was no way for me to 1) try them all before tomorrow and 2) do a thorough analysis of how well they each handle my desired features.&lt;/p&gt;

&lt;p&gt;Since the abstract on ApacheCon&apos;s website mentions my original presentation, I don&apos;t want to yank out the carpet and present the second without asking. So my plan is to ask the audience which one they&apos;d rather hear and continue from there. I&apos;ve updated both presentations with the latest statistics and uploaded them for your review. For those of you who&apos;ve used these frameworks, I&apos;d be interested to hear how accurate you think my Pros and Cons section is. If you know of better pros or cons, please let me know and I&apos;ll adjust as needed.&lt;/p&gt;

&lt;ul class=&quot;glassList&quot;&gt;

&lt;li&gt;&lt;a href=&quot;http://static.raibledesigns.com/repository/presentations/ComparingJavaWebFrameworks-ApacheConUS2007.pdf&quot;&gt;Comparing  JSF, Spring MVC, Stripes, Struts 2, Tapestry and Wicket&lt;/li&gt;

&lt;li&gt;&lt;a href=&quot;http://static.raibledesigns.com/repository/presentations/ComparingJVMWebFrameworks-ApacheConUS2007.pdf&quot;&gt;Comparing  Flex, Grails, GWT, Seam, Struts 2 and Wicket&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;While creating the 2nd presentation, I found a couple things that surprised me. The first is how popular Flex is - not only in job listings, but also in skilled developers and mailing list traffic. Below is a graph that shows how there aren&apos;t many jobs for most of the frameworks, but there&apos;s lots for Flex.

&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;

&lt;img src=&quot;//static.raibledesigns.com/repository/images/dicejobcount-20071115.png&quot; width=&quot;416&quot; height=&quot;276&quot; alt=&quot;Dice.com Job Count - November 2007&quot; /&gt;

&lt;/p&gt;

&lt;p&gt;The following graph illustrates while I chose to use Flex instead of OpenLaszlo as the Flash framework. OpenLaszlo has a &lt;em&gt;much&lt;/em&gt; smaller community than Flex.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;

&lt;img src=&quot;//static.raibledesigns.com/repository/images/mailinglisttraffic-200711.png&quot; width=&quot;424&quot; height=&quot;257&quot; alt=&quot;User Mailing List Traffic - November 2007&quot; /&gt;

&lt;/p&gt;

&lt;p&gt;The second thing that was surprising is &lt;strong&gt;Seam doesn&apos;t have a logo&lt;/strong&gt;! How does it &lt;em&gt;ever&lt;/em&gt; expect to become a popular open source project without a logo?! It&apos;s amazing they&apos;ve made it this far without having this essential feature. To motivate the creation of a Seam logo, I&apos;m using the following butt-ugly logo in my presentation (found &lt;a href=&quot;http://www.plwmarine.co.uk/images/seam.gif&quot;&gt;here&lt;/a&gt;). Hopefully something better comes along before I deliver my talk tomorrow. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;

&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;

&lt;img src=&quot;//static.raibledesigns.com/repository/images/seam.gif&quot; width=&quot;383&quot; height=&quot;136&quot; alt=&quot;Seam Logo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Monday&apos;s post started an &lt;a href=&quot;http://www.nabble.com/Stripes-Ignored...Again-tf4800043.html#a13732878&quot;&gt;interesting thread&lt;/a&gt; on Stripes&apos; mailing list. Also, I really like &lt;a href=&quot;http://blog.interface21.com/main/2007/11/14/annotated-web-mvc-controllers-in-spring-25/&quot;&gt;Spring MVC&apos;s new annotation support&lt;/a&gt;. It&apos;d be nice to see it go a step further and use defaults (like ControllerClassNameHandlerMapping + subpackage support) and only require annotations to override the defaults. IMO, Stripes, Spring MVC and Struts 2 are all excellent choices if a request-based framework provides the best architecture for your application. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; Comparing Flex, Grails, GWT, Seam, Struts 2 and Wicket seems to gave gained a lot of interest (and support) &lt;a href=&quot;http://www.gmjjavadesigns.com/gmjd/entry/comparing_web_frameworks&quot;&gt;in&lt;/a&gt; &lt;a href=&quot;http://rmh.blogs.com/weblog/2007/11/comparing-web-f.html&quot;&gt;the&lt;/a&gt; &lt;a href=&quot;http://in.relation.to/Bloggers/TheWebFrameworkSpaceIsAchangin&quot;&gt;blogosphere&lt;/a&gt;. Because of this, I&apos;m considering submitting it as a JavaOne talk. If I were to do this, how would you like to see this presentation changed and improved?
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 3:&lt;/strong&gt; I received the following Seam logo via e-mail. &lt;em&gt;Thanks Christian!&lt;/em&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;

&lt;img src=&quot;//static.raibledesigns.com/repository/images/seam_logo_blue.png&quot; width=&quot;400&quot; height=&quot;160&quot; alt=&quot;Seam Logo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 4:&lt;/strong&gt; I&apos;ve updated the Dice.com graph to include &quot;Java&quot; with every search term. To understand the comments on this entry, you might want to view the &lt;a href=&quot;http://static.raibledesigns.com/repository/images/dicejobcount-20071114.png&quot; rel=&quot;lightbox&quot;&gt;previous graph&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 5:&lt;/strong&gt; This presentation was posted to the Wicket User mailing list. I followed up asking users to post the pros and cons of Wicket. Now there&apos;s a &lt;a href=&quot;http://www.nabble.com/Matt-Raible%27s-ApacheCon-presentation-tf4815955.html&quot;&gt;lengthy thread&lt;/a&gt; on Wicket&apos;s Pros and Cons. Good stuff.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/comparing_web_frameworks_time_for</guid>
    <title>Comparing Web Frameworks: Time for a Change?</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/comparing_web_frameworks_time_for</link>
        <pubDate>Mon, 12 Nov 2007 16:46:56 -0700</pubDate>
    <category>Java</category>
    <category>struts2</category>
    <category>comparison</category>
    <category>gwt</category>
    <category>grails</category>
    <category>webframeworks</category>
    <category>seam</category>
    <category>wicket</category>
            <description>I first came up with the idea to do a &quot;Comparing Web Frameworks&quot; talk in 2004. I submitted a talk to ApacheCon and it got accepted. From there, I &lt;a href=&quot;http://raibledesigns.com/rd/entry/comparing_web_frameworks_presentation_outline&quot;&gt;outlined&lt;/a&gt;, &lt;a href=&quot;http://raibledesigns.com/rd/entry/comparing_web_frameworks_equinox_ant&quot;&gt;created sample apps&lt;/a&gt; and &lt;a href=&quot;http://raibledesigns.com/rd/entry/comparing_web_frameworks_presentation&quot;&gt;practiced&lt;/a&gt; this talk before ApacheCon. Believe it or not, that was my first time speaking in front of a large audience.
&lt;/p&gt;
&lt;p class=&quot;smokey&quot;&gt;
&lt;strong&gt;Historical note:&lt;/strong&gt; October 2004 was a pretty cool month - I &lt;a href=&quot;http://raibledesigns.com/rd/entry/rails_the_mvc_framework_for&quot;&gt;discovered Rails&lt;/a&gt; and Roller had a &lt;a href=&quot;http://raibledesigns.com/rd/entry/upgraded_to_roller_1_0&quot;&gt;1.0 release candidate&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;When I created the presentation, it was in large part due to all the WebWork and Tapestry folks harassing me on this very blog. I started using Struts in June 2001 (the same month 1.0 was released) and had used it successfully on many projects. Part of the reason this blog became so popular was I posted lots of tips and tricks that I learned about Struts (and its related project) while using it. After a while, the noise became too heavy to ignore it - especially after I&apos;d tried Spring MVC. So in an effort to learn more about the the other frameworks, I submitted a talk and &lt;em&gt;forced&lt;/em&gt; myself to learn them. It seems to have worked out pretty well.
&lt;/p&gt;
&lt;p&gt;With that being said, I think it&apos;s time for a change. The reason I originally wrote this was to educate developers on how the top Java web frameworks differed and encourage developers to try more than one. A while later, I realized there&apos;s &lt;a href=&quot;http://raibledesigns.com/rd/entry/tssjs_bof_web_framework_sweet&quot;&gt;different tools for different jobs&lt;/a&gt; and it&apos;s not a one-size-fits-all web framework world. It&apos;s not a component vs. request-based framework world either. There&apos;s lots of options now. When I&apos;ve delivered this talk earlier this year, I&apos;ve always felt like I&apos;ve left quite a few frameworks out. The solution could be to add more and more frameworks. However, I don&apos;t think that&apos;s a good idea. The talk is already difficult to squeeze into 90 minutes and it&apos;s unlikely that adding more frameworks is going to help.
&lt;/p&gt;
&lt;p&gt;The change I&apos;d like to do is to reduce the number of frameworks down to (what I consider) the top web frameworks for deploying to the JVM. What are those frameworks? IMHO, they are as follows, in no particular order:
&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;GWT-Ext&lt;/li&gt;
&lt;li&gt;Wicket&lt;/li&gt;
&lt;li&gt;Grails&lt;/li&gt;
&lt;li&gt;Flex/OpenLaszlo&lt;/li&gt;
&lt;li&gt;Seam&lt;/li&gt;
&lt;li&gt;Struts 2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The RIFE, Tapestry and ZK folks can start bitching now. Sorry - less frameworks make for a more interesting talk. Maybe I&apos;ll add you in the future and I can ask the audience which ones they want compared then we can choose four and go from there. Why don&apos;t I mention Spring MVC? Because I think Struts 2 is easier to learn and be productive with and I also like it&apos;s more open and active community. I&apos;ve written applications with both and I like Struts 2 better. As for Flex vs. OpenLaszlo, I&apos;m somewhat torn. It seems like learning Flex is going to be better for your career, but it&apos;s likely useless without the Flex Builder - which is not open source. However, at $250, it&apos;s likely worth its price. I know the &lt;a href=&quot;http://www.picnik.com/&quot;&gt;Picnik&lt;/a&gt; folks used Flex for their UI - I wonder how much they used Flex Builder in the process?
&lt;/p&gt;
&lt;p&gt;What do you think? Are these the top web frameworks for JVM deployment today? The next time I give this talk is &lt;a href=&quot;http://us.apachecon.com/us2007/program/talk/1994&quot;&gt;this Thursday at ApacheCon&lt;/a&gt;. I may try to re-write my talk and then give the audience a choice of old vs. new. The downside of doing the new talk is I won&apos;t have time to write apps with GWT, Flex or Seam. Anyone care to post their top three pros and cons for any of these frameworks?</description>          </item>
  </channel>
</rss>