<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7650455487047312963</id><updated>2011-07-30T23:18:06.473-07:00</updated><title type='text'>KeyChain</title><subtitle type='html'>http://www.keychain.it</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://keychain-notes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://keychain-notes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>KeyChain Team</name><uri>http://www.blogger.com/profile/05243109052190209558</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><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7650455487047312963.post-3990771407007752125</id><published>2010-01-01T13:58:00.000-08:00</published><updated>2010-01-01T14:35:21.356-08:00</updated><title type='text'>Insert custom controls on  Google maps</title><content type='html'>We definitely like maps, for this reason me and Alberto decided to explore some features related to maps and we realized some sample app in order to play with a few features:&lt;br /&gt;- &lt;a href="http://www.jooink.com/experiments/map03/"&gt;Twitter &amp;amp; maps api&lt;/a&gt; &lt;br /&gt;- &lt;a href="http://www.jooink.com/experiments/mapHelloKitty/"&gt;Random walk on the map&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;The main features of these applications (use of twitter api, put the tweets and personalized marker on the map, geocoding, paged infowindows) are described in others post (cfr. &lt;a href="http://woorkup.com/2009/12/26/how-to-play-with-google-maps-and-twitter-api/"&gt;How to Play with Google Maps and Twitter api&lt;/a&gt;  &amp;amp; &lt;a href="http://woorkup.com/2009/12/30/super-simple-way-to-use-google-maps-api-geocoding-service/"&gt;Super simple way to use Google maps api geocoding service&lt;/a&gt;) but here let us to explore the definition of controls on the google map.&lt;div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: 24px; font-weight: bold; "&gt;Map's custom controls&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;The google map contain UI elements that allow user interaction, as pan/zoom (e.g. GLargeMapControl), a scale (e.g. GSmallZoomControl), a button that switches the view between different map types (GMapTypeControl, per default allowing to swith between Map, Satellite, Terrain, ...).&lt;br /&gt;These elements, inserted directly on the map, are known as controls and they can be included in any Google Maps API application.&lt;br /&gt;&lt;br /&gt;All the default controls (i.e. provided by the maps API) are described &lt;a href="http://code.google.com/apis/maps/documentation/controls.html"&gt;here&lt;/a&gt; but it is also possible (and even straightforward)  to build a custom control by subclassing the GControl class; Custom controls are useful for any sort of user interaction and are the standard way of putting something 'in the area' of the map (e.g. to display a custom logo in the map constructing a custom control is far the simplest way).&lt;br /&gt;On the HelloKitty sample we use, for example, a control on the map in order to let the user to switch on/off the visualization of the path.&lt;br /&gt;&lt;br /&gt;Let us to describe briefly how to setup an user generated control.&lt;br /&gt;&lt;br /&gt;The definition of a custom control is possible through assigning as prototype object  an instance of the GControl object; we define the Control on the map "TrivialMapControl" as:&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;   TrivialMapControl = function () {}&lt;br /&gt;  TrivialMapControl.prototype = new GControl();&lt;br /&gt;&lt;br /&gt;  TrivialMapControl.toggleOn &lt;br /&gt;      = document.createElement("span");&lt;br /&gt;  TrivialMapControl.toggleOn.innerHTML ="Trace ON";&lt;br /&gt;&lt;br /&gt;  TrivialMapControl.toggleOff &lt;br /&gt;      = document.createElement("span");&lt;br /&gt;  TrivialMapControl.toggleOff.innerHTML ="Trace OFF";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The definition of a custom control requires te definition of two methods:&lt;br /&gt;initialize(): that creates and returns a DOM element;&lt;br /&gt;getDefaultPosition(): that defines and  returns an object of type GControlPosition.&lt;br /&gt;&lt;br /&gt;The following is the initialize function that we use in our sample code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; TrivialMapControl.prototype.initialize = function(map) {&lt;br /&gt;   var container = document.createElement("div");&lt;br /&gt;   //setAttribute does not work consistently &lt;br /&gt;   //for 'class' with IE and ... the rest of the world&lt;br /&gt;   container.classNode = "map_control";&lt;br /&gt; &lt;br /&gt;   this.setButtonStyle_(TrivialMapControl.toggleOff);&lt;br /&gt;   GEvent.addDomListener(TrivialMapControl.toggleOff, &lt;br /&gt;     "click", &lt;br /&gt;     function() {&lt;br /&gt;       isViewTrace = false;&lt;br /&gt;       container.replaceChild(TrivialMapControl.toggleOn,&lt;br /&gt;         TrivialMapControl.toggleOff);&lt;br /&gt;  });&lt;br /&gt;&lt;br /&gt; GEvent.addDomListener(TrivialMapControl.toggleOn, &lt;br /&gt;     "click", &lt;br /&gt;     function() {&lt;br /&gt;       isViewTrace=true;&lt;br /&gt;       container.replaceChild(TrivialMapControl.toggleOff,&lt;br /&gt;         TrivialMapControl.toggleOn);&lt;br /&gt;   });&lt;br /&gt;&lt;br /&gt;  container.appendChild(TrivialMapControl.toggleOn);&lt;br /&gt;&lt;br /&gt; var lb = document.createElement("div");&lt;br /&gt;       &lt;br /&gt; var jl = document.createElement("img");&lt;br /&gt; jl.className = "trivialmap_logo";&lt;br /&gt; jl.src = document.getElementById("logo_small").src;&lt;br /&gt; &lt;br /&gt; lb.appendChild(jl);&lt;br /&gt; container.appendChild(lb);&lt;br /&gt;&lt;br /&gt; map.getContainer().appendChild(container);&lt;br /&gt; return container;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Our prototype.initialize() method  simply displays a custom logo and defines the button (with a special style), used to show or to hide the Trace of the path along the way.&lt;br /&gt;&lt;br /&gt;Furthermore, the getDefaultPosition function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  TrivialMapControl.prototype.getDefaultPosition =&lt;br /&gt;       function() {&lt;br /&gt;           return new GControlPosition(G_ANCHOR_TOP_LEFT, &lt;br /&gt;                 new GSize(80, 12));&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;defines the default position of the control (so the name :o) G_ANCHOR_TOP_LEFT in our sample (the others possible choices are G_ANCHOR_TOP_RIGHT, G_ANCHOR_BOTTOM_RIGHT, G_ANCHOR_BOTTOM_LEFT) and the distance from the top/left corner.&lt;br /&gt;&lt;br /&gt;After the definition, the map control has to be added to the map container through the following instructions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  var map = &lt;br /&gt;    new GMap2(document.getElementById("map_canvas"), ...);&lt;br /&gt;  map.addControl(new TrivialMapControl());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's all Folks !!!&lt;br /&gt;&lt;/div&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/7650455487047312963-3990771407007752125?l=keychain-notes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keychain-notes.blogspot.com/feeds/3990771407007752125/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://keychain-notes.blogspot.com/2010/01/insert-custom-controls-on-google-maps.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/3990771407007752125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/3990771407007752125'/><link rel='alternate' type='text/html' href='http://keychain-notes.blogspot.com/2010/01/insert-custom-controls-on-google-maps.html' title='Insert custom controls on  Google maps'/><author><name>KeyChain Team</name><uri>http://www.blogger.com/profile/05243109052190209558</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><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7650455487047312963.post-2949029752405872952</id><published>2009-09-30T10:11:00.001-07:00</published><updated>2009-09-30T10:11:42.146-07:00</updated><title type='text'>Using Appengine to store and retrieve data</title><content type='html'>TBD&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7650455487047312963-2949029752405872952?l=keychain-notes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keychain-notes.blogspot.com/feeds/2949029752405872952/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://keychain-notes.blogspot.com/2009/09/using-appengine-to-store-and-retrieve.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/2949029752405872952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/2949029752405872952'/><link rel='alternate' type='text/html' href='http://keychain-notes.blogspot.com/2009/09/using-appengine-to-store-and-retrieve.html' title='Using Appengine to store and retrieve data'/><author><name>KeyChain Team</name><uri>http://www.blogger.com/profile/05243109052190209558</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><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7650455487047312963.post-2299151793065488353</id><published>2009-09-17T12:16:00.000-07:00</published><updated>2009-09-30T10:15:42.945-07:00</updated><title type='text'>Geolocation</title><content type='html'>Keychain_team is actually working on a maps mashup (JooinK) based on the google maps api.&lt;br /&gt;During the development we faced the problem of geolocate the remote user.&lt;br /&gt;&lt;br /&gt;We looked a lot around the web and we found that it is possible&lt;br /&gt;to obtain the position of the remote user accessing the "google&lt;br /&gt;loader" ClientLocation field, unfortunately appear not possible to do&lt;br /&gt;this directly through gwt's maps api but defining a jni function&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;private static native LatLng UserLocation() /*-{&lt;br /&gt; if( $wnd.google ) {&lt;br /&gt;  if( $wnd.google.loader ) {&lt;br /&gt;   if ($wnd.google.loader.ClientLocation){&lt;br /&gt;    var center = new $wnd.google.maps.LatLng(&lt;br /&gt;      $wnd.google.loader.ClientLocation.latitude,&lt;br /&gt;      $wnd.google.loader.ClientLocation.longitude&lt;br /&gt;     );&lt;br /&gt;    return center;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; return null;&lt;br /&gt;}-*/;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and then calling the native method&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;  LatLng userDefaultLocation = UserDefaultLocation();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We get the LatLng position of the user&lt;br /&gt;Do not forget to load google's jsapi, e.g. putting in the head of your html file&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" &lt;br /&gt;  src="http://www.google.com/jsapi"&amp;gt;&lt;br /&gt;  &amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;you will find soon the complete project on http://www.keychain.it&lt;br /&gt;&lt;br /&gt;That's all folk!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7650455487047312963-2299151793065488353?l=keychain-notes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keychain-notes.blogspot.com/feeds/2299151793065488353/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://keychain-notes.blogspot.com/2009/09/geolocation.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/2299151793065488353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/2299151793065488353'/><link rel='alternate' type='text/html' href='http://keychain-notes.blogspot.com/2009/09/geolocation.html' title='Geolocation'/><author><name>KeyChain Team</name><uri>http://www.blogger.com/profile/05243109052190209558</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><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7650455487047312963.post-9085668719709370761</id><published>2009-09-08T14:17:00.000-07:00</published><updated>2009-09-30T10:09:22.623-07:00</updated><title type='text'>Authentication on demand (using appengine UserService)</title><content type='html'>During the development of  our  map's  mashup  (JooinK, still  in progress) we  faced the problem of handling authentication (in  this post we focus on Google  Accounts).&lt;br /&gt;&lt;br /&gt;Our target was to let the user to authenticate on demand during the navigation of JooinK without losing the current status (say, the current position on the map). We know this is in no way an unexplored field (actually, blogspot does something similar) but  we think that the description  of the complete procedure worth a note.&lt;br /&gt;&lt;br /&gt;So let us suppose we want to write a simple application (named JooinK ;-) ) to be published on Google App Engine using the provided UserService (see &lt;a href="http://code.google.com/webtoolkit/tutorials/1.6/appengine.html#user"&gt;http://code.google.com/webtoolkit/tutorials/1.6/appengine.html#user&lt;/a&gt; for the general overview).&lt;br /&gt;&lt;br /&gt;Roughly speaking  authentication on-demand should proceed as follows:&lt;br /&gt;&lt;OL type="a"&gt;&lt;br /&gt;  &lt;LI&gt; the user navigate anonymously JooinK;&lt;br /&gt;  &lt;LI&gt; the user begin the process of authentication (e.g. triggered by a component of the user interface);&lt;br /&gt;  &lt;LI&gt; the control is transferred to the "google login page";&lt;br /&gt;  &lt;LI&gt; at the end of the authentication process the control returns back to JooinK;&lt;br /&gt;  &lt;LI&gt; the user interface changes accordingly to the result of the authentication, not loosing the "current status".&lt;br /&gt;&lt;/OL&gt;&lt;br /&gt;&lt;br /&gt;In particular:&lt;br /&gt;&lt;br /&gt;Step a. represents a first look to the application by an anonymous user, which  can navigate in and, for instance, choose a location on the map.&lt;br /&gt;&lt;br /&gt;To proceed through  step b.  it is required to know the URL of the google account's identity provider, which has to be retrieved using a GWT-RPC call to an ad hoc service, as described in the aforementioned example and quoted below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;public class LoginServiceImpl &lt;br /&gt;    extends RemoteServiceServlet &lt;br /&gt;        implements LoginService {&lt;br /&gt;&lt;br /&gt; public LoginInfo login(String ComeBackURL) {&lt;br /&gt;  UserService userService &lt;br /&gt;        = UserServiceFactory.getUserService();&lt;br /&gt;  User user = userService.getCurrentUser();&lt;br /&gt;  LoginInfo loginInfo = new LoginInfo();&lt;br /&gt;&lt;br /&gt;  if(user != null) {&lt;br /&gt;    loginInfo.setLoggedIn(true);&lt;br /&gt;    loginInfo.setEmailAddress(user.getEmail());&lt;br /&gt;    loginInfo.setNickname(user.getNickname());&lt;br /&gt;    loginInfo.setLogoutUrl(&lt;br /&gt;      userService.createLogoutURL(ComeBackURL));&lt;br /&gt;  } else {&lt;br /&gt;    loginInfo.setLoggedIn(false);&lt;br /&gt;    loginInfo.setLoginUrl(&lt;br /&gt;      userService.createLoginURL(ComeBackURL));&lt;br /&gt;  }&lt;br /&gt;  return loginInfo;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After a successful call to the login service the returned LoginInfo object will contain:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;informations about the user i.e. username etc, for a logged in user;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the URL of the identity provider for the anonymous user.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Please note that ComeBackURL is the URL of the page where the idp will  redirect the user's browser on completion of the login process, i.e. it is the  URL of  the part of our code that performs Step d. (we will give further details later on this paper).&lt;br /&gt;&lt;br /&gt;When the user express the aim of authenticating (so entering into step b), say with a click on the  "let me authenticate" link, we call the loginService as in the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;// do something informing the user that &lt;br /&gt;// we are processing the&lt;br /&gt;// authentication request, &lt;br /&gt;//e.g. change the link text with something&lt;br /&gt;//else&lt;br /&gt;.....&lt;br /&gt;loginService.login(ComeBackUrl, &lt;br /&gt;  new AsyncCallback&amp;lt;logininfo&gt;() {&lt;br /&gt;   public void onFailure(Throwable error) {&lt;br /&gt;    // error comunication with the server &lt;br /&gt;    //.... handle this.&lt;br /&gt;    Window.alert('Something unhappy happened&lt;br /&gt;        to Jooink, try later');&lt;br /&gt;   }&lt;br /&gt;   public void onSuccess(LoginInfo result) {&lt;br /&gt;    loginInfo = result;&lt;br /&gt;    if(loginInfo.isLoggedIn()) {&lt;br /&gt;     // the user is already logged in ...&lt;br /&gt;     // nothing to do&lt;br /&gt;     // modify the user interface&lt;br /&gt;     // e.g  remove the authentication link and&lt;br /&gt;     // sostitute it with the logout one&lt;br /&gt;     // show somewhere the username &lt;br /&gt;     //(it is inside loginInfo)&lt;br /&gt;    } else {&lt;br /&gt;     // the user is not logged in&lt;br /&gt;     // we have to pass the control to the idp&lt;br /&gt;     manageLogin(loginInfo);&lt;br /&gt;    }&lt;br /&gt;  );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here the function manageLogin(...) represents step c and is obviously executed only if the user is not already authenticated.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;public void manageLogin(LoginInfo li) {&lt;br /&gt;   dialogBox = new DialogBox();&lt;br /&gt;   dialogBox.setModal(true)&lt;br /&gt;   dialogBox.setText("-- Authentication --");&lt;br /&gt;   final Frame idpFrame &lt;br /&gt;                = new NamedFrame("idpFrame");&lt;br /&gt;   dialogBox.add(idpInteractionFrame);&lt;br /&gt;   idpFrame.setUrl(loginInfo.getLoginUrl());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The purpose of the above function is to let the user interact directly with the identity provider but this cannot be realized simply redirecting the user  to loginInfo.loginURL because this will&lt;br /&gt;trash the status of the application (or force the status to be serialized somewhere in ComeBackUrl), instead we use an IFRAME (IFrames or windows appear to be the only choice here).&lt;br /&gt;&lt;br /&gt;Actually the shown code does what we expect, i.e. let the user to authenticate but unfortunately, after a successful login we will get ComeBackUrl loaded inside the FRAME that may be not the desired result (this is where we enter into step d: taking back control).&lt;br /&gt;&lt;br /&gt;Definitely what we want is: closing the dialog box,  having a variable in our code bounded with the current username.&lt;br /&gt;To accomplish this we need two ingredients:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a servlet associated to ComeBackUrl;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;a bit of jsni;&lt;/li&gt;&lt;/ul&gt;as shown in the following code:&lt;br /&gt;&lt;br /&gt;The servlet is simply a non RPC version of LoginServiceImpl (but we cannot call the RPC as a result of a redirection) that returns an html page containing javascript cote that "injects" variables in the running GWT application.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;...&lt;br /&gt;public class LoginServlet extends HttpServlet {&lt;br /&gt; public void doGet(HttpServletRequest request, &lt;br /&gt;                  HttpServletResponse res)&lt;br /&gt;   throws ServletException {&lt;br /&gt;  UserService userService &lt;br /&gt;         = UserServiceFactory.getUserService();&lt;br /&gt;  User user = userService.getCurrentUser();&lt;br /&gt;  LoginInfo loginInfo = new LoginInfo();&lt;br /&gt;  if (user != null) {&lt;br /&gt;    returnSuccess(res,&lt;br /&gt;       user.getEmail(),user.getNickname());&lt;br /&gt;  } else {&lt;br /&gt;    returnFailure(res,&lt;br /&gt;       user.getLoginUrl(ComeBackUrl));&lt;br /&gt;  }&lt;br /&gt;  return;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately now we  are unable to return the loginInfo  as we did in the RPC: a servlet cannot return  an object to our  application so we have to play with html, plain javascript and jsni.&lt;br /&gt;&lt;br /&gt;The returnFailure method is the  simpler, we have to generate an html noticing the user that  some problem happened and eventually a courtesy link to let the user to retry authentication. For instance:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;public void &lt;br /&gt;returnFailure(HttpServletResponse res, &lt;br /&gt;              String loginURL) {&lt;br /&gt; try {&lt;br /&gt;   PrintWriter out = response.getWriter();&lt;br /&gt;   out.println("Autentication UNsuccessfull. " +&lt;br /&gt;    "&lt;a href="http://..."&gt;Retry&lt;/a&gt;");&lt;br /&gt; } catch (Exception e) {&lt;br /&gt;   ...&lt;br /&gt; }&lt;br /&gt; return;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On the  other hand  returnSuccess  should  trigger a javascript method to close the  dialog and "inject" username and email in the application running in the browser.  Let us  remark that  the following  code  is for demonstration  purpose  and  is  cumbersome  because  a  more  elegant&lt;br /&gt;implementation  will require  to  describe a  more  structured set  of classes that are out of the scope of this note.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;public void &lt;br /&gt;returnSuccess(HttpServletResponse res,&lt;br /&gt;              String email, String name) {&lt;br /&gt;  String onload = &lt;br /&gt;    "window.parent.userData('"+name+"');";&lt;br /&gt;  onLoad += &lt;br /&gt;    "window.parent.userEmail('"+email+"');";&lt;br /&gt;  onLoad += "window.parent.dialogHide();";&lt;br /&gt;  try {&lt;br /&gt;    PrintWriter out = response.getWriter();&lt;br /&gt;    out.println("Autentication OK");&lt;br /&gt;  } catch (Exception e) {&lt;br /&gt;    ...&lt;br /&gt; }&lt;br /&gt; return; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;where userData, userEmail, dialogHide (step e!) have  to be provided by jsni; to do  this we have to  call, e.g.  in  manageLogin just  after the  assignment of dialogBox, a special function  (actually a native function) defined as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java; html-script: true; gutter: false; light: true; toolbar: false; font-size:'50%';"&gt;&lt;br /&gt;public static native void&lt;br /&gt;prepareAuthHookMethods(LoginInfo logI, &lt;br /&gt;                         DialogBox db) /*-{&lt;br /&gt; $wnd.userName = function(s) {&lt;br /&gt; return&lt;br /&gt;   logI.@FULL_PACKAGE_NAME_HERE.&lt;br /&gt;       LoginInfo::&lt;br /&gt;          setUserName(Ljava/lang/String)(s);&lt;br /&gt; }&lt;br /&gt; $wnd.userEmail = function(s) {&lt;br /&gt;   return&lt;br /&gt;     logI.@FULL_PACKAGE_NAME_HERE.&lt;br /&gt;          LoginInfo::&lt;br /&gt;             setUserEmail(Ljava/lang/String)(s);&lt;br /&gt; }&lt;br /&gt; $wnd.dialogHide= function() {&lt;br /&gt;   return &lt;br /&gt;     db.@FULL_PACKAGE_NAME_HERE.&lt;br /&gt;        LoginInfo::hide()();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's all folks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7650455487047312963-9085668719709370761?l=keychain-notes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://keychain-notes.blogspot.com/feeds/9085668719709370761/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://keychain-notes.blogspot.com/2009/09/authentication-on-demand-using.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/9085668719709370761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7650455487047312963/posts/default/9085668719709370761'/><link rel='alternate' type='text/html' href='http://keychain-notes.blogspot.com/2009/09/authentication-on-demand-using.html' title='Authentication on demand (using appengine UserService)'/><author><name>KeyChain Team</name><uri>http://www.blogger.com/profile/05243109052190209558</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><thr:total>0</thr:total></entry></feed>
