<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0IFQH4ycSp7ImA9WhRaGU8.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709</id><updated>2012-02-22T06:38:31.099-08:00</updated><category term="Roo" /><category term="GoogleApps" /><category term="POM" /><category term="GWT" /><category term="SpringRoo" /><category term="MVC" /><category term="ClickHandler" /><category term="Objectify" /><category term="Domain Objects" /><category term="UiBinder" /><category term="Dependency Injection" /><category term="Declarative Layout" /><category term="crm" /><category term="RPC" /><category term="demo" /><category term="GWTP" /><category term="Spring Roo" /><category term="Groovy on Grails" /><category term="Git" /><category term="Chrome" /><category term="Grails" /><category term="eclipse" /><category term="Spring" /><category term="code" /><category term="POJO" /><category term="GIN" /><category term="review" /><category term="Video" /><category term="vaadin" /><category term="News" /><category term="Handler" /><category term="Newbie" /><category term="GoogleIO" /><category term="future" /><category term="backbone.js" /><category term="GUICE" /><category term="Google Apps Marketplace" /><category term="tutorial" /><category term="GAE" /><category term="XML" /><category term="format" /><category term="Piriti" /><category term="Inversion of Control" /><category term="Java" /><category term="Contactpa" /><category term="widgets" /><category term="Groovy" /><category term="sohocrm" /><category term="Demos" /><category term="OpenID" /><category term="AttributeExchange" /><category term="DI" /><category term="TabLayoutPanel" /><category term="Example" /><category term="Maven" /><category term="twitter" /><category term="Marketplace" /><category term="microsoft" /><category term="Authentication" /><category term="Dependencies" /><category term="article" /><category term="framework" /><category term="gwtsushi" /><category term="MVP4G" /><category term="Event" /><category term="Google Apps" /><category term="Tab" /><title>GWT Sushi</title><subtitle type="html">Rolls of GWT, Java, Spring, Grails, Design Patterns and other pro web development goodies.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.gwtsushi.info/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>56</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/GwtSushi" /><feedburner:info uri="gwtsushi" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUcMR3s9eyp7ImA9WhRSEkw.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-3094829419546494219</id><published>2011-11-13T11:12:00.001-08:00</published><updated>2011-11-13T11:38:06.563-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-13T11:38:06.563-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="backbone.js" /><category scheme="http://www.blogger.com/atom/ns#" term="GWTP" /><category scheme="http://www.blogger.com/atom/ns#" term="DI" /><category scheme="http://www.blogger.com/atom/ns#" term="MVP4G" /><category scheme="http://www.blogger.com/atom/ns#" term="Spring" /><title>Subjective thoughts on best practice with GWT applications.</title><content type="html">&lt;br /&gt;
&lt;div class="separator" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"&gt;
&lt;a href="http://draft.blogger.com/"&gt;&lt;span id="goog_316789841"&gt;&lt;/span&gt;&lt;span id="goog_316789845"&gt;&lt;/span&gt;&lt;span id="goog_316789851"&gt;&lt;/span&gt;&lt;img border="0" height="145" src="http://2.bp.blogspot.com/-oBfKjDlaPw8/TsAcZ44POcI/AAAAAAAAJP8/rYlo0NuKlw0/s400/Screen+Shot+2011-11-13+at+11.36.47+AM.png" width="400" /&gt;&lt;span id="goog_316789852"&gt;&lt;/span&gt;&lt;/a&gt;&lt;span id="goog_316789846"&gt;&lt;/span&gt;&lt;span id="goog_316789842"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
If you have spent anytime with me you know I love GWT. &amp;nbsp;But in my humble opinion there are ways to build web applications that still involve the&amp;nbsp;gamut&amp;nbsp;of javascript frameworks and bog-standard HTML5 and javascript. &amp;nbsp;Through my vast and continued learning experience of GWT I am beginning to see it in its current guise as being great for building complex and large widgets embedded in a web environment that is built in a more traditional web application framework. &amp;nbsp;Using the word tradition is kind of absurd in the web application design sphere because a tradition is&amp;nbsp;established&amp;nbsp;in a matter of months and then disposed for a new&amp;nbsp;tradition&amp;nbsp;within a couple of years. &amp;nbsp;However we appear to be heading towards a path of convergence in how and the way we code. &amp;nbsp;I recognise this as entirely subjective but for companies adopting GWT for the first time,&amp;nbsp;experimenting&amp;nbsp;with complex GWT widgets, then embedding them into their existing web applications is a great way to start on the GWT path. &lt;br /&gt;
&lt;br /&gt;
Model-View-Controller (MVC) and Model-View-Presenter (MVP) are&amp;nbsp;becoming&amp;nbsp;the de-facto design patterns for building desktop, web and mobile applications. &amp;nbsp;Developers pay attention, if these are not on your resume, get them on there as fast as possible. &amp;nbsp;You should not leave home without it. &amp;nbsp;Many frameworks in almost every language develop according to this pattern. &amp;nbsp;So whether you are using Ruby on Rails, Grails, GWT, Spring MVC, Backbone.js they all design their frameworks around this convention. &amp;nbsp;GWT is a little late to the game with regards to this and so two additional frameworks have been around for a while which in my opinion currently offer a lot more features than the "Activities and Places" inbuilt infrastructure. &amp;nbsp;These two frameworks are GWT-Platform and MVP4G. &amp;nbsp; They are both on Google Code and both have extensive user collaboration and input. &amp;nbsp;Developing outside of GWT in the standard HTML-CSS-JS arena backbone.js offers a Javascript implementation of MVC. &amp;nbsp;I haven't used it as of yet but from the brief tutorials I have read it appears to be very easy to use.&lt;br /&gt;
&lt;br /&gt;
In a similar vein, Dependency Injection is also a must have. &amp;nbsp;Design your code to interfaces and inject interfaces at runtime. &amp;nbsp;This is achievable in GWT using Google GIN on the client and Google GUICE on the server. &amp;nbsp;However my current overwhelming suggestion on the server is the Spring framework. &amp;nbsp;If you are writing Java server code and not using Spring, you are probably writing lots of boilerplace bullshit. &amp;nbsp;Stop it now!. &amp;nbsp;My server side framework knowledge is limited so would love to hear from other developers on alternatives, but from what I have seen this is well adopted, supported and promoted in the media and job adverts. &amp;nbsp;Spring is about more than Dependency Injection but this is at the core of the framework. &amp;nbsp;If you want to develop modular, testable code then you need to use DI. &lt;br /&gt;
&lt;br /&gt;
Using the Facebook web site as an example lets look at how you might construct this from scratch. &amp;nbsp;Some GWT developers will suggest that the whole site should be built in GWT. &amp;nbsp;I disagree but more on that later. &amp;nbsp;However I believe that you will have a more flexible and productive if you develop the complex parts of your web site in GWT and embed them into the website. &amp;nbsp; So when looking at your newsfeed the complex box that controls updating your status etc might be a small GWT application but it is embedded in an AJAX-controlled feed panel table. &amp;nbsp;The reason I think this? &amp;nbsp;Unless your whole team consists of ninja, ex-Google GWT developers that worked on the ad-sense or ad-words interface, then you are going to experience delays in your project as you migrate your developers to a new way or working. &amp;nbsp;By concentrating complexity in small manageable chunks you reduce your exposure to delays in your project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-3094829419546494219?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AeAFADkyzr2O105SPeVMuPpEKb8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AeAFADkyzr2O105SPeVMuPpEKb8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AeAFADkyzr2O105SPeVMuPpEKb8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AeAFADkyzr2O105SPeVMuPpEKb8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/Kc_VySzDsvo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/3094829419546494219/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/11/subjective-thoughts-on-best-practice.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3094829419546494219?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3094829419546494219?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/Kc_VySzDsvo/subjective-thoughts-on-best-practice.html" title="Subjective thoughts on best practice with GWT applications." /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-oBfKjDlaPw8/TsAcZ44POcI/AAAAAAAAJP8/rYlo0NuKlw0/s72-c/Screen+Shot+2011-11-13+at+11.36.47+AM.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/11/subjective-thoughts-on-best-practice.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAGQn49fip7ImA9WhRTEUs.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-2440857328033401932</id><published>2011-11-01T09:57:00.000-07:00</published><updated>2011-11-01T09:58:43.066-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-01T09:58:43.066-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Apps Marketplace" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy on Grails" /><category scheme="http://www.blogger.com/atom/ns#" term="demo" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Single Sign On to Google Apps Marketplace with a Grails application</title><content type="html">Hey, have you tried Grails? &amp;nbsp;If you love Java and love Spring, you are going to adore Groovy on Grails (www.grails.org). &amp;nbsp;Last week I decided to try out Groovy on Grails using the excellent free ebook located here: &amp;nbsp;&lt;a href="http://www.infoq.com/minibooks/grails-getting-started" target="_blank"&gt;free ebook - yes please&lt;/a&gt;. &amp;nbsp;The book took me two days to navigate through and if you have any experience in Ruby on Rails, you are going to love it. &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-frppKc8Aw5A/TrAZCu8HL3I/AAAAAAAAJPs/Tz64-Xw1zwc/s1600/Screen+Shot+2011-11-01+at+9.04.38+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="176" src="http://4.bp.blogspot.com/-frppKc8Aw5A/TrAZCu8HL3I/AAAAAAAAJPs/Tz64-Xw1zwc/s400/Screen+Shot+2011-11-01+at+9.04.38+AM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Grails applications are typically called Groovy on Grails. &amp;nbsp;Groovy is the language and Grails is the utility that uses convention over configuration to build easily, web applications. &amp;nbsp;I won't go into too much detail here as the book says it better than I can but it is well worth checking out.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;b&gt;SSO - Google Apps Marketplace&lt;/b&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
As usual I always try to do something "complicated" in order to test the validity and maturity of any framework. &amp;nbsp;My usual test case is to try Single Sign On with the Google Apps Marketplace. &amp;nbsp;Again I am not going to go into too much details on what that actually means but if you are a Google Apps user and you have installed a third party application it is a way of authenticating the user without having to ask them for their credentials. &amp;nbsp;Since I build apps for the Google Apps Marketplace I have to ensure I can do this otherwise the framework itself won't be a good choice. &amp;nbsp;In addition because I am not an OpenID expert and prefer to stand on the shoulders of giants, the ease at which this can be implemented and understood is very important to me.&amp;nbsp;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Since Groovy is a superset and dynamic language and can basically use Java and Java dependencies and since I had already built a SSO solution in a Java-GWT application for www.contactpa.com, I figured this should be fairly simple. &amp;nbsp;On the whole it was my biggest problem was understanding how Dependency Injection works with Grails / Groovy and how to include dependencies in my project.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
All code is available here on this &lt;a href="https://github.com/thinkjones/SSO-with-Google-Apps-Marketplace-with-Grails" target="_blank"&gt;github repository&lt;/a&gt;.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;b&gt;What did I learn?&lt;/b&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Here are the pitfalls and problems I overcame whilst building this project:&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;b&gt;Dependencies: &amp;nbsp;&lt;/b&gt;I love/hate Maven, I have enough power to know how to do something and resolve issues but not a complete mastery, I am a perfectionist, to really understand. &amp;nbsp;Anyhow I recognise the power of Maven and love it otherwise. &amp;nbsp;So my first question was how to include&amp;nbsp;dependencies. &amp;nbsp;Now I tried messing around with the project by mavenizing but this left me with a whole host of other issues which I couldn't understand. &amp;nbsp;Mainly due to my lack of experience in Grails. &amp;nbsp;So I decided to use the standard approach. &amp;nbsp;On conf/BuildConfig.groovy there are several sections to add dependencies. &amp;nbsp;Anyone with maven experience will understand this coding convention:&lt;/div&gt;
&lt;pre&gt;    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.

        // runtime 'mysql:mysql-connector-java:5.1.13'
  
  runtime 'mysql:mysql-connector-java:5.1.13'
  compile group:'org.openid4java', name:'openid4java-consumer', version:'0.9.6'
  compile group:'com.google', name:'step2-common', version:'1-SNAPSHOT'
  compile group:'com.google', name:'step2-consumer', version:'1-SNAPSHOT'
  compile group:'com.google.inject', name:'guice', version:'3.0'
  compile group:'javax.servlet', name:'jstl', version:'1.2'
  compile group:'org.apache.httpcomponents', name:'httpclient', version:'4.1'
  compile (group:'org.openxri', name:'openxri-client', version:'1.2.1') { excludes([ group: 'org.slf4j', name: 'slf4j-jcl']) }
  compile group:'org.jdom', name:'jdom', version:'1.1'
  compile group:'com.google.collections', name:'google-collections', version:'1.0'
    }
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Mapping the openid: &amp;nbsp;&lt;/b&gt;I created a controller called GAMOpenIdController which stands for Google Apps Marketplace OpenID. &amp;nbsp; Using convention this would have mapped to a url:/GAMOpenId/OpenID where for clarity I would prefer it to look like this: &amp;nbsp;url:/openid. &amp;nbsp;This url is the one Google redirects you to &amp;nbsp;to check a user exists and then to authenticate the application. &amp;nbsp;In order to do this I had to add an entry into the UrlMappings.groovy configuration file:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class="p1"&gt;
"/openid"&lt;span class="s1"&gt;(controller:&lt;/span&gt;"GAMOpenId"&lt;span class="s1"&gt;, action:&lt;/span&gt;"openid"&lt;span class="s1"&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&lt;b&gt;Adding Java SSO Code: &amp;nbsp;&lt;/b&gt;This is one of the reasons Grails is so awesome. &amp;nbsp;You can embed Java code in with your Groovy code. &amp;nbsp;Awesome. &amp;nbsp;So I copied my SSO helper code from my other application. &amp;nbsp;This is largely based on the marketplace sample application &lt;a href="http://code.google.com/googleapps/marketplace/tutorial_java.html" target="_blank"&gt;located here&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-wQAI783hhow/TrAc4h7fiZI/AAAAAAAAJP0/jGtUmyD6FEc/s1600/Screen+Shot+2011-11-01+at+9.21.42+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-wQAI783hhow/TrAc4h7fiZI/AAAAAAAAJP0/jGtUmyD6FEc/s1600/Screen+Shot+2011-11-01+at+9.21.42+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
I have modified this code slightly and will include a full copy of the grails application at the end of this article.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;b&gt;Adding the Controller: &amp;nbsp;&lt;/b&gt;This was so easy. &amp;nbsp; See the code at the end.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;b&gt;Adding the service: &amp;nbsp;&lt;/b&gt;Services in Grails control the business logic so I added all the servlet code from the marketplace application in here, but modified for Groovy. See file contactpa.GoogleOpenIdAuthService.groovy. &amp;nbsp;This then called the Java SSO Code listed above. &amp;nbsp;I didn't really have a problem here but the final stage of authentication was failing. &amp;nbsp;I fixed this in the method&amp;nbsp;&lt;span style="background-color: transparent;"&gt;getReceivingUrl(). &amp;nbsp;It turns out when the server makes a call to another server, when the request is returned this is routed to a URL of the format: url:/&lt;/span&gt;&lt;span style="background-color: transparent;"&gt;grails/GAMOpenId/openid.dispatch whereas for the receivingURL to be authenticated correctly it should read url:/&lt;/span&gt;&lt;span style="background-color: transparent;"&gt;openid.&lt;/span&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;b&gt;Don't edit applicationContext.xml: &amp;nbsp;&lt;/b&gt;One trap, coming from a Spring background was that I needed to add some DI Beans in my Spring configuration for the Java SSO stuff above. &amp;nbsp;Instead of following Grails convention I decided to edit the applicationContext.xml, which you would ordinaarily do in a standard Spring app. &amp;nbsp;However this gave me a whole host of unusual errors until I read that beans should be configured in a file called resources.xml. &amp;nbsp; So in conf/spring/resources.xml I added my beans:&lt;/div&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="s2"&gt;xml&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;version&lt;span class="s3"&gt;=&lt;/span&gt;&lt;span class="s4"&gt;"1.0"&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;encoding&lt;span class="s3"&gt;=&lt;/span&gt;&lt;span class="s4"&gt;"UTF-8"&lt;/span&gt;&lt;span class="s1"&gt;?&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;beans&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;xmlns&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.springframework.org/schema/beans"&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s5"&gt;xmlns:util&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.springframework.org/schema/util"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;xmlns:xsi&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s5"&gt;xmlns:context&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.springframework.org/schema/context"&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s5"&gt;xmlns:mvc&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.springframework.org/schema/mvc"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;xmlns:task&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.springframework.org/schema/task"&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s5"&gt;xmlns:p&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"http://www.springframework.org/schema/p"&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;xsi:schemaLocation&lt;span class="s3"&gt;=&lt;/span&gt;&lt;span class="s4"&gt;"&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/beans &lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/util &lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/util/spring-util-3.0.xsd&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/context &lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/context/spring-context-3.0.xsd&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/mvc &lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/task &lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;http://www.springframework.org/schema/task/spring-task-3.0.xsd"&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;bean&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;name&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"consumerHelperFactory"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;class&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"contactpa.sso.ConsumerFactory"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s1"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;bean&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;name&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"consumerHelper"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;class&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"com.google.step2.ConsumerHelper"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;factory-method&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"getConsumerHelper"&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s5"&gt;factory-bean&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"consumerHelperFactory"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s1"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="s3"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;bean&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;name&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"httpFetcher"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;class&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"com.google.step2.http.DefaultHttpFetcher"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s1"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;bean&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;name&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"googleHostedHostMetaFetcher"&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s5"&gt;class&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"contactpa.sso.GoogleHostedHostMetaFetcher"&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;constructor-arg&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;index&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"0"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;ref&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"httpFetcher"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s1"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p4"&gt;
&lt;span class="s3"&gt;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;bean&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p4"&gt;
&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;beans&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;b&gt;Summary&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
This has turned to be a bit of a mind dump as I navigate a new area in Java development, for me anyhow. Grails is a great natural progression for Java developers looking to get into dynamic programming and using a framework for convention over configuration. &amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
I have open sourced this project and it is available at git hub to analyse and comment on:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
https://github.com/thinkjones/SSO-with-Google-Apps-Marketplace-with-Grails&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-2440857328033401932?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/saCYUlHwq7ccmyaBCma_aVa0-Ns/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/saCYUlHwq7ccmyaBCma_aVa0-Ns/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/saCYUlHwq7ccmyaBCma_aVa0-Ns/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/saCYUlHwq7ccmyaBCma_aVa0-Ns/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/R0VhUMbpGfo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/2440857328033401932/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/11/single-sign-on-to-google-apps.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/2440857328033401932?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/2440857328033401932?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/R0VhUMbpGfo/single-sign-on-to-google-apps.html" title="Single Sign On to Google Apps Marketplace with a Grails application" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-frppKc8Aw5A/TrAZCu8HL3I/AAAAAAAAJPs/Tz64-Xw1zwc/s72-c/Screen+Shot+2011-11-01+at+9.04.38+AM.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/11/single-sign-on-to-google-apps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUHR3w7eip7ImA9WhdaFkg.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-667289290128660560</id><published>2011-10-26T11:03:00.000-07:00</published><updated>2011-10-26T11:03:56.202-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-26T11:03:56.202-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gwtsushi" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><title>Hey fools I am on twitter - @gwtsushi</title><content type="html">With reference to the title of this article: After recently completing the Steve Jobs' biography I am convinced that the best way to succeed is to be a brutally honest ass hole. &amp;nbsp;It won't last long, films and books tend to affect me. &amp;nbsp;Anyway readers I am trying to spruce up my twitter feed and I need three things:&lt;br /&gt;
&lt;br /&gt;
1. &amp;nbsp;A good logo.&lt;br /&gt;
2. &amp;nbsp;Brilliant followers&lt;br /&gt;
3. &amp;nbsp;Good things to follow.&lt;br /&gt;
&lt;span style="background-color: transparent;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: transparent;"&gt;Feel free to help, suggest or get in contact: &amp;nbsp;&lt;/span&gt;&lt;a href="http://twitter.com/#!/gwtsushi" style="background-color: transparent;"&gt;@gwtsushi&amp;nbsp;&lt;/a&gt;&lt;span style="background-color: transparent;"&gt;. &amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-667289290128660560?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TiWUUwbqJoZrLpeDo76n5xdWj8I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TiWUUwbqJoZrLpeDo76n5xdWj8I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TiWUUwbqJoZrLpeDo76n5xdWj8I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TiWUUwbqJoZrLpeDo76n5xdWj8I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/852fVn3bE20" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/667289290128660560/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/10/hey-fools-i-am-on-twitter-gwtsushi.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/667289290128660560?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/667289290128660560?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/852fVn3bE20/hey-fools-i-am-on-twitter-gwtsushi.html" title="Hey fools I am on twitter - @gwtsushi" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/10/hey-fools-i-am-on-twitter-gwtsushi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04HRHwzfip7ImA9WhdWE08.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-7925637476151120537</id><published>2011-09-06T08:12:00.000-07:00</published><updated>2011-09-06T08:12:15.286-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-06T08:12:15.286-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Spring Roo" /><category scheme="http://www.blogger.com/atom/ns#" term="Roo" /><category scheme="http://www.blogger.com/atom/ns#" term="GAE" /><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="SpringRoo" /><title>Spring Roo 1.2.0 with GWT and Google App Engine</title><content type="html">I was first introduced to Spring Roo at Google IO 2010 and I was amazed with the product, it allowed a developer to prototype an application very quickly, building everything from the server, domain, and GWT client. &amp;nbsp;It looked awesome. &lt;br /&gt;
&lt;br /&gt;
When I got home I realised that we were shown a fixed demo in that many of the features didn't really work when building on Google App Engine and Google Web Toolkit. &amp;nbsp;Not a problem as all developers know we are used to living on the cutting alpha-beta edge of software where great new features come with one huge caveat, they occasionally don't work.&lt;br /&gt;
&lt;br /&gt;
That was then and this is now. &amp;nbsp;Like Sushi which I try every 6 months just to confirm that I still am not a huge fan, it doesn't taste of anything right?, I try the latest version of Spring Roo. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The Upgrade Path&lt;/b&gt;&lt;br /&gt;
Let me just say that I love SpringSource they provide a lot of excellent tools for the Java developer and the Spring Roo documentation is no exception. &amp;nbsp;The upgrade path is very easy, unpack the latest Spring Roo to a directory of your choosing, amend your $ROO_HOME variable in .profile (Mac OSx) and then re-establish the symbolic link to the roo command line. &amp;nbsp;(&lt;span style="background-color: white; font-family: monospace; font-size: 12px; text-align: justify;"&gt;sudo ln -s $ROO_HOME/bin/roo.sh /usr/bin/roo&lt;/span&gt;)&lt;br /&gt;
&lt;br /&gt;
Done and done!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The Bleeding Edge&lt;/b&gt;&lt;br /&gt;
So I tried Spring Roo 1.1.5 and it was giving me lots of errors with trying a GWT-GAE project. &amp;nbsp;It seemed as equally unreliable as I had tried with previous versions. &amp;nbsp;Let me just add if you are using a standard database such as MySQL or any of the other persistence options, I believe Spring Roo works just fine. &amp;nbsp;The problems I usually run into are related to the peculiarities of Google App Engine and how Roo handles those. &lt;br /&gt;
&lt;br /&gt;
Since most of my current projects are currently in the GAE-GWT sphere and Roo advertises that it is suppose to work in this area, I decided to upgrade to the very latest Spring Roo, so I delved into the nightly builds and installed (1.2.0.BUILD-SNAPSHOT [rev 176e407]).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Go for 1.2.0 Its Much Better&lt;/b&gt;&lt;br /&gt;
After building a couple of projects with 1.2.0 I can honestly say this is the best version yet by far. &amp;nbsp;Why? &amp;nbsp;Well it appears to work this time for GWT-GAE projects. &amp;nbsp;Most of my personal work is done on Google App Engine. &amp;nbsp;This might change as I am not really liking the new billing restrictions but we will see how those actually plan out when implemented.&lt;br /&gt;
&lt;br /&gt;
I typically build small projects that utilise some sort of&amp;nbsp;reference&amp;nbsp;between domain objects and then build a GWT project and then test it to see if it actually works. &amp;nbsp;I will deal with deployment in a different post. &amp;nbsp;What is great about Roo is that you can amend say the domain objects and the auto UI will get updated automatically. &amp;nbsp;Simply add the line : private String userName; : to your domain object, boot up Roo and it auto creates the UI amendments needed. &amp;nbsp;Pretty stunning. &amp;nbsp;I haven't yet got to work out how you prevent it from doing this should you want to improve the UI, but I am sure that will come soon.&lt;br /&gt;
&lt;br /&gt;
The project I have built it is that for a taxi company to take bookings. &amp;nbsp;It includes three domain objects Contact, Booking and Journey. &amp;nbsp; &amp;nbsp;A booking can have one or more contacts, and one ore more journeys. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;A Spring Roo GAE GWT project that works&lt;/b&gt;&lt;br /&gt;
&amp;nbsp;Here is the contents of my Roo file, hopefully this will help you work with your project.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;project com.prestige.booking

persistence setup --provider DATANUCLEUS --database GOOGLE_APP_ENGINE --applicationId PrestigeBooking

enum type --class ~.shared.domain.ContactType
enum constant --name Booking
enum constant --name Billing
enum constant --name Passenger

entity --class ~.shared.domain.Contact  --testAutomatically 
field string --fieldName fullName --notNull
field string --fieldName email
field string --fieldName phoneNumber
field enum --fieldName contactType --type ~.shared.domain.ContactType

entity --class ~.shared.domain.Booking --testAutomatically 
field reference --type ~.shared.domain.Contact passenger

entity --class com.prestige.booking.shared.domain.Journey --testAutomatically 
field date --fieldName journeyDate --type java.util.Date 
field string --fieldName startAddress 
field string --fieldName endAddress
field string --fieldName startTime 
field reference --fieldName booking --type com.prestige.booking.shared.domain.Booking 

loggin setup --level INFO

web gwt setup
&lt;/pre&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Next Steps&lt;/b&gt;&lt;br /&gt;
If you have used Roo or have done some interesting things with a Roo project please get in contact. &amp;nbsp;I have yet to explore the AddOns or detailed more information on the workflow in a Roo project that goes from prototyping to real world application. &amp;nbsp;Get in contact and lets document some Best Practices for this awesome product.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-7925637476151120537?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Jdbyx_kYlpgg2jws8nDNZw9rkRY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jdbyx_kYlpgg2jws8nDNZw9rkRY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Jdbyx_kYlpgg2jws8nDNZw9rkRY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jdbyx_kYlpgg2jws8nDNZw9rkRY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/oUwwlpw2HH0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/7925637476151120537/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/09/spring-roo-120-with-gwt-and-google-app.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7925637476151120537?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7925637476151120537?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/oUwwlpw2HH0/spring-roo-120-with-gwt-and-google-app.html" title="Spring Roo 1.2.0 with GWT and Google App Engine" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/09/spring-roo-120-with-gwt-and-google-app.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEBRn8_cSp7ImA9WhdWE0k.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-7284423544793632142</id><published>2011-09-02T07:43:00.000-07:00</published><updated>2011-09-06T14:14:17.149-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-06T14:14:17.149-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="POM" /><category scheme="http://www.blogger.com/atom/ns#" term="Domain Objects" /><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><category scheme="http://www.blogger.com/atom/ns#" term="Dependencies" /><title>Including external dependencies in your Maven GWT project</title><content type="html">There are many variations on this problem but lets relate it to a concrete example. &amp;nbsp;Say perhaps you have a &amp;nbsp;series of domain objects that exist in a dependency jar, but you want to be able to serialize them and send them to the GWT client. &amp;nbsp;How do you serialize an object that doesn't already exist in your core GWT project?&lt;br /&gt;
&lt;br /&gt;
There are several steps required so lets take them in a logical order. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Step 1 : Ensure your objects are serializable&lt;/b&gt;&lt;br /&gt;
Two things required here:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Ensure your objects are implementing serializable.&lt;/li&gt;
&lt;li&gt;Ensure you have at least a no-argument private constructor.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
If you don't do these things your objects cannot be serialized and sent to the client.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 2 : Add a GWT Module XML File&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
In order to indicate to the GWT Compiler that this dependency is a GWT Compilable you need to tell it so. &amp;nbsp;Therefore you will need to add the &amp;lt;ModuleName&amp;gt;.gwt.xml file in the /src/main/resources folder of the external dependency.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="prettyprint"&gt;&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="s2"&gt;xml&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;version&lt;span class="s3"&gt;=&lt;/span&gt;&lt;span class="s4"&gt;"1.0"&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;encoding&lt;span class="s3"&gt;=&lt;/span&gt;&lt;span class="s4"&gt;"UTF-8"&lt;/span&gt;&lt;span class="s1"&gt;?&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;rename-to&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"DependencyApi"&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&amp;nbsp; &lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;inherits&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;name&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"com.google.gwt.user.User"&lt;span class="s1"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s3"&gt;&amp;nbsp; &lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s5"&gt;path&lt;/span&gt;&lt;span class="s3"&gt;=&lt;/span&gt;"domainobjects"&lt;span class="s3"&gt; &lt;/span&gt;&lt;span class="s1"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p3"&gt;
&lt;/div&gt;
&lt;div class="p4"&gt;
&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;module&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In the above example "domainobjects" is the root package that you want serialized. &amp;nbsp;Similar to how a lot of GWT projects are constructed where you see a client and shared entry.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Step 3 : Export the dependency source&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
In order for the GWT-Compiler to compile to javascript it needs access to the source files, therefore as part of the dependencies build process you need to tell it to export the source. &amp;nbsp;An entry similar to the one below in your pom file should do it.&lt;/div&gt;
&lt;pre class="prettyprint"&gt;&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;build&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;plugins&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;plugin&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s3"&gt;groupId&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="s3"&gt;groupId&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s3"&gt;artifactId&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s4"&gt;maven&lt;/span&gt;-source-&lt;span class="s4"&gt;plugin&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="s3"&gt;artifactId&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;version&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;2.1.2&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;version&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;executions&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;execution&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s3"&gt;id&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;attach-sources&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="s3"&gt;id&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s3"&gt;goals&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s3"&gt;goal&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;jar&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="s3"&gt;goal&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="s3"&gt;goals&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;execution&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;executions&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;plugin&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;plugins&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;build&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;/pre&gt;
&lt;b&gt;Step 4 : Tell the GWT Compiler to add this dependency to the GWT Compile process&lt;/b&gt;
&lt;br /&gt;
&lt;div&gt;
In the main GWT Project's pom file you need to tell it to now use this dependency and combine its source into the compilation process. &amp;nbsp;This is achieved using the GWT-Maven-Plugin's configuration section.&lt;/div&gt;
&lt;pre class="prettyprint"&gt;&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;configuration&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;compileSourcesArtifacts&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s3"&gt;artifact&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&amp;lt;group id&amp;gt;:&amp;lt;artifactid&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="s3"&gt;artifact&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="p1"&gt;
&lt;span class="s2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="Apple-tab-span"&gt;	&lt;/span&gt;&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;compileSourcesArtifacts&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span class="s1"&gt;&amp;lt;/&lt;/span&gt;configuration&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;/pre&gt;
&lt;pre class="prettyprint"&gt;&lt;b style="font-family: Times; white-space: normal;"&gt;Step 5: Include reference in the main Web Application Module.gwt.xml&lt;/b&gt;&lt;/pre&gt;
&lt;pre class="prettyprint"&gt;&lt;span style="font-family: Times; white-space: normal;"&gt;Ensure you have a reference to the dependency in your main GWT Application config file.&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="prettyprint"&gt;&lt;div class="p1"&gt;
&lt;span class="s1"&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;!-- Dependency API --&amp;gt;&lt;/div&gt;
&lt;div class="p2"&gt;
&lt;span class="s1"&gt;&amp;nbsp; &lt;/span&gt;&lt;span class="s3"&gt;&amp;lt;&lt;/span&gt;&lt;span class="s4"&gt;inherits&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="s5"&gt;name&lt;/span&gt;&lt;span class="s1"&gt;=&lt;/span&gt;'com.acme.com.DependencyApi'&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="s3"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/pre&gt;
&lt;pre class="prettyprint"&gt;&lt;b style="font-family: Times; white-space: normal;"&gt;Summary&lt;/b&gt;&lt;/pre&gt;
&lt;div&gt;
Et Voila. &amp;nbsp;That is it complete. &amp;nbsp;A logical but not completely obvious solution to intermediate Maven users like myself. &amp;nbsp;I would love to hear from the community how they might have solved this problem.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-7284423544793632142?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FLEKoF2e2nIxV-pYV5j1pQAwJv8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FLEKoF2e2nIxV-pYV5j1pQAwJv8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FLEKoF2e2nIxV-pYV5j1pQAwJv8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FLEKoF2e2nIxV-pYV5j1pQAwJv8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/iODta1rmpcc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/7284423544793632142/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/09/including-external-dependencies-in-your.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7284423544793632142?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7284423544793632142?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/iODta1rmpcc/including-external-dependencies-in-your.html" title="Including external dependencies in your Maven GWT project" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>0</thr:total><georss:featurename>Seattle, WA, USA</georss:featurename><georss:point>47.6062095 -122.3320708</georss:point><georss:box>47.43492 -122.64792779999999 47.777499 -122.0162138</georss:box><feedburner:origLink>http://www.gwtsushi.info/2011/09/including-external-dependencies-in-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEHSHYyeip7ImA9WhdSFk4.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-5568084341416762835</id><published>2011-07-25T17:03:00.000-07:00</published><updated>2011-07-25T17:03:59.892-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-25T17:03:59.892-07:00</app:edited><title>Do you need a Java GWT developer?</title><content type="html">This is an open post to anyone that may require a GWT / Java Developer. &amp;nbsp;I am the author of this blog and am currently looking for work either in a telecommute role or based in my hometown of the sunny Seattle, Washington. &lt;br /&gt;
&lt;br /&gt;
I have over 10 years development experience and have worked for a wide variety of institutions large and small. I enjoy working in Agile teams and adopting a test driven methodology. &amp;nbsp;Having said that I am an expert at fitting into any team and have great references.&lt;br /&gt;
&lt;br /&gt;
If you know of anyone that needs a GWT developer, please get in touch.&lt;br /&gt;
&lt;br /&gt;
Regards&lt;br /&gt;
Gene&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-5568084341416762835?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5BTFJsJukzeUmDC6UihDPyjUgSQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5BTFJsJukzeUmDC6UihDPyjUgSQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5BTFJsJukzeUmDC6UihDPyjUgSQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5BTFJsJukzeUmDC6UihDPyjUgSQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/K94fz1LcKAA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/5568084341416762835/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/07/do-you-need-java-gwt-developer.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/5568084341416762835?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/5568084341416762835?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/K94fz1LcKAA/do-you-need-java-gwt-developer.html" title="Do you need a Java GWT developer?" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>3</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/07/do-you-need-java-gwt-developer.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUHQ3o5cCp7ImA9WhZWFUQ.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-8300361830742486260</id><published>2011-05-13T13:37:00.001-07:00</published><updated>2011-05-16T18:37:12.428-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-16T18:37:12.428-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="framework" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="POJO" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="XML" /><category scheme="http://www.blogger.com/atom/ns#" term="Piriti" /><title>XML to POJO Mapper for GWT using a GDATA Example with Google Contacts (ContactEntry).</title><content type="html">&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=gwtsu-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=1590597060&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="align: left; height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;If your like me I dislike cowboy coding.&amp;nbsp; You are hacking away at something to get the job done, but the nagging thought at the back of your head is telling you "You kow you shouldn't be doing this".&amp;nbsp; The best path maybe unavailable because a lack of experience, or perhaps we are unaware of suitable boilerplate-removing framework.&amp;nbsp; We've all been there time is in the essence, deadlines are pressing and your new TPS Reports Engine needs to be delivered yesterday.&amp;nbsp; Well I found myself in such a quandry recently and found a tool which will solve a common problem for many GWT developers. So instead of waffling what actually is the problem?&lt;br /&gt;
&lt;br /&gt;
Imagine an application that communicates with Google Contacts.&amp;nbsp; Server-side you receive a an atom-rss feed representation of a contact in the form of a ContactEntry object.&amp;nbsp; Google kindly provides you with GData POJOs which are already populated with the information you require.&amp;nbsp; On the server this is beautiful, Google has done all the hard work and the POJO is populated with data.&amp;nbsp; If you were using the wonderful Spring MVC you could render the contact information very easily.&amp;nbsp; However you are a profound, if not magical developer that has the GWT Swiss army knife in their toolkit, and you want to send this POJO to the client.&amp;nbsp; In the words of Mr. J. Carrey you reach the Alrighty Then brick wall of stoppage.&amp;nbsp; The ContactEntry POJO is not serializable to the client.&amp;nbsp; Or is it?&lt;br /&gt;
&lt;br /&gt;
One giant caveat is that I maybe encountering a newbie problem and someone may have created an easy way to make GData objects serializable for sending over GWT-RPC, but at present the only way I have found to do it, is manually, i.e. boilerplatery.&amp;nbsp; Create my own ContactEntry objects on the server and populate them.&amp;nbsp; This obviously involves copious amounts of repetition.&amp;nbsp; It can be done this way, and is the way I have done it in the past, before I knew better, but it isn't efficient.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Lets recap:&amp;nbsp; We want a solution to send a GData ContactEntry object to the GWT client that we can use in a POJO, without becoming America's best plumber to create all the additional boilerplate code.&lt;br /&gt;
&lt;br /&gt;
My proposed solution: &amp;nbsp;Send the XML as a String to the client and use a fancy GWT plugin, Piriti, XPath to auto populate a client side POJO. &amp;nbsp;Quick, efficient and maintainable. &amp;nbsp;So how do we do this?&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Caveat: &amp;nbsp;If someone has a better way of doing this please let me know. &amp;nbsp;I am all ears.&amp;nbsp; This may not be the best solution and I would love to know how anyone else has tackled this issue.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Step 1: Extract XML&lt;/b&gt;&lt;br /&gt;
Lets assume you know how to get the ContactEntry from Google using their GData library but now you want to convert that into XML to transport to the GWT Client:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public String getContactEntryXml(ContactEntry entry) {
StringWriter sw = new StringWriter();
String entryXml = "";
try {
XmlWriter xw = new XmlWriter(sw);
entry.generate(xw, contactServiceFactory.getBasicContactsService().getExtensionProfile());
entryXml = sw.toString();
} catch (IOException e) {
e.printStackTrace();
}

return entryXml; // sw.toString();
}
&lt;/pre&gt;&lt;b&gt;Step 2: Transfer to Client&lt;/b&gt;&lt;br /&gt;
I am assuming you know how to write GWT applications and communicate back and forther between the server and client. &amp;nbsp;There are man built in libraries to do this, GWT RPC, Request Factory, and may external third party modules; net.customware.gwt.dispatch, GWTP etc.&lt;br /&gt;
&lt;b&gt;Step 3: Create POJO&lt;/b&gt;&lt;br /&gt;
The key here is reaally the library we are going to use. &amp;nbsp;After looking at many examples I am using Piriti's library. &amp;nbsp;It appears to be well used and has good documentation:&amp;nbsp;&lt;a href="http://code.google.com/p/piriti/" title="http://code.google.com/p/piriti/"&gt;http://code.google.com/p/piriti/&lt;/a&gt;&lt;br /&gt;
&lt;blockquote&gt;Piriti (&lt;a href="http://www.maoridictionary.co.nz/index.cfm?dictionaryKeywords=bridge" rel="nofollow"&gt;Maori for "bridge"&lt;/a&gt;)  is a JSON and XML mapper for GWT based on annotations and deferred  binding. The following code snippets show the basic idea behind Piriti. &amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;So create a POJO and add these lines to the top of your POJO class:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class ContactEntrySoho {

public static interface ContactEntrySohoReader extends XmlReader { }
public static final ContactEntrySohoReader XML = GWT.create(ContactEntrySohoReader.class);
&lt;/pre&gt;These lines are used when mapping the POJO members to their XML nodes.&lt;br /&gt;
&lt;b&gt;Step 4 : Map atom:title to an instance member&lt;/b&gt;&lt;br /&gt;
Let's start easy lets map the atom:title entry of the ContactEntry XML. &amp;nbsp;First it is probably worth taking a look a the XML:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;atom:title type='text'&amp;gt;Alan UserA1&amp;lt;/atom:title&amp;gt;
&lt;/pre&gt;Now lets look at how we would map this using XPath in the Pojo:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@Path("atom:title") private String title;
&lt;/pre&gt;For a more in-depth view of XPath look online for various cheat-sheets and tutorials it is very powerful and very useful.&lt;br /&gt;
&lt;b&gt;Step 5 : Load the Pojo&lt;/b&gt;&lt;br /&gt;
All we need to do now is load the POJO with information to do this see the below:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@Override
public ContactEntrySoho parse(String xml) {
try {

Map&amp;lt;String, String&amp;gt; namespaces = new HashMap&amp;lt;String, String&amp;gt;();
namespaces.put("atom", "http://www.w3.org/2005/Atom");
namespaces.put("gContact", "http://schemas.google.com/contact/2008");
namespaces.put("batch", "http://schemas.google.com/gdata/batch");
namespaces.put("gd", "http://schemas.google.com/g/2005");
Document doc = new XmlParser().parse(xml, namespaces);

//Document doc = new XmlParser().parse(xml, NAMESPACES);
ContactEntrySoho sContactEntry = ContactEntrySoho.XML.read(doc);
return sContactEntry;

} catch (Exception e) {
return null;
}
}
&lt;/pre&gt;The namespaces tell the parser what the tag mean and correspond to the root note elements of the ContactEntry XML:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;atom:entry xmlns:atom='http://www.w3.org/2005/Atom' 

xmlns:gContact='http://schemas.google.com/contact/2008'  

xmlns:batch='http://schemas.google.com/gdata/batch' 

xmlns:gd='http://schemas.google.com/g/2005'&amp;gt;
&lt;/pre&gt;Remember those additions we added to the POJO we simply call those (XML.read) to parse the xml Document. &amp;nbsp;Et Voila! &amp;nbsp;You have your own POJO created with hatever components from the XML you require.&lt;br /&gt;
&lt;b&gt;Step 6 : A more complex example please sir.&lt;/b&gt;&lt;br /&gt;
As you can see I have chosen the easiest node to map and as all articles which only go into the most basic of examples infuriate me, I shan't do the same here. &amp;nbsp;Let's take a look at an example where we need to map to another POJO. &amp;nbsp;Take the StructuredPostalAddress component of the ContactEntry class.&lt;br /&gt;
The XML in ContactEntry:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&amp;lt;gd:structuredPostalAddress primary='false' rel='http://schemas.google.com/g/2005#home'&amp;gt;
&amp;lt;gd:formattedAddress&amp;gt;6217 Woodlawn Ave N, Seattle, WA. 98103&amp;lt;/gd:formattedAddress&amp;gt;
&amp;lt;gd:street&amp;gt;1234 Acme Ave N&amp;lt;/gd:street&amp;gt;
&amp;lt;gd:postcode&amp;gt;11111&amp;lt;/gd:postcode&amp;gt;
&amp;lt;gd:city&amp;gt;Seattle&amp;lt;/gd:city&amp;gt;
&amp;lt;gd:region&amp;gt;WA.&amp;lt;/gd:region&amp;gt;
&amp;lt;/gd:structuredPostalAddress&amp;gt;
&lt;/pre&gt;The data in  our parent ContactEntrySoho class:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@Path("//gd:structuredPostalAddress") private List&amp;lt;GDStructuredPostalAddress&amp;gt; gdStructuredPostalAddresses;
&lt;/pre&gt;Wait what is GDStructuredPostalAddress?  This is another POJO with the headers defined in Step 3.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class GDStructuredPostalAddress extends ABaseElement{

public interface GDStructuredPostalAddressXmlReader extends XmlReader&amp;lt;GDStructuredPostalAddress&amp;gt; {}
public static final GDStructuredPostalAddressXmlReader XML = GWT.create(GDStructuredPostalAddressXmlReader.class);

@Path("gd:formattedAddress") private String formattedAddress;
@Path("gd:street") private String street;
@Path("gd:postcode") private String postcode;
@Path("gd:city") private String city;
@Path("gd:region") private String region;
&lt;/pre&gt;Et Voila!  I found when using this that the POJO members sometimes had to be public otherwise they wouldn't populate but this problem was intermittent, so I am unsure whether this is an issue with Piriti's excellent XML-&amp;gt;POJO Mapper or my inept code ;).&lt;br /&gt;
I would love to hear how other people are doing this as this seems like a good solution but I am sure there are many others.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-8300361830742486260?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/po8hxHOpudvpcl5TOxN8-0-b8ls/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/po8hxHOpudvpcl5TOxN8-0-b8ls/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/po8hxHOpudvpcl5TOxN8-0-b8ls/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/po8hxHOpudvpcl5TOxN8-0-b8ls/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/G_LESwxdxJ4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/8300361830742486260/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/05/xml-to-pojo-mapper-for-gwt-using-gdata.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8300361830742486260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8300361830742486260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/G_LESwxdxJ4/xml-to-pojo-mapper-for-gwt-using-gdata.html" title="XML to POJO Mapper for GWT using a GDATA Example with Google Contacts (ContactEntry)." /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/05/xml-to-pojo-mapper-for-gwt-using-gdata.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcCRHs_cCp7ImA9Wx9aF0o.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-8391196927773499854</id><published>2011-03-10T09:09:00.001-08:00</published><updated>2011-03-10T09:11:05.548-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-10T09:11:05.548-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><title>Excellent GIT Cheat Sheet</title><content type="html">&lt;p&gt;If your like me and fairly new to Git but appreciate its awesomeness. &amp;nbsp;I have just found a great cheat sheet for GIT. &amp;nbsp;Both clear, logical and concise get the sheet here: &amp;nbsp;&amp;nbsp;&lt;a href="http://cheat.errtheblog.com/s/git/"&gt;Your link text here.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This website appears to be a collection of clear cheat sheets so go fill your boots people!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-8391196927773499854?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XAmIx9NM0MTUAfyUgoDfo12cuKA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XAmIx9NM0MTUAfyUgoDfo12cuKA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XAmIx9NM0MTUAfyUgoDfo12cuKA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XAmIx9NM0MTUAfyUgoDfo12cuKA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/3swgSVQ9hKM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/8391196927773499854/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/03/excellent-git-cheat-sheet.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8391196927773499854?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8391196927773499854?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/3swgSVQ9hKM/excellent-git-cheat-sheet.html" title="Excellent GIT Cheat Sheet" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/03/excellent-git-cheat-sheet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIDSXc8fSp7ImA9Wx9aFU4.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-175510168005612645</id><published>2011-03-07T13:32:00.000-08:00</published><updated>2011-03-07T13:32:58.975-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-07T13:32:58.975-08:00</app:edited><title>Jumpstart your GWT Development with JappStart</title><content type="html">I am currently experimenting with the JappStart framework, well not really a framework, but a beginner project that integrates many interesting technologies, all of which have been nicely converted and are ready to perform on Google App Engine. &amp;nbsp;It has many features including:&lt;br /&gt;
&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: arial, sans-serif; font-size: 13px;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul style="max-width: 65em; padding-left: 40px;"&gt;&lt;li&gt;Appstats Support&lt;/li&gt;
&lt;li&gt;Google AJAX Library API (jQuery)&lt;/li&gt;
&lt;li&gt;Gravatar Integration&lt;/li&gt;
&lt;li&gt;JRebel Support&lt;/li&gt;
&lt;li&gt;Local Development Console Support (&lt;a href="http://localhost:8080/_ah/admin" rel="nofollow" style="color: #0000cc;"&gt;http://localhost:8080/_ah/admin&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Maven Support&lt;/li&gt;
&lt;ul style="max-width: 65em; padding-left: 40px;"&gt;&lt;li&gt;CSS/JS minification via the yuicompressor-maven-plugin&lt;/li&gt;
&lt;li&gt;Uses the maven-gae-plugin&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Remote API/Bulk Loader Support&lt;/li&gt;
&lt;li&gt;Sitemesh Integration&lt;/li&gt;
&lt;li&gt;Spring 3&lt;/li&gt;
&lt;ul style="max-width: 65em; padding-left: 40px;"&gt;&lt;li&gt;JPA support&lt;/li&gt;
&lt;li&gt;JSON/AJAX integration (Jackson)&lt;/li&gt;
&lt;li&gt;JSR-303 validation&lt;/li&gt;
&lt;li&gt;Localization support&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Spring Security 3&lt;/li&gt;
&lt;ul style="max-width: 65em; padding-left: 40px;"&gt;&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Expression based access control&lt;/li&gt;
&lt;li&gt;Fully integrated with the App Engine Datastore and Memcache&lt;/li&gt;
&lt;li&gt;Login/create account functionality with e-mail confirmation&lt;/li&gt;
&lt;li&gt;Remember Me&lt;/li&gt;
&lt;li&gt;Support for hierarchical roles&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Static Error Handler Support&lt;/li&gt;
&lt;li&gt;Task Queue Support&lt;/li&gt;
&lt;li&gt;URL Rewrite Integration&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Current versions:&lt;br /&gt;
&lt;ul style="max-width: 65em; padding-left: 40px;"&gt;&lt;li&gt;Goole App Engine SDK for Java 1.4.2&lt;/li&gt;
&lt;li&gt;jQuery 1.5.0&lt;/li&gt;
&lt;li&gt;Maven GAE Plugin 0.8.2&lt;/li&gt;
&lt;li&gt;Spring 3.0.5&lt;/li&gt;
&lt;li&gt;Spring Security 3.0.5&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
As you can see it covers a lot of bases so you can get started easily on developing professional Google App Engine applications. &amp;nbsp;I am examining it so I can also integrate GWT and MVP. &amp;nbsp;Stay tuned for a demo project coming soon.&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;JappStart Home Page:&amp;nbsp;&lt;a href="http://code.google.com/p/jappstart/"&gt;http://code.google.com/p/jappstart/&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-175510168005612645?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ECCWk5_eGEXxwoMHItXGoK1k4cI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ECCWk5_eGEXxwoMHItXGoK1k4cI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ECCWk5_eGEXxwoMHItXGoK1k4cI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ECCWk5_eGEXxwoMHItXGoK1k4cI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/b_Ww2gnCIMU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/175510168005612645/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/03/jumpstart-your-gwt-development-with.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/175510168005612645?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/175510168005612645?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/b_Ww2gnCIMU/jumpstart-your-gwt-development-with.html" title="Jumpstart your GWT Development with JappStart" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/03/jumpstart-your-gwt-development-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYBSXc7eSp7ImA9Wx9WGUQ.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-3353865710867794491</id><published>2011-01-25T14:22:00.000-08:00</published><updated>2011-01-25T14:22:38.901-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-25T14:22:38.901-08:00</app:edited><title>Google I/O 2011</title><content type="html">Google IO 2011 Site is up and running.  If your going and want to hook up please let me know.&lt;br /&gt;&lt;a href="http://www.google.com/events/io/2011/about.html"&gt;Google I/O 2011&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-3353865710867794491?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2dqY5rF51TgN8ITvIOBkVtaB5DE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2dqY5rF51TgN8ITvIOBkVtaB5DE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2dqY5rF51TgN8ITvIOBkVtaB5DE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2dqY5rF51TgN8ITvIOBkVtaB5DE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/9-gkXJOvgxA" height="1" width="1"/&gt;</content><link rel="related" href="http://www.google.com/events/io/2011/about.html" title="Google I/O 2011" /><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/3353865710867794491/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/01/google-io-2011.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3353865710867794491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3353865710867794491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/9-gkXJOvgxA/google-io-2011.html" title="Google I/O 2011" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/01/google-io-2011.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QNSXw9eSp7ImA9Wx9WGU4.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-7621715680926556938</id><published>2011-01-24T20:53:00.000-08:00</published><updated>2011-01-24T20:56:38.261-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-24T20:56:38.261-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GUICE" /><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="GIN" /><category scheme="http://www.blogger.com/atom/ns#" term="DI" /><category scheme="http://www.blogger.com/atom/ns#" term="Inversion of Control" /><title>Using Gin-Guice With Java Generics (Cell Table/DAO Example)</title><content type="html">Last year was so interesting and I have discovered so many interesting methods, ideas, patterns, and frameworks for developing professional software. &amp;nbsp;A big proportion of this learning curve has been embracing Test-Driven Development and the necessary changes required to the structure of your code. &amp;nbsp;One design pattern is the Dependency-Injection (DI) pattern where an objects dependencies are injected into the constructor. &amp;nbsp;This allows us to clearly see what the dependencies of an object are, and using a framework allows us to inject our implemented classes. &amp;nbsp;Spring offers a DI framework, which I hope to experiment at some point, but for now, and because many of the Google GWT examples use it, I am using Google GIN on the client side GWT projects and Google GUICE on the server.&lt;br /&gt;
&lt;br /&gt;
Explaining Generics is a little more complicated and I defer to someone more experienced. &amp;nbsp;So a quick web search yields this:&lt;br /&gt;
&lt;blockquote&gt;&lt;i&gt;"Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection."&lt;/i&gt;&lt;/blockquote&gt;Now here comes the tricky part. &amp;nbsp;&lt;b&gt;How do we inject a generic type class using Gin/Guice?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;I always like to lead by example so lets talk about the example used here. &amp;nbsp;Imagine you have a base class for all of your tables you are gong to render. &amp;nbsp;However depending on the annotation used where you inject the base table, then that dictates what the type of the generic class used. &amp;nbsp;In addition the annotation decides what ColumnFormatter class is used to render table. &amp;nbsp;So in summary:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;1 Base Class SohoTable&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;li&gt;Several ColumnFormatter classes depending on table used.&lt;/li&gt;
&lt;/ul&gt;&lt;b&gt;Declaration of SohoTable&lt;/b&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class SohoTable&amp;lt;T extends HasReadId&amp;gt; extends Composite implements
  HasEventBus, HasTableChangedEventHandler {
&lt;/pre&gt;&lt;pre class="prettyprint"&gt;@Inject
public SohoTable(ColumnFormatter columnFormatter) {
&lt;/pre&gt;&lt;br /&gt;
Here the base class shows the generics declaration. &amp;nbsp;Here you can replace HasReadId with any interface your common DAOs implement. &amp;nbsp;For simplicity we just ensure that HasReadId has a method to get the unique Id of the row.&lt;br /&gt;
&lt;br /&gt;
The constructor requires a ColumnFormatter implementation for the DAO object you are creating. &amp;nbsp; This is a little abstract, so hold off your questions until later.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ContactColumnFormatter&lt;/b&gt;&lt;br /&gt;
let us dig deeper into a real implementation. &amp;nbsp;So we have a table of Contacts which we are going to use the generic base class for therefore we need to create this class and implement the ColumnFormatter.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class ContactColumnFormatter extends ColumnFormatter {
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Create the annotation&lt;/b&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@BindingAnnotation
public @interface ContactTableAnnot {

}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Ginjector&lt;/b&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;SohoTable&lt;contact&gt; getSohoTableOfContact();
&lt;/contact&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Create the ContactTableProvider&lt;/b&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class ContactTableProvider implements Provider&amp;lt;SohoTable&amp;lt;Contact&amp;gt;&amp;gt;{

 private final Provider&amp;lt;ContactColumnFormatter&amp;gt; providerFormatter;

 @Inject
 public ContactTableProvider(Provider&amp;lt;ContactColumnFormatter&amp;gt; providerFormatter) {
  this.providerFormatter = providerFormatter;
 }

 @Override
 public SohoTable&amp;lt;Contact&amp;gt; get() {
  return new SohoTable&amp;lt;Contact&amp;gt;(providerFormatter.get());
 }

}
&lt;/pre&gt;Here we inject the correct ColumnFormatter for the Contact table.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Wire up the classes in the ClientModule (AbstractGinModule)&lt;/b&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;bind(ContactColumnFormatter.class);
bind(ContactTableProvider.class);
bind(new TypeLiteral&amp;lt;SohoTable&amp;lt;? extends HasReadId&amp;gt;&amp;gt;(){}).annotatedWith(ContactTableAnnot.class).toProvider(ContactTableProvider.class);
&lt;/pre&gt;This is where we where the main action takes place.  All the subclasses are wired up.  The final line is the cool one.  We need to use a TypeLiteral in order to wire up the generic elements.  The annotated item shows how to wire up the annotation with the correct provider.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;This is all very good but how do I use it?&lt;/b&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@UiField(provided = true)
SohoTable&amp;lt;Contact&amp;gt; contactTable;

@Inject
public RolodexView(@ContactTableAnnot SohoTable&amp;lt;? extends HasReadId&amp;gt; contactTable) {
  this.contactTable = (SohoTable&amp;lt;Contact&amp;gt;) contactTable;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-7621715680926556938?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/e1z0xRdUi_0ERdjcipQKNkb8Cxk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e1z0xRdUi_0ERdjcipQKNkb8Cxk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/e1z0xRdUi_0ERdjcipQKNkb8Cxk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e1z0xRdUi_0ERdjcipQKNkb8Cxk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/-nKx9XcLhf4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/7621715680926556938/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/01/using-gin-guice-with-java-generics.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7621715680926556938?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7621715680926556938?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/-nKx9XcLhf4/using-gin-guice-with-java-generics.html" title="Using Gin-Guice With Java Generics (Cell Table/DAO Example)" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/01/using-gin-guice-with-java-generics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8CR3g6fCp7ImA9Wx9aF0o.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-3222733653559011525</id><published>2011-01-10T19:46:00.000-08:00</published><updated>2011-03-10T09:07:46.614-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-10T09:07:46.614-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="GWTP" /><category scheme="http://www.blogger.com/atom/ns#" term="article" /><category scheme="http://www.blogger.com/atom/ns#" term="review" /><title>A personal review of GWT for 2010</title><content type="html">&lt;p&gt;2010 has been an exciting year and I wanted to thank everyone who commented, got in touch and generally helped out. &amp;nbsp;A big thankyou goes out to the people at &lt;a href="http://code.google.com/p/gwt-platform/" target="_blank"&gt;GWTP project&lt;/a&gt;. &amp;nbsp;Philippe and Christian thanks for all your help in utilising the framework in my example application.&lt;/p&gt;&lt;p&gt;The year started with a change of career. &amp;nbsp;For the past 15 years I have primarily been a Microsoft developer working for various commercial interests in London, Iceland, and now the USA. &amp;nbsp;Currently living in Seattle, the Gaceland for computer programmers, or as we are now known Software Engineers, I decided that it was time to change my career track and learn a proper programming language (let the flame wars begin). &amp;nbsp;&lt;/p&gt;&lt;p&gt;I am now sure whether I particularly dislike Windows, or whether I just needed a change of scenery but the Microsoft programming platform doesn't jive with my liberal view on life. &amp;nbsp;I always wanted to learn an open source language, partly because I am an academic at heart and partly t stick it to the man. &amp;nbsp;So the scene was set, and the only real option was to learn the current professional language de jour, JAVA.&lt;/p&gt;&lt;p&gt;One thing I also failed to mention was my love of Google. &amp;nbsp;Any company which adopts open source as much as they have means they have to be admired in some way. &amp;nbsp;Computer Programming tools are not proprietary systems. They are ideas that should be shared with everyone, in the same way that the cure for Malaria, will one day hopefully. &amp;nbsp;I am not saying that all software built with open source tools should not be commercial far from it. &amp;nbsp;But the ideas and tools we use should be at their core.&lt;/p&gt;&lt;p&gt;So I was learning Java and has a long term ASP.Net developer was looking for something that improved my programming environment. &amp;nbsp;Google App Engine was the first oh wow moment three years ago, where I thought, this takes all the hassle out of programming. &amp;nbsp;Then when I discovered Google Web Toolkit and what that actually means for feature rich internet applications. &amp;nbsp;I thought oh wow oh wow.&lt;/p&gt;&lt;p&gt;So for the past year I have been learning Java with GWT on GAE. &amp;nbsp;I learn best by example and building a contact application was the best way forward. &amp;nbsp;I have a passion for helping small businesses and developing software which is functionally logical. &amp;nbsp;So much software is plain old bad. &amp;nbsp;GWT liberates the developer to programme professionally at all levels in the stack, thus improving and professionalising their daily routine. &amp;nbsp;Google continues to build on this great architecture by partnering with Spring and Roo, to introduce Rapid Application Development tools. &amp;nbsp;Plus they continue to enhance and develop the library. &amp;nbsp;Speed Tracer looks awesome, performance tuning built in on the server and client side. &amp;nbsp;Need I say more. &amp;nbsp;Google needs to be congratulated for this piece of kit because it has improved my development daily routine no end.&lt;/p&gt;&lt;p&gt;Where am I now? &amp;nbsp;Well on the basis of my skills developed during the past year I have landed a job with a startup, doing yes you guessed it... &amp;nbsp;Java-GWT development. &amp;nbsp;2011 continues to be exciting. &amp;nbsp;I also transferred to a Mac which I have been wanting to do for ages, and with the launch of this new career it will help me do so. &amp;nbsp;Here is to 2011. &amp;nbsp;&lt;/p&gt;&lt;p&gt;Continue to read, continue to ask questions, and lets have a great 2011.&lt;/p&gt;&lt;p&gt;&lt;a href="http://cheat.errtheblog.com/s/git/"&gt;Your link text here.&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-3222733653559011525?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BTbaVSVAxKQgVNwuzTB674W1J7s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BTbaVSVAxKQgVNwuzTB674W1J7s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BTbaVSVAxKQgVNwuzTB674W1J7s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BTbaVSVAxKQgVNwuzTB674W1J7s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/zMR30nYeDgk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/3222733653559011525/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2011/01/2010-in-review.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3222733653559011525?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3222733653559011525?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/zMR30nYeDgk/2010-in-review.html" title="A personal review of GWT for 2010" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>3</thr:total><feedburner:origLink>http://www.gwtsushi.info/2011/01/2010-in-review.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4ERHozcCp7ImA9WhZWE08.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-1235813432828191515</id><published>2010-12-12T20:08:00.001-08:00</published><updated>2011-05-13T15:15:05.488-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-13T15:15:05.488-07:00</app:edited><title>CellTable Examples</title><content type="html">&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=gwtsu-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=0321705149&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="align: left; height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;Over the last few weeks I thought it was high time to experiment with the new Data Presentation widgets released in GWT version 2.1.&amp;nbsp; It has been an interesting experience to say the least and as my life motto goes it is a journey not the destination.&amp;nbsp; Anyhow I came across a particularly good collection of CellTable examples that I wanted to share.&amp;nbsp; See this link for details:&lt;br /&gt;
&lt;a href="http://stackoverflow.com/questions/2891803/how-to-use-gwt-2-1-data-presentation-widgets"&gt;http://stackoverflow.com/questions/2891803/how-to-use-gwt-2-1-data-presentation-widgets&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-1235813432828191515?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4a4ouWAgdKfWE9ZSx4Hpsd-JrJ8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4a4ouWAgdKfWE9ZSx4Hpsd-JrJ8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4a4ouWAgdKfWE9ZSx4Hpsd-JrJ8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4a4ouWAgdKfWE9ZSx4Hpsd-JrJ8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/l-4IQ_H_-yU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/1235813432828191515/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/12/celltable-examples.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/1235813432828191515?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/1235813432828191515?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/l-4IQ_H_-yU/celltable-examples.html" title="CellTable Examples" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/12/celltable-examples.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUGRX05eSp7ImA9Wx5aFEQ.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-6003086059966004755</id><published>2010-11-11T09:57:00.001-08:00</published><updated>2010-11-11T09:57:04.321-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-11T09:57:04.321-08:00</app:edited><title>Conditional Logic and GUICE</title><content type="html">&lt;p&gt;For &lt;a href="http://www.google.com/enterprise/marketplace/viewListing?productListingId=1940+4324839027261926410" target="_blank"&gt;Contact Personal Assistant&lt;/a&gt; I am using GUICE.&amp;nbsp;&amp;nbsp; After being introduced to Dependency Injection, or Inversion of Control, I appreciate its awesomeness, if I don’t fully understand it.&amp;nbsp; One of my main issues with fully adopting this paradigm shift, has been the usual barrage of questions a developer asks and answers in their own head in a daily basis, and the main one for me so far was.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;How do I implement a conditional logic for an implementation instance based on runtime parameters?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Sounds a little abstract, I know.&amp;nbsp; So lets try an example.&amp;nbsp; Imagine you have a control which renders some information from a IDataServer interface but at runtime you have several Implementations of the IDataServer interface to chose from.&lt;/p&gt; &lt;p&gt;I have thought of many ways this could be achieved, but have known, them all to be hacky, my implementation based on how I currently understand GUICE, and trying to fit it into what I require.&amp;nbsp; As they say with great power comes great responsibility, and I want to use this framework correctly, not in hacked way that I can get it to work given my current level of knowledge.&lt;/p&gt; &lt;p&gt;It turns out the solution is as simple as it is beautiful:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;USE MAP BINDER!&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Luckily the answer is discussed on this &lt;a href="http://groups.google.com/group/google-guice/browse_thread/thread/3a452d6d7b1acf35/1c95de1d9366819b?lnk=gst&amp;amp;q=conditional#1c95de1d9366819b" target="_blank"&gt;thread&lt;/a&gt; which I replicate here:&amp;nbsp;&amp;nbsp; &lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CalculatorModule extends AbstractModule { &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;   &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; configure() { &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;     MapBinder&amp;lt;Types, Class&amp;lt;ICalculator&amp;gt;&amp;gt; mapbinder &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;         = MapBinder.newMapBinder(binder(), Types.&lt;span class="kwrd"&gt;class&lt;/span&gt;, &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;ICalculator.&lt;span class="kwrd"&gt;class&lt;/span&gt;); &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;     mapbinder.addBinding(Types.A).toInstance(ACalculator.&lt;span class="kwrd"&gt;class&lt;/span&gt;); &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;     mapbinder.addBinding(Types.B).toInstance(BCalculator.&lt;span class="kwrd"&gt;class&lt;/span&gt;); &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;     mapbinder.addBinding(Types.C).toInstance(CCalculator.&lt;span class="kwrd"&gt;class&lt;/span&gt;); &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;   } &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt; } &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;@Singleton &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CalculatorFactory { &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; final Injector injector; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; final Map&amp;lt;Types, Class&amp;lt;Calculator&amp;gt;&amp;gt; calculators; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;   @Inject &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; CalculatorFactory(Injector injector, Map&amp;lt;Types, &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;Class&amp;lt;Calculator&amp;gt;&amp;gt; calculators) { &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.injector = injector; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.calculators = calculators; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    } &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; ICalculator create(UserGroup group) { &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;         injector.getInstance(calculators.get(group.getType)); &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;    } &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;} &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This example uses a calculator factory to allow the user to select whether they want implementation A, B or C.&amp;nbsp; Simply inject the calculator factory into whichever class requires it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Beautiful!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-6003086059966004755?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/w01ni__ae8L8ZH3FfkmsiakpH1o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/w01ni__ae8L8ZH3FfkmsiakpH1o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/w01ni__ae8L8ZH3FfkmsiakpH1o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/w01ni__ae8L8ZH3FfkmsiakpH1o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/X9ZySrSPhNU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/6003086059966004755/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/11/conditional-logic-and-guice.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/6003086059966004755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/6003086059966004755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/X9ZySrSPhNU/conditional-logic-and-guice.html" title="Conditional Logic and GUICE" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/11/conditional-logic-and-guice.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYDSXk7eip7ImA9Wx5bGE8.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-3593965429228616419</id><published>2010-11-03T16:40:00.001-07:00</published><updated>2010-11-03T16:49:38.702-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-03T16:49:38.702-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="format" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="review" /><title>Code Formatting Live Writer Plugins.</title><content type="html">&lt;p&gt;That’s It!&amp;nbsp; I have had enough of my code snippets going awry when posting to the Blogger platform.&amp;nbsp; I typically use Live Writer to blog so I am now going to review the code syntax formatters and declare a winner.&amp;nbsp; Well my preferred formatter anyway.&amp;nbsp; The Live Writer plugins are:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Code Snippet&lt;/li&gt; &lt;li&gt;Insert Code&lt;/li&gt; &lt;li&gt;Source Code&lt;/li&gt; &lt;li&gt;Source Code (another one)&lt;/li&gt; &lt;li&gt;WintyCodeArea&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Lets take a look at how they format the same bit of code.&lt;/p&gt; &lt;h2&gt;Code Snippet&lt;/h2&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DynaTable implements EntryPoint {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; onModuleLoad() {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Find the slot for the calendar widget.&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     RootPanel slot = RootPanel.get(&lt;span style="color: #006080"&gt;"calendar"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (slot != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;       SchoolCalendarWidget calendar = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SchoolCalendarWidget(15);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;       slot.add(calendar);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;       &lt;span style="color: #008000"&gt;// Find the slot for the days filter widget.&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;       &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;       slot = RootPanel.get(&lt;span style="color: #006080"&gt;"days"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (slot != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         DayFilterWidget filter = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DayFilterWidget(calendar);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         slot.add(filter);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;       }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;   }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;Insert Code&lt;/h2&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DynaTable implements EntryPoint {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; onModuleLoad() {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="rem"&gt;// Find the slot for the calendar widget.&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="rem"&gt;//&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    RootPanel slot = RootPanel.get(&lt;span class="str"&gt;"calendar"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (slot != &lt;span class="kwrd"&gt;null&lt;/span&gt;) {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;      SchoolCalendarWidget calendar = &lt;span class="kwrd"&gt;new&lt;/span&gt; SchoolCalendarWidget(15);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;      slot.add(calendar);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;      &lt;span class="rem"&gt;// Find the slot for the days filter widget.&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;      &lt;span class="rem"&gt;//&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;      slot = RootPanel.get(&lt;span class="str"&gt;"days"&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;      &lt;span class="kwrd"&gt;if&lt;/span&gt; (slot != &lt;span class="kwrd"&gt;null&lt;/span&gt;) {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;        DayFilterWidget filter = &lt;span class="kwrd"&gt;new&lt;/span&gt; DayFilterWidget(calendar);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;        slot.add(filter);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;      }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;  }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Source Code (1)&lt;/h2&gt;&lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:5645ede1-ee85-4c60-98d5-08d2298af3af" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: java; gutter: true; first-line: 1; tab-size: 4;  toolbar: true;  width: 400px; height: 300px;" style=" width: 400px; height: 300px;overflow: auto;"&gt;public class DynaTable implements EntryPoint {&lt;br /&gt;&lt;br /&gt;  public void onModuleLoad() {&lt;br /&gt;    // Find the slot for the calendar widget.&lt;br /&gt;    //&lt;br /&gt;    RootPanel slot = RootPanel.get(&amp;quot;calendar&amp;quot;);&lt;br /&gt;    if (slot != null) {&lt;br /&gt;      SchoolCalendarWidget calendar = new SchoolCalendarWidget(15);&lt;br /&gt;      slot.add(calendar);&lt;br /&gt;&lt;br /&gt;      // Find the slot for the days filter widget.&lt;br /&gt;      //&lt;br /&gt;      slot = RootPanel.get(&amp;quot;days&amp;quot;);&lt;br /&gt;      if (slot != null) {&lt;br /&gt;        DayFilterWidget filter = new DayFilterWidget(calendar);&lt;br /&gt;        slot.add(filter);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;Source Code (2)&lt;/h2&gt;&lt;pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DynaTable &lt;span style="color: #0000ff"&gt;implements&lt;/span&gt; EntryPoint {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; onModuleLoad() {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #008000"&gt;// Find the slot for the calendar widget.&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    RootPanel slot = RootPanel.get("&lt;span style="color: #8b0000"&gt;calendar&lt;/span&gt;");&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (slot != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      SchoolCalendarWidget calendar = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SchoolCalendarWidget(15);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      slot.add(calendar);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      &lt;span style="color: #008000"&gt;// Find the slot for the days filter widget.&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      slot = RootPanel.get("&lt;span style="color: #8b0000"&gt;days&lt;/span&gt;");&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (slot != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        DayFilterWidget filter = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DayFilterWidget(calendar);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        slot.add(filter);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div class="mycode"&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="mycode"&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="mycode"&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Winty Code Area&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Didn’t work.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Based on the visuals above and interface in Windows Live Writer.&amp;nbsp; My nomination goes to…. drum roll please… Code Snippet.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-3593965429228616419?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/d0pdUqJSD2MTZf0dh6gRar7f9wM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d0pdUqJSD2MTZf0dh6gRar7f9wM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/d0pdUqJSD2MTZf0dh6gRar7f9wM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d0pdUqJSD2MTZf0dh6gRar7f9wM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/ed7Tr6-7wmQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/3593965429228616419/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/11/code-formatting-live-writer-plugins.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3593965429228616419?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3593965429228616419?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/ed7Tr6-7wmQ/code-formatting-live-writer-plugins.html" title="Code Formatting Live Writer Plugins." /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/11/code-formatting-live-writer-plugins.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQBSHo8fyp7ImA9Wx5VFE0.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-8315039966172638436</id><published>2010-10-06T14:59:00.000-07:00</published><updated>2010-10-06T14:59:19.477-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-06T14:59:19.477-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Google Apps Marketplace" /><category scheme="http://www.blogger.com/atom/ns#" term="Contactpa" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Apps" /><title>Contact Personal Assistant Launches</title><content type="html">Well I have some exciting news... Contact Personal Assistant (&lt;a href="http://www.contactpa.com/"&gt;www.contactpa.com&lt;/a&gt;) formerly known as sohocrm.appspot.com, has been accepted in the Google Apps Marketplace. &amp;nbsp;Since we all like an image here it is. &amp;nbsp;It can also be viewed &lt;a href="https://www.google.com/enterprise/marketplace/viewListing?productListingId=1940+4324839027261926410"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ycfjxQr4PEU/TKzwlZJjE-I/AAAAAAAAI_U/ROB6Ayb1TQM/s1600/C:%5Cfakepath%5CScreenshot-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="182" src="http://3.bp.blogspot.com/_ycfjxQr4PEU/TKzwlZJjE-I/AAAAAAAAI_U/ROB6Ayb1TQM/s400/C:%5Cfakepath%5CScreenshot-7.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;This is a great milestone for the product, it has been a few months in development as I have learned a whole host of new technologies and frameworks. &amp;nbsp;It has been tough, but interesting, and that's what I love about software engineering, its constant puzzle solving nature. &amp;nbsp;Feel free to install Contact Personal Assistant to your Google Apps domain, or use it freely as a standalone product.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-8315039966172638436?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/v8dZ_iEdhMgVWhZlI1uWuFSRRX0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/v8dZ_iEdhMgVWhZlI1uWuFSRRX0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/v8dZ_iEdhMgVWhZlI1uWuFSRRX0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/v8dZ_iEdhMgVWhZlI1uWuFSRRX0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/ZNHtd_UTIvY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/8315039966172638436/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/10/contact-personal-assistant-launches.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8315039966172638436?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8315039966172638436?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/ZNHtd_UTIvY/contact-personal-assistant-launches.html" title="Contact Personal Assistant Launches" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ycfjxQr4PEU/TKzwlZJjE-I/AAAAAAAAI_U/ROB6Ayb1TQM/s72-c/C:%5Cfakepath%5CScreenshot-7.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/10/contact-personal-assistant-launches.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAGSX45cSp7ImA9Wx5WGEs.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-5903443267163737553</id><published>2010-09-30T08:32:00.000-07:00</published><updated>2010-09-30T08:32:08.029-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-30T08:32:08.029-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UiBinder" /><category scheme="http://www.blogger.com/atom/ns#" term="Example" /><category scheme="http://www.blogger.com/atom/ns#" term="TabLayoutPanel" /><category scheme="http://www.blogger.com/atom/ns#" term="Tab" /><title>Creating a TabPanel in UIBinder Declarative Layout View</title><content type="html">Some posts just need to be short and sweet.&amp;nbsp; Looking to create a TabPanel in UiBinder for GWT?&amp;nbsp; Check out this &lt;a href="http://giantflyingsaucer.com/blog/?p=1062"&gt;article&lt;/a&gt; and code below:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:TabLayoutPanel addStyleNames="{style.tabPanelExample1}"&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ui:field="tabPanel" barUnit="PX" barHeight="60" width="375px"&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; height="150px"&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:tab&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:header&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; UiBinder Tab 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:header&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:HTML&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Hello tab 1&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Good bye!&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:HTML&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:tab&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:tab&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:header&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; UiBinder Tab 2&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:header&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:HTML&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;h2&amp;gt;Hello tab 2&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:HTML&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:tab&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:tab&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:header&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; UiBinder Tab 3&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:header&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g:HTML&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;strong&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;i&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;u&amp;gt;Hello tab number 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/i&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/strong&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:HTML&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:tab&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g:TabLayoutPanel&amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-5903443267163737553?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YjKT2CC3eq3str_8Xxa1WVEu17I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YjKT2CC3eq3str_8Xxa1WVEu17I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YjKT2CC3eq3str_8Xxa1WVEu17I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YjKT2CC3eq3str_8Xxa1WVEu17I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/RJyKW38oGNs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/5903443267163737553/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/09/creating-tabpanel-in-uibinder.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/5903443267163737553?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/5903443267163737553?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/RJyKW38oGNs/creating-tabpanel-in-uibinder.html" title="Creating a TabPanel in UIBinder Declarative Layout View" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/09/creating-tabpanel-in-uibinder.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUMRXk9fSp7ImA9Wx5XEU8.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-3108322827122323670</id><published>2010-09-10T05:11:00.000-07:00</published><updated>2010-09-10T06:11:24.765-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-10T06:11:24.765-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GAE" /><category scheme="http://www.blogger.com/atom/ns#" term="Authentication" /><category scheme="http://www.blogger.com/atom/ns#" term="AttributeExchange" /><category scheme="http://www.blogger.com/atom/ns#" term="OpenID" /><title>Using OpenID on GWT with Google App Engine</title><content type="html">&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;style type="text/css"&gt;
    
&lt;/style&gt;  &lt;br /&gt;
&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;OpenID (TM) is the way forward for providing secure and intuitive access to your website. &amp;nbsp;The increasing proliferation of websites offering multiple methods for authentication is indicative this is a trend is here to stay. &amp;nbsp;Websites commonly contain access via Google Accounts, Facebook, Twitter, MyOpenId, and many other providers. &amp;nbsp;Not all of these use the OpenID standard but the term is likely to spread given its open source status. &amp;nbsp;Using OpenID with GWT on Google App Engine is fairly easy to implement, but has its perils which you should be aware of. &amp;nbsp;In this article we discuss the code and methods used to build a solution using the dyuproject framework. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;Why not use the new developmental federated login provided by Google App Engine? &lt;/b&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;This article documents very clearly the process to implement OpenID using the GAE SDK. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Using Federated Authentication via OpenID in Google App Engine -&amp;nbsp;&lt;a href="http://code.google.com/appengine/articles/openid.html"&gt;Link&lt;/a&gt; &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;I tried this method and it works very well and is easy to implement. &amp;nbsp;However from using it I had two issues. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Firstly, and probably the most importantly, is the&amp;nbsp;behavior&amp;nbsp;in debug mode. &amp;nbsp;When logging in the user is directed to the GAE SDK development server login page, rather than the OpenID provider selected when authenticating. &amp;nbsp;This makes debugging of your authentication system very&amp;nbsp;difficult, especially when you have to upload a new version of the application with increased logging, if you have a problem with authentication. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Secondly, if the OpenID authorization URL is incorrect, the application just sits on a blank page after trying to redirect to the authorization URL. &amp;nbsp;Now this maybe a functionality of the OpenID protocol rather than its implementation here, but the user experience was strange so I decided to abandon it. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;This is an&amp;nbsp;experimental&amp;nbsp;feature at present so I am far from saying do not use it. &amp;nbsp;What I am saying is that if you prefer to have a similar authentication experience in debug as in live, then use the suggestions given further down. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;User Interface &lt;/b&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Many of the articles written here are concerned with the steps taken to produce the website SohoCRM, a small business, Google Apps focussed CRM system - http://sohocrm.appspot.com. &amp;nbsp;The screen shot below shows the initial implementation of OpenID. &amp;nbsp;I say initial because there are plans to improve its look, but at present in its draft form it looks like this: &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ycfjxQr4PEU/TIoQkPmpmiI/AAAAAAAAI-Q/-HMLSBDC5Ck/s1600/Screenshot-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/_ycfjxQr4PEU/TIoQkPmpmiI/AAAAAAAAI-Q/-HMLSBDC5Ck/s400/Screenshot-3.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;As you can see the OpenID providers are split into two groups. &amp;nbsp;Those which require a username and those that do not. &amp;nbsp;The purpose for the username relates to the construction of the OpenID URL. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;The OpenID URL is a value passed to the OpenID library duyproject which handles how the application redirects to the authentication page of the OpenID provider. &amp;nbsp;The RelyingParty is the application requiring access, an industry standard term worth remembering. &amp;nbsp;The URL hierarchy and construction of the login images is rendered from a HashMap containing all the OpenID providers the application currently supports: &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;//Doesn't require username first &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Google","https://www.google.com/accounts/o8/id","/openid2/nascar/large/google.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Yahoo","https://me.yahoo.com","/openid2/nascar/large/yahoo.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("YahooJapan","https://me.yahoo.co.jp","/openid2/nascar/large/yahoo-jp.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("MyId","https://myid.net/","/openid2/nascar/large/myidnet.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Mixi","https://mixi.jp","/openid2/nascar/large/mixi_jp.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;//Does require username &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("MyOpenId","http://username.myopenid.com/","/openid2/nascar/large/myopenid.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Flickr","http://www.flickr.com/","/openid2/nascar/large/flickr.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("AOL","http://openid.aol.com/username","/openid2/nascar/large/aol.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Blogger","http://username.blogspot.com/","/openid2/nascar/large/blogger.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("LiveJournal","http://username.livejournal.com/","/openid2/nascar/large/livejournal.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Verisign","http://username.pip.verisignlabs.com/","/openid2/nascar/large/verisign.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("ClaimId","http://claimid.com/username","/openid2/nascar/large/claimid.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;insertProvider("Wordpress","http://username.wordpress.com","/openid2/nascar/large/wordpress.png"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;On rendering, if the login widget finds the keyword username in the URL component it renders the login image button to the bottom flow panel. &amp;nbsp;This is the one that requires the user to enter a username first. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;The second parameter for the inserProvider function is the base URL needed to access the OpenID authentication screen. &amp;nbsp;This URL is passed to the duyproject by redirecting the screen to a URL of the type: &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;"/openid2/login?openid_identifier={providerUrl}" &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;Authentication Servlet &lt;/b&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;In GWT we have setup this URL pattern to map to our OpenID Authentication servlet. &amp;nbsp;In this application we have used GUICE to setup our mappings. &amp;nbsp;In our&amp;nbsp;DispatchServletModule we have configured the mapping as below:  &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;serve("/openid2/login").with(OpenIdServlet.class); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Which then maps to an object of this type: &lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public class OpenIdServlet extends HttpServlet { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;The&amp;nbsp;Authentication&amp;nbsp;Process &lt;/b&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;This took a while because I was new to the OpenID protocol. &amp;nbsp;I had the typical programmers dilema where you know you are tackling a problem someone else has&amp;nbsp;probably&amp;nbsp;completed and published online but just need the quick heads up on how to implement. &amp;nbsp;I already has some code from GWTP Puzzlebazar's project so I quickly adapted that for my purposes. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;The doGet method points to the doPost in this servlet so the code below is where this will be found. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;Step 1&lt;/b&gt;: Establish Parameters and Logout &lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;String openIdIdentifier = request.getParameter("openid_identifier"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;if(openIdIdentifier!=null){ &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;this.userDAO.get().logoutSessionUser(); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;} &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;The openid_identifier is an important parameter in the URL so you must make sure that this is passed. &amp;nbsp;The duyproject expects this parameter so however you construct your redirect to the servlet it is expecting this in the querystring. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;Step 2&lt;/b&gt;: Create RelyingParty instance and attempt to authorization &lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;RelyingParty relyingParty = RelyingParty.getInstance(); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;try { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; OpenIdUser openIdUser = relyingParty.discover(request); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Here an instance of the relying party is created which attempts to authorize the URL passed in. &amp;nbsp;It checks whether the user has access to this URL and populates the openIdUser with information related to its status. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;After verifying the user the application then checks on how to proceed. &amp;nbsp;The duyproject covers this process very well and the javadoc here is an excellent resource on how to continue:&amp;nbsp;link. &amp;nbsp;The example code given is shown below: &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;OpenIdUser user = _relyingParty.discover(request); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; if(user==null) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; { &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; if(RelyingParty.isAuthResponse(request)) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // authentication timeout &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; response.sendRedirect(request.getRequestURI()); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; else &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // set error msg if the openid_identifier is not resolved. &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(request.getParameter(_relyingParty.getIdentifierParameter())!=null) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; request.setAttribute(OpenIdServletFilter.ERROR_MSG_ATTR, errorMsg); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // new user &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; request.getRequestDispatcher("/login.jsp").forward(request, response); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; return; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; if(user.isAuthenticated()) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; // user already authenticated &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; request.getRequestDispatcher("/home.jsp").forward(request, response); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; return; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; if(user.isAssociated() &amp;amp;&amp;amp; RelyingParty.isAuthResponse(request)) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; // verify authentication &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; if(_relyingParty.verifyAuth(user, request, response)) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // authenticated &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// redirect to home to remove the query params instead of doing: &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // request.setAttribute("user", user); request.getRequestDispatcher("/home.jsp").forward(request, response); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; response.sendRedirect(request.getContextPath() + "/home/"); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; else &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // failed verification &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; request.getRequestDispatcher("/login.jsp").forward(request, response); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; return; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; StringBuffer url = request.getRequestURL(); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; String trustRoot = url.substring(0, url.indexOf("/", 9)); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; String realm = url.substring(0, url.lastIndexOf("/")); &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; String returnTo = url.toString(); &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; if(_relyingParty.associateAndAuthenticate(user, request, response, trustRoot, realm, returnTo)) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; // successful association &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; return; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;As you can see this handles each particular outcome of the interaction with the OpenID provider. &amp;nbsp;Providing you have supplied this example code with a good url, then the duyproject handles all the redirection and processing required to authenticate the user. &amp;nbsp;The only thing you need to do is implement above the code required to register that a user has authenticated in your application, i.e. logging in DB and creating a session variable. &amp;nbsp; This would occur after the line that reads: &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="code-western"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;if (openIdUser.isAssociated() &amp;amp;&amp;amp; RelyingParty.isAuthResponse(request)) { &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="code-western"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;Attribute Exchange &lt;/b&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;The OpenIDUser object contains all the methods needed to extract any AttributeExchange information such as the Country, Language and any other attributes that are part of the AttributeExchange specification. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;Do not use the email address as the unique ID!!!!! &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;I cannot stress this enough because this issue may arrive as you transfer from one authentication system to another. &amp;nbsp;For example say you have a current auth system which requires the user to login via their email address and a password. &amp;nbsp;Fine so far. &amp;nbsp;Now in order to keep your current data model you assume that the email address returned from the OpenID provider can be used as the key again, because you have&amp;nbsp;incorrectly assumed&amp;nbsp;that the OpenID provider checks to make sure that the user who registers with an email address has been verified. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;STOP!!! &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;You cannot rely on the email address returned from the OpenID Provider because some providers allow you to specify what email address you want to return to the RelyingParty website. &amp;nbsp;Thereby changing this to another value of an account you may want access may give you a backdoor access to&amp;nbsp;someones&amp;nbsp;account. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;The only uniqueID you can rely on from the OpenID provider is what is known as the ClaimedID (openIdUser.getClaimedId()). &amp;nbsp;This value is the authentication URL the user is allowed access to. &amp;nbsp;For example my AOL ClaimedId is:  http://openid.aol.com/thinkjones &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;Summary &lt;/b&gt;&lt;/div&gt;&lt;div align="CENTER" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;This took me a while to complete, the code not the article, because I was too caught up in thinking that I needed to write absolutely everything of the OpenID process. &amp;nbsp;Relying on the duyproject was a good move as it allowed me to just slot in my current authentication process at the appropriate point. &amp;nbsp;All I needed to do was create a good URL to pass to this component. &amp;nbsp; &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;When testing the project with the different OpenID providers I needed to test each URL individually because each OID Provider had slightly different requirements in their URL syntax. &amp;nbsp;Hopefully the fairly comprehensive list above will help you implement many solutions into your current web work. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;I&amp;nbsp;apologize&amp;nbsp;if this article is a bit vague or badly written. &amp;nbsp;I have jet lag at the moment and wanted to get this article out as quickly as possible. &amp;nbsp;As usual leave questions in the comments. &lt;/div&gt;&lt;div align="LEFT" style="margin-bottom: 0in; orphans: 2; widows: 2;"&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="zemanta-pixie"&gt;&lt;img alt="" class="zemanta-pixie-img" src="http://img.zemanta.com/pixy.gif?x-id=7dea4b8d-2280-8e9f-908b-ecbd05f2a8e1" /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-3108322827122323670?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ch1Y3NbFQHN8MyuBd_6mXDuwbVo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ch1Y3NbFQHN8MyuBd_6mXDuwbVo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ch1Y3NbFQHN8MyuBd_6mXDuwbVo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ch1Y3NbFQHN8MyuBd_6mXDuwbVo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/tFquxsz5PTg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/3108322827122323670/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/09/using-openid-on-gwt-with-google-app.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3108322827122323670?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/3108322827122323670?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/tFquxsz5PTg/using-openid-on-gwt-with-google-app.html" title="Using OpenID on GWT with Google App Engine" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ycfjxQr4PEU/TIoQkPmpmiI/AAAAAAAAI-Q/-HMLSBDC5Ck/s72-c/Screenshot-3.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/09/using-openid-on-gwt-with-google-app.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYCQnw5fyp7ImA9Wx5REEQ.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-6509373387982203838</id><published>2010-08-17T17:35:00.000-07:00</published><updated>2010-08-17T17:42:43.227-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-17T17:42:43.227-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ClickHandler" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><title>Four easy steps to implementing a ClickHandler in a composite control.</title><content type="html">After developing a composite control a click handler interface (ClickHandler) is required to respond to user events. A typically example might be the type of thing shown as a row in your Gmail email list. You have developed a control which nicely lays out all the relevant information in the row, but the row as a whole should fire a click event when clicked.&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;This kind of implementation is easy, but it can get confusing especially if you are new (like me) to this kind of expert level programming. So for my own benefit and yours this is how it is implemented.&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;Step 1 : Implement HasClickHandlers Interface&lt;/b&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;In the child composite control first implement the HasClickHandlers interface:&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public class ApplicationMenuLink extends Composite implements HasClickHandlers {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;Step 2 : Add the unimplemented methods&lt;/b&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public HandlerRegistration addClickHandler(ClickHandler handler) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return addHandler(handler, ClickEvent.getType());&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;Step 3 : Fire the event when needed&lt;/b&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;@UiHandler("hyperlinkControlInComposite")&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;void doClick(ClickEvent e){&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;this.fireEvent(e);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;Step 4 : Implement handler in the parent control&lt;/b&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;instanceOfChildComposite.addClickHandler(new ClickHandler() {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;@Override&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;public void onClick(ClickEvent event) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;//Do Stuff&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;or using the UiHandler convention:&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;@UiHandler("instanceOfChildComposite")&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;void doClick(ClickEvent e){&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;//Do Stuff&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Et Voila! Thats all there is to it. As usual the path to this solution is a lot more tortuous than it would appear, but hopefully now I have it here it will be simpler for me and all us GWT developers.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-6509373387982203838?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/iDEkGHsTxNjaNCCnYOyNzN7urg0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iDEkGHsTxNjaNCCnYOyNzN7urg0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/iDEkGHsTxNjaNCCnYOyNzN7urg0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iDEkGHsTxNjaNCCnYOyNzN7urg0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/JGpSLjl-v_I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/6509373387982203838/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/08/four-easy-steps-to-implementing.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/6509373387982203838?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/6509373387982203838?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/JGpSLjl-v_I/four-easy-steps-to-implementing.html" title="Four easy steps to implementing a ClickHandler in a composite control." /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>5</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/08/four-easy-steps-to-implementing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUNQX48eyp7ImA9Wx5SFUU.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-2600296062011085036</id><published>2010-08-10T16:47:00.000-07:00</published><updated>2010-08-11T21:11:30.073-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-11T21:11:30.073-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Marketplace" /><category scheme="http://www.blogger.com/atom/ns#" term="GoogleApps" /><title>Integrating GWT applications into the Google Apps Marketplace</title><content type="html">This article examines how easy it is to integrate a GWT application into the Google Apps Marketplace.  Application stores are becoming the de-facto method to distribute software.  It is a clean, secure and hassle free method of introducing users to a large software base.  In the near future Google will be releasing an application store for chrome to distribute software, and it currently offers a business software alternative for its Google Apps users.  This article takes a look at how easy it is to change an existing GWT application for integration into the Google Apps Marketplace.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Google Apps is the term used for a suite of applications that run under your own domain name.  You get the Mail, Calendar, Documents, Sites and overall Google experience but it is configured to run on your own domain.  A recent extension to this is the Google Apps Marketplace which allows anyone with a useful application, to integrate into the Google authentication and authorization system.  Thus allowing the user a seamless experience through their current Google applications and any third-party applications configured to run on this system.  The power of this feature cannot be underestimated.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Opening up the Google Apps world to all application developers provides developers with a easy to integrate revenue stream and customer marketplace.  Whilst providing the end users with an easy to use configure application store for Google Apps.  This is a win, win situation.  No whilst it is easy to see how this will be a benefit for web application developers it might be interesting to see how easy it is in practice to integrate your application into this system.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;Background Reading&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;You didn't think I was going to do everything did you?  I would seriously recommend reading this article first to get an overview of what we are trying to do here.  This gives an overview from a development perspective of what we are trying to achieve.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Writing your First Marketplace App using Java:  &lt;a href="http://code.google.com/googleapps/marketplace/tutorial_java.html"&gt;http://code.google.com/googleapps/marketplace/tutorial_java.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In addition this page gives a rough overview of the whole process including development, but also submission to the Google Apps Marketplace:&lt;br /&gt;&lt;a href="http://developer.googleapps.com/marketplace"&gt;http://developer.googleapps.com/marketplace&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;On your marks...&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The application I am discussing is, my often touted, Simple CRM application, Soho CRM (&lt;a href="http://sohocrm.appspot.com/"&gt;http://sohocrm.appspot.com&lt;/a&gt;).  It is a small business focussed CRM system aimed at the small business market.  The application is developed in GWT, using Java, and is deployed to Google App Engine.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ycfjxQr4PEU/TGHYkynqMoI/AAAAAAAAI8E/9gbPHJ9xreE/s1600/SohoCRMSnapshot.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_ycfjxQr4PEU/TGHYkynqMoI/AAAAAAAAI8E/9gbPHJ9xreE/s400/SohoCRMSnapshot.PNG" border="0" height="117" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;As you can see from the picture the application looks like a Google application with the familiar toolbar users come to expect.  What follows is the process involved in converting this to fit into this architecture.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; margin: 0px; text-align: left;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; margin: 0px; text-align: left;"&gt;&lt;b&gt;Step 1 : Create Vendor Profile&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; margin: 0px; text-align: left;"&gt;In order to get anywhere in this system you first need to become a vendor.  The overview page here, &lt;a href="http://developer.googleapps.com/marketplace/getting-started"&gt;http://developer.googleapps.com/marketplace/getting-started&lt;/a&gt;, explains how to do that in the section "Becoming a Vendor".&lt;/div&gt;&lt;div class="separator" style="clear: both; margin: 0px; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; margin: 0px; text-align: left;"&gt;&lt;b&gt;Step 2 : Download Code&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Google provides us with an example application which you can deploy to Google App Engine and integrate into your own vendor profile in the Google Apps Marketplace.  This code is located here:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://apps-marketplace-resources.googlecode.com/files/helloworld-java.zip"&gt;Google Apps Marketplace Hello World Java&lt;/a&gt; &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 3 : Integrate code&lt;/b&gt;&lt;br /&gt;If you understand theory then the developer resource above would have been good enough for you.  I prefer real code so I can create my own internal models of what is happening during this process.  To get started I copied all the code in the directory:&lt;br /&gt;&lt;br /&gt;\helloworld-java\src\main\java\com\google\code\samples\apps\marketplace&lt;br /&gt;&lt;br /&gt;to a marketplace pacakge in my own GWT code&lt;br /&gt;&lt;br /&gt;~\server\marketplace\&lt;br /&gt;&lt;br /&gt;I also flattened the package all files required existed in this package and it wasn't distributed amongst several packages like it is in the example.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_ycfjxQr4PEU/TGHbthXOkaI/AAAAAAAAI8I/DmeEvSn1TWs/s1600/Screenshot-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://4.bp.blogspot.com/_ycfjxQr4PEU/TGHbthXOkaI/AAAAAAAAI8I/DmeEvSn1TWs/s1600/Screenshot-2.png" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I also renamed the OpenIdServlet class to GoogleAppsOpenIdServlet because regular open id users can already log into the application and I didn't want the classes to become confusing.&lt;br /&gt;&lt;br /&gt;GuiceModule.java: This file is in the downloaded code but not in the integration above, because this application already had GUICE configured.  I simply took the code from the HW example and integrated it with my own.&lt;br /&gt;&lt;br /&gt;ConsumerFactory.java:  This file was excluded because again it wasn't required.&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;A final step in this process is integrating all the required libraries.  The downloaded code comes with a library folder to make this easier.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 4 : Map Servlets&lt;/b&gt;&lt;br /&gt;Examination of the web.xml file reveals the servlets you need to map.  These can either be setup here, or if you have a code alternative set them up there.  You will need to record what URL is used as the OpenID authenticator as this is sent to the Google Apps Marketplace when you install your application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 5 : Create the manifest file&lt;/b&gt;&lt;br /&gt;By this stage your application will be ready for installing.  You just now need to configure Google Apps Marketplace to accept your application.  The first step in this process is creating the manifest.xml file.  This file  is a configuration file which tells Google Apps the name and description of your application; how to authenticate; and what Google Services the application should be given access to.  The manifest is quite an extensive piece of kit so the full explanation on the file is listed here:&lt;br /&gt;&lt;br /&gt;Creating the manifest: &lt;a href="http://code.google.com/googleapps/marketplace/manifest.html"&gt;http://code.google.com/googleapps/marketplace/manifest.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 6 : Getting Excited - We are almost there!!!&lt;/b&gt;&lt;br /&gt;The next stage is to add the application to the Google Apps Marketplace.  The vendor profile was created earlier, so after navigating to that URL : &lt;a href="https://www.google.com/enterprise/marketplace/viewVendorProfile"&gt;https://www.google.com/enterprise/marketplace/viewVendorProfile&lt;/a&gt;&lt;br /&gt;You should now be able to see a button which says "Create new listing".  Click that button and fill in your application details.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ycfjxQr4PEU/TGHhTc5aPoI/AAAAAAAAI8M/KZbPkcJe77c/s1600/GoogleAppsMarketplace.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_ycfjxQr4PEU/TGHhTc5aPoI/AAAAAAAAI8M/KZbPkcJe77c/s400/GoogleAppsMarketplace.PNG" border="0" height="283" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Make sure you check the button "My product may be directly installed into the Google Apps domain".  This then reveals the Manifest box in which you will place the manifest.xml code to set the application up.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;After completing all the sections click "Save and Preview".  On the screen that follows do not publish your application as you will first need to test it.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Step 7 : Grab oAuth Key and Secret&lt;/b&gt;&lt;br /&gt;Back on the application listing page of your vendor profile your application should now be listed.  If the stages above were completed correctly then a new link "View OAuth Consumer Key" will show under the application.  Click this and record this information as you will need it to authenticate your application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 8 : Add oAuthKey and Secret into web.xml.&lt;/b&gt;&lt;br /&gt;If you are following the Hello World example then you will need to place the OAuth Key and Secret into the web.xml file.  This correctly identifies your application to Google which will then authorise you to view the users OpenId details.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 9 : Integrate the user logon process into your application.&lt;/b&gt;&lt;br /&gt;In the doPost method of the OpenIdServlet you can see what the application does after authenticating a user. In this section you need to introduce whatever code you need to setup the logged in user.  In my code this involved setting the session.user variable to the current user.  Then simply redirect the user to the application home page.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 9 : Test&lt;/b&gt;&lt;br /&gt;If all has gone well then you should be ready to perform two important tests:&lt;br /&gt;1) Installing this application on your domain.&lt;br /&gt;2) Testing the application as an end user.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;Installing: &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;Is easy enough.  Go to the marketplace home page for your application and click the button "Add It Now".  This simply takes you to the domain administrator page for this application and gives you the option of installing the application or not.&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;Testing: &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;Once installed simply log into your domains mail application and on the right hand side where the more dropdown shows your application should now be visible.&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ycfjxQr4PEU/TGHknNowg5I/AAAAAAAAI8Q/McE6zT9zfl0/s1600/SohoCRMGoogleMenu.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_ycfjxQr4PEU/TGHknNowg5I/AAAAAAAAI8Q/McE6zT9zfl0/s320/SohoCRMGoogleMenu.PNG" border="0" height="122" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;This is where most of my time was spent developing this application.  I haven't worked on many OpenID projects so understanding the concepts was a large part of this, but the Hello World example given was very helpful in solving the problems involved.  This article, although long, is a cursory look at the steps involved.  Any readers wanting help, or more explanation on any of the steps, please let me know and I would be glad to help.&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-2600296062011085036?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7QBGW3Yu3OBh8cs5JudySOeRmMA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7QBGW3Yu3OBh8cs5JudySOeRmMA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7QBGW3Yu3OBh8cs5JudySOeRmMA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7QBGW3Yu3OBh8cs5JudySOeRmMA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/r3BMAbPYKd0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/2600296062011085036/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/08/integrating-gwt-applications-into.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/2600296062011085036?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/2600296062011085036?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/r3BMAbPYKd0/integrating-gwt-applications-into.html" title="Integrating GWT applications into the Google Apps Marketplace" /><author><name>Gene Conroy-Jones</name><uri>http://www.blogger.com/profile/09636423115609290509</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_ycfjxQr4PEU/TGHYkynqMoI/AAAAAAAAI8E/9gbPHJ9xreE/s72-c/SohoCRMSnapshot.PNG" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/08/integrating-gwt-applications-into.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIDR38yeSp7ImA9WhZWE08.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-6831661523045308640</id><published>2010-08-03T10:02:00.000-07:00</published><updated>2011-05-13T15:09:36.191-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-13T15:09:36.191-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vaadin" /><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="framework" /><title>Initial Thoughts on Vaadin : Not so much a GWT complement more of a replacement.</title><content type="html">&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=gwtsu-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=1849690448&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="align: left; height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=gwtsu-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=0321705149&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="align: left; height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;I have had the intention for a while now to try and comment on the Vaadin framework. &amp;nbsp;The website, plugins and demos exude confidence for this comprehensive toolset. &amp;nbsp;After a commentator on my &lt;a href="http://gwtsushi.blogspot.com/2010/07/increasing-importance-of-gwt.html"&gt;last post &lt;/a&gt;&amp;nbsp;suggested that I try the framework, I took this advice and proceeded through the tutorials.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://vaadin.com/tutorial/-/page/skeleton.html"&gt;address book tutorial&lt;/a&gt;&amp;nbsp;is a great introduction to the framework, the web application demonstrated is quite comprehensive and is fairly boiler-plate code free. &amp;nbsp;Check out my finished application here: &lt;a href="http://thinktaxi.appspot.com/"&gt;http://thinktaxi.appspot.com&lt;/a&gt;. &amp;nbsp;I, like most developers, dream of the ultimate framework where we can get on with just programming the logic of the application and the boiler place code is handled&amp;nbsp;beautifully&amp;nbsp;and&amp;nbsp;efficiently&amp;nbsp;by the abstraction the framework provides. &amp;nbsp;It is like the search for the Holy Grail, except of course I hope one day that this framework may actually exist.&lt;br /&gt;
&lt;br /&gt;
Vaadin is advertised as being: "Built on GWT-based widgets, Vaadin applications support all Ajax-capable browsers, with no plugins." &amp;nbsp;This is a true statement but after completing the tutorial I feel that this needs further explanation. &amp;nbsp;Vaadin runs completely on the server, using GWT as a container. &amp;nbsp;The integration of GWT and Vaadin appears to be quite separate. &amp;nbsp;An initial peruse around the&amp;nbsp;documentation&amp;nbsp;may lead you to think that Vaadin is a set of GWT-Widgets that can be used to dress up your typical GWT application. &amp;nbsp;This assumption maybe false. &amp;nbsp;I say maybe because I am fully expecting a Vaadin expert to correct my assumption here. &amp;nbsp;Vaadin is almost completely separate to GWT and shouldn't really be considered to be part of it.&lt;br /&gt;
&lt;br /&gt;
So, Vaadin runs on the server, which allows you to write complete Java code, a "benefit" when compared to GWT in which you are allowed to use certain Java libraries in the client code. &amp;nbsp;However the downside is that everything you do in Vaadin involves a trip to the server. &amp;nbsp;This in itself is a crucial point and raises the question. &amp;nbsp;How efficient can Vaadin be if everything requires a round trip? &amp;nbsp;&amp;nbsp;An additional downside is that you are learning a whole new architecture system on top of GWT. &amp;nbsp;Which restricts your future solutions if your companies&amp;nbsp;knowledge&amp;nbsp;base is Vaadin only. &lt;br /&gt;
&lt;br /&gt;
Anyway I am not a hater. &amp;nbsp;Although I am a GWT fanboy so Vaadin lovers prepare to feel the love. What applications might make Vaadin a good solution. &amp;nbsp;Well I think the quick small utility type applications that maybe used on an intranet or for just one company might be the answer. &amp;nbsp;In business, typically the speed of development and deployment is more important than how well your application performs. &amp;nbsp;The function of the application may never reach more than 100 users, so the load on the application will never be high. &amp;nbsp;I was very impressed by the speed and complexity of the application developed through the tutorial and I could see many benefits for RAD development.&lt;br /&gt;
&lt;br /&gt;
In summary Vaadin good for small business development, but it is not a GWT framework contribution and shouldn't be considered as such (If you made that assumption like I did).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-6831661523045308640?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SKTyaRx0wpQc0zrVqUvv9WdmA5M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SKTyaRx0wpQc0zrVqUvv9WdmA5M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SKTyaRx0wpQc0zrVqUvv9WdmA5M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SKTyaRx0wpQc0zrVqUvv9WdmA5M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/-nfuTR10h8Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/6831661523045308640/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/08/initial-thoughts-on-vaadin.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/6831661523045308640?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/6831661523045308640?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/-nfuTR10h8Q/initial-thoughts-on-vaadin.html" title="Initial Thoughts on Vaadin : Not so much a GWT complement more of a replacement." /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>8</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/08/initial-thoughts-on-vaadin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8MRXk8fSp7ImA9Wx5TFU0.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-7021530629938612122</id><published>2010-07-30T09:54:00.001-07:00</published><updated>2010-07-30T09:54:44.775-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-30T09:54:44.775-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="article" /><category scheme="http://www.blogger.com/atom/ns#" term="future" /><category scheme="http://www.blogger.com/atom/ns#" term="microsoft" /><title>The increasing importance of GWT</title><content type="html">&lt;p&gt;Google Web Toolkit is a fantastic piece of kit.&amp;#160; As a developer, or as anybody really, when you do a repetitive task for any period of time you become fully aware of the problems associated with it and how to improve them.&amp;#160; Microsoft’s take on this problem is to make applications prettier, and more complex, whereas Google and Apple, try to increase complexity utilizing simplicity.&amp;#160; My personal opinion is that GWT addresses this by making web application development a lot simpler at every stage of the software lifecycle.&lt;/p&gt;  &lt;p&gt;It is clear to any academically minded individual that open source is the best route forward because it takes in the ideas of the people you are trying to encourage to adopt.&amp;#160; There is an instant connection and contribution between you and your client base.&amp;#160; As the web develops in complexity it is increasingly important that a robust top to bottom professional framework exists to develop complex and layered applications.&amp;#160; Developers are increasing excited and frustrated with the multitude of decisions required for any web product.&amp;#160; GWT helps with this problem by providing a toolset that addresses many layers in the stack.&amp;#160; The proof is also in the proverbial pudding.&amp;#160; If you think Google Wave is a good product, then wouldn’t you like to use the same toolset that was used to produce that?&amp;#160; Take a look at the popular websites on the web, very few, I am aware are developed using Microsoft technologies, and the ones that are, feel like they have been developed by Microsoft technologies.&lt;/p&gt;  &lt;p&gt;The success of the iPhone, iOs and Android platforms is clear.&amp;#160; The business model clearly works.&amp;#160; At Google IO 2010 the Chrome Applications store was announced which will provide another one stop shop for people to try and buy web applications.&amp;#160;&amp;#160; With&amp;#160; HTML5 on the horizon it is clear these applications are becoming feature rich and their complexity and adoption is likely to increase exponentially.&amp;#160; As a result it is essential that the developer be allowed, to use a professional programming language, top to bottom in the software stack.&amp;#160; It makes life easier, more robust, and fulfills the need to program professionally.&amp;#160; As we move towards the cloud, frameworks such as GWT, will increase in importance as the de-facto choice for cloud based web application programming.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-7021530629938612122?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4byMN1Xenf-4zAIKQRXIowRDBPc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4byMN1Xenf-4zAIKQRXIowRDBPc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4byMN1Xenf-4zAIKQRXIowRDBPc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4byMN1Xenf-4zAIKQRXIowRDBPc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/HFjuubvVIIc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/7021530629938612122/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/07/increasing-importance-of-gwt.html#comment-form" title="19 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7021530629938612122?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/7021530629938612122?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/HFjuubvVIIc/increasing-importance-of-gwt.html" title="The increasing importance of GWT" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>19</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/07/increasing-importance-of-gwt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIDQ3g6eSp7ImA9Wx5TEUs.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-8695243782516641489</id><published>2010-07-26T09:09:00.000-07:00</published><updated>2010-07-26T09:09:32.611-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-26T09:09:32.611-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GAE" /><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="Objectify" /><title>Objectification is not always bad.</title><content type="html">We are like things that make our lives easier, unless the task of completion is the glory unto itself. &amp;nbsp;When it comes to GWT and JDO, a nice layer of abstraction exists already so it is easy to develop a data model and implement it in your system. &amp;nbsp;When GAE is added into the mix, which isn't really a relational database, certain nuances make the implementation just a little more complicated and so any library which helps with this operation is warmly welcomed. &amp;nbsp;The downside is that you are building your application specifically for Google App Engine, rather than any DB which implements JDO.&lt;br /&gt;
&lt;br /&gt;
Luckily, I Love Google. &amp;nbsp;Google I Heart You... And so that is where &lt;a href="http://code.google.com/p/objectify-appengine/"&gt;Objectify&lt;/a&gt; steps in. &amp;nbsp;Objectify is a layer which sits on top of your objects to provide easy, get, put, delete and query operations into your Google App Engine database. &amp;nbsp;At this stage I am just promoting and highlighting this functionality but will be soon posting examples of how to use this system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-8695243782516641489?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/T31UjcYzjOP65D7PUigAcfe9_Ho/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T31UjcYzjOP65D7PUigAcfe9_Ho/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/T31UjcYzjOP65D7PUigAcfe9_Ho/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T31UjcYzjOP65D7PUigAcfe9_Ho/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/V04zlMDllrY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/8695243782516641489/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/07/objectification-is-not-always-bad.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8695243782516641489?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/8695243782516641489?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/V04zlMDllrY/objectification-is-not-always-bad.html" title="Objectification is not always bad." /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/07/objectification-is-not-always-bad.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8GQn44eCp7ImA9WhZWE08.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-2380787662364724490</id><published>2010-07-16T16:51:00.000-07:00</published><updated>2011-05-13T15:13:43.030-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-13T15:13:43.030-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GWT" /><category scheme="http://www.blogger.com/atom/ns#" term="Event" /><category scheme="http://www.blogger.com/atom/ns#" term="Newbie" /><category scheme="http://www.blogger.com/atom/ns#" term="Handler" /><title>How to create a custom event handler in GWT</title><content type="html">&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=gwtsu-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=0321705149&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="align: left; height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;After struggling for longer than I should have I need to document the process partly for my own benefit and because if I struggled then someone else probably will as well. &amp;nbsp; So what am I documenting.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Scenario:&lt;/b&gt;&lt;br /&gt;
You have created a custom control Composite and want to implement a custom event for your control. &amp;nbsp;For example in the same way a button has a click event which is handled by the controls that use it.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Technology:&lt;/b&gt;&lt;br /&gt;
GWT 2.0, Java&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Solution Outline:&lt;/b&gt;&lt;br /&gt;
In this example we are using a paging control as the example. &amp;nbsp;This is a custom control that aims to replicate the kind of functionality as seen in the next, first, prev, last and message&amp;nbsp;functionality&amp;nbsp;when navigating between emails.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ycfjxQr4PEU/TEDmxBEKk6I/AAAAAAAAIvM/XdZcGMuZhVc/s1600/Pager.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_ycfjxQr4PEU/TEDmxBEKk6I/AAAAAAAAIvM/XdZcGMuZhVc/s1600/Pager.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Step 1: Create the custom event - PageChangedEvent&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The PageChangedEvent will be fired when ever a paging action takes place. &amp;nbsp;For instance if a move next, prev, first or last action is called. &amp;nbsp;The code is pretty self explanatory but for clarity I have&amp;nbsp;separated&amp;nbsp;the code into the boiler-plate section and the code specific to this event.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;/b&gt;&lt;/div&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public class PageChangedEvent extends GwtEvent&amp;lt;PageControlHandler&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;// Boiler plate code required to make your event work correctly in the GWT system&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;private static final Type&amp;lt;PageControlHandler&amp;gt; TYPE = new Type&amp;lt;PageControlHandler&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public com.google.gwt.event.shared.GwtEvent.Type&amp;lt;PageControlHandler&amp;gt; getAssociatedType() {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;return TYPE;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;protected void dispatch(PageControlHandler handler) {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;handler.onPageChanged(this);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;// Code specific to this custom event&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public enum PageChangeType {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;first, prev, next, last&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;private final PageChangeType pageChangeType;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public PageControlEvent(PageChangeType pageChangeType) {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;this.pageChangeType = pageChangeType;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public static Type&amp;lt;PageControlHandler&amp;gt; getType() {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;return TYPE;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public PageChangeType getPageChangeType(){&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;return pageChangeType;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;Step 2 : Advertise that this control has this types of events&lt;/b&gt;&lt;br /&gt;
In the PageControl which &lt;b&gt;&lt;i&gt;has&lt;/i&gt;&lt;/b&gt; these kinds of events we need to advertise this fact to the other classes, therefore the control will advertise this by implementing an interface called HasPageChangedHandler:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public class PageControl extends Composite implements ClickHandler, HasPageChangedHandler {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
However this interface has yet to exist so we need to create it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;import com.google.gwt.event.shared.HandlerRegistration;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;import com.google.gwt.event.shared.HasHandlers;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;public interface HasPageChangedHandler extends HasHandlers {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;public void addPageControlHandler(PageChangedHandler handler);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This invites other parent controls to use this event by registering a PageChangedHandler with this control&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Step 4 : Create the PageChangedHandler Interface&lt;/b&gt;&lt;br /&gt;
The handler interface indicates what type of events, or methods are required when implementing a handler of this type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;import com.google.gwt.event.shared.EventHandler;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public interface PageChangedHandler extends EventHandler{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &amp;nbsp;void onPageChanged(PageChangedEvent event);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Step 5 : Implement the methods in the composite control&lt;/b&gt;&lt;br /&gt;
In Step 2 we implemented an interface, and Step 3&amp;amp;4 we created those interfaces now we need to go back to the PageControl and the unimplemented methods.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public void addPageChangedHandler(PageChangedHandler handler) {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;addHandler(handler, PageChangedEvent.getType());&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
This is an important step. &amp;nbsp;This registers the handler for this type of event. &amp;nbsp;The "addHandler" method is part of the GWT Widget class and is native to GWT. &amp;nbsp;Therefore this method doesn't need to be created.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Step 6 : Wire up the parent control to respond to onPageChangedEvents&lt;/b&gt;&lt;br /&gt;
There are a myriad of ways of doing this but assuming the parent control has only one page control then I wired it up by implementing the&amp;nbsp;PageChangedHandler onto the main class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public class MainSearchPresenter extends PresenterImpl&amp;lt;MainSearchPresenter.MyView, MainSearchPresenter.MyProxy&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;implements SearchChangedHandler, ContactAddedHandler, ShowSearchResultsHandler, &lt;b&gt;PageChangedHandler&lt;/b&gt; {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Which then shows the method that is run when a PageChangedEvent is called:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;public void onPageChanged(PageChangedEvent event) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;if (event.getPageChangeType() == PageChangeType.next) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;   &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;getView().setupPager(1l, totalRecords, 20l);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;However this will not work yet as we haven't registered this class as being ready to accept incoming onPageChanged requests from the pageControl. &amp;nbsp;Therefore whereever you bind up your controls, which will differ depending on what framework you use then you will need to add something like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;pageControl.addPageChangedHandler(this);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;If you were implementing this an&amp;nbsp;anonymous&amp;nbsp;inner class then this kind of setup would be used, which is very similar to the click handlers which are often implemented.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;pageControl.addPageChangedHandler( new&amp;nbsp;PageChangedHandler(){&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;@Override&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;public void onPageChanged(PageChangedEvent event) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;if (event.getPageChangeType() == PageChangeType.next) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;getView().setupPager(1l, totalRecords, 20l);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;Step 7 : But wait - how do I fire this event from the child control?&lt;/b&gt;&lt;br /&gt;
Using whatever constructor arguments you require depending on the &amp;nbsp;type of event to fire then you simply call the composites native fireEvent method.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New',Courier,monospace;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;&amp;nbsp;  &lt;/span&gt;this.fireEvent(new PageChangedEvent(PageChangeType.first));&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
This took me a day to figure out. &amp;nbsp;Ouch. &amp;nbsp;A lot of it had to do with getting confused with the old listeners method. &amp;nbsp;Which you should ignore if you are using 2.0 GWT or higher. &amp;nbsp;But there were plenty of code examples, which weren't quite complete. &amp;nbsp;I am hoping that this might help a newbie in the future like myself understand this process better.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-2380787662364724490?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/avgdU60N5Lq31BmnmjN-21Ci1d4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/avgdU60N5Lq31BmnmjN-21Ci1d4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/avgdU60N5Lq31BmnmjN-21Ci1d4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/avgdU60N5Lq31BmnmjN-21Ci1d4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/cBQE6EGAg9M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/2380787662364724490/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/07/how-to-create-custom-event-handler-in.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/2380787662364724490?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/2380787662364724490?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/cBQE6EGAg9M/how-to-create-custom-event-handler-in.html" title="How to create a custom event handler in GWT" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_ycfjxQr4PEU/TEDmxBEKk6I/AAAAAAAAIvM/XdZcGMuZhVc/s72-c/Pager.png" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/07/how-to-create-custom-event-handler-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcEQXszeip7ImA9WxFaEkw.&quot;"><id>tag:blogger.com,1999:blog-3895474834344383709.post-94254072145984530</id><published>2010-07-15T10:46:00.000-07:00</published><updated>2010-07-15T10:46:40.582-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-15T10:46:40.582-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GAE" /><category scheme="http://www.blogger.com/atom/ns#" term="sohocrm" /><category scheme="http://www.blogger.com/atom/ns#" term="crm" /><category scheme="http://www.blogger.com/atom/ns#" term="GWTP" /><title>Soho CRM Moves to GWTP</title><content type="html">As you are probably aware I am currently using, and dare I say recommending using the GWTP framework, as it has a lot of built in features which are very useful to the&amp;nbsp;burgeoning&amp;nbsp;GWT application creators. &amp;nbsp;Basically if you want to free yourself of spaghetti code and extensive boiler plate boredom, then go GWTP, or go home ;)&lt;br /&gt;
&lt;br /&gt;
So I have been using the framework extensively, often asking questions in the &lt;a href="http://groups.google.com/group/gwt-platform"&gt;forum&lt;/a&gt;&amp;nbsp;and have even been invited to contribute to the &lt;a href="http://code.google.com/p/gwt-platform/"&gt;project&lt;/a&gt;. &amp;nbsp;Therefore I started where all responsible people should, and contributed to the much loved documentation. &amp;nbsp;Since I needed a FAQ page I &lt;a href="http://code.google.com/p/gwt-platform/wiki/FrequentlyAskedQuestions"&gt;created the start of one&lt;/a&gt;. &amp;nbsp;Now after two weeks I have learned a lot, and have the start of my CRM application in Google App Engine - &lt;a href="http://sohocrm.appspot.com/"&gt;http://sohocrm.appspot.com&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ycfjxQr4PEU/TD9I5ufF8VI/AAAAAAAAItM/9_vv5xhh4Z0/s1600/Screenshot-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="146" src="http://2.bp.blogspot.com/_ycfjxQr4PEU/TD9I5ufF8VI/AAAAAAAAItM/9_vv5xhh4Z0/s400/Screenshot-1.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Ok. I know it looks rough. &amp;nbsp;But believe me I have been on a learning expedition which is now starting to bare a good crop.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3895474834344383709-94254072145984530?l=www.gwtsushi.info' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/n_gMXCtd61qOuUdohhpqzSYAMLA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n_gMXCtd61qOuUdohhpqzSYAMLA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/n_gMXCtd61qOuUdohhpqzSYAMLA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n_gMXCtd61qOuUdohhpqzSYAMLA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/GwtSushi/~4/c5LdVVWeYbY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.gwtsushi.info/feeds/94254072145984530/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.gwtsushi.info/2010/07/soho-crm-moves-to-gwtp.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/94254072145984530?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3895474834344383709/posts/default/94254072145984530?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/GwtSushi/~3/c5LdVVWeYbY/soho-crm-moves-to-gwtp.html" title="Soho CRM Moves to GWTP" /><author><name>Gene</name><uri>http://www.blogger.com/profile/17596228613938166964</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="26" src="http://lh3.google.com/drgenejones/ROS6tikYABI/AAAAAAAAAT8/9N4AAK6KXVc/s288/RichardsBBQ_Gene.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_ycfjxQr4PEU/TD9I5ufF8VI/AAAAAAAAItM/9_vv5xhh4Z0/s72-c/Screenshot-1.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://www.gwtsushi.info/2010/07/soho-crm-moves-to-gwtp.html</feedburner:origLink></entry></feed>

