Thanks for the tips Eric. - I noticed that newInstance was used in Google Maps so i'm adopted the same convention.
- I see what you mean about exception handling. I'll make use of your ExceptionHelper for Runnables. For the AsyncCallbacks, i'll try to mirror your ExceptionHelper implementation. - When generating the overloads i plug "undefined" in place of omitted optional parameters. Methods with only one parameter were causing the single "undefined" parameter you pointed out, this will be gone after polishing. I have another batch of questions/comments coming up - there's one class in GData, the base class for all service classes, which requires some thought since it has methods that may receive constructors (for example GetFeed, which receives the constructor of the feed to be returned). How this class is implemented has some implications on the classes that extend it. I'll have the auto-generated GWT library up sometime next week, this way i'll be able to link to the GWT and JS classes and hopefully get some more feedback on the implementation - not so much on the JSNI code but on the architecture/structure of the library. I'm also attempting to auto-generating base Unit tests for each class - most classes are data classes, so Unit tests are straightforward enough (e.g. call each setter, call the corresponding getter, check that the gotten value is the set value). The service classes themselves, which retrieve and update data in the various systems are more difficult, i don't have a plan for those, there will probably be some manual labor but it's not the end of the world if it comes to that. Bobby On May 18, 3:30 pm, Eric Ayers <[email protected]> wrote: > Hi Bobby, > > Thanks for the update, here is some feedback inline. Sorry for the > delay, I was out last week. > > > > > > On Mon, May 11, 2009 at 3:17 AM, Bobby <[email protected]> wrote: > > > I'm very close, i've just compiled a GData JS example via the GData > > GWT library - which retrieves a Calendar feed - and it worked. > > > Here are some of the implementation choices i've made so far: > > - map all namespaces to be under com.google.gwt.gdata.client.* > > - map all Object parameters to JavaScriptObject (some GData functions > > receive generic JS objects for initialization purposes). > > - implement JS classes as Overlay Types > > - implement class constants as JSNI methods, for example: > > public static native String REL_MESSAGE_TO() /*-{ return > > $wnd.google.gdata.Who.REL_MESSAGE_TO; }-*/; > > - implement constructors as JSNI methods (since i'm using Overlay > > Types), for example: > > public static native Who construct() /*-{ return new > > $wnd.google.gdata.Who(undefined); }-*/; > > In the gwt-google-apis, I have been naming these factory methods > newInstance() or getInstance() for constructing singletons. This > comes from convention in the JRE and Joshua Bloch's "Effective Java". > > > - generate overloads for methods that have optional parameters or > > multi-type parameters in JS, for example: > > public final native void setValueString(String valueString) /*- > > { this.setValueString(valueString); }-*/; > > public final native void setValueString() /*-{ this.setValueString > > (undefined); }-*/; > > - implement continuation callbacks (non success/failure) as Runnable, > > for example: > > public static final native boolean getInfo(Runnable callback) /*- > > { return $wnd.google.accounts.user.getInfo(function() > > { [email protected]::run()(); }); }-*/; > > This is good, but in order to display exceptions in Hosted mode, a > more complex pattern is needed. Essentially, you need to call a > special handler for exceptions in hosted mode. A particularly nice > implementation of this is the Handler class in gwt-visualization which > uses the ExceptionHelper class in the ajaxloader package. > > http://code.google.com/p/gwt-google-apis/source/browse/releases/visua...http://code.google.com/p/gwt-google-apis/source/browse/releases/ajaxl... > > I usually pull the ajaxloader class into the other gwt-google-api > projects using an svn:externals property if you haven't done that > already. > > > - implement success/failure callbacks as AsyncCallback<T>, for > > example: > > public final native CalendarAclFeed getAclFeed(String uri, > > AsyncCallback<CalendarAclFeed> callback) /*-{ > > return this.getAclFeed(uri, function(result) > > { @com.google.gwt.gdata.client.impl.Utils::handleSuccessCallback(Lcom/ > > google/gwt/user/client/rpc/AsyncCallback;Ljava/lang/Object;)(callback, > > result); }, function(error) > > { @com.google.gwt.gdata.client.impl.Utils::handleFailureCallback(Lcom/ > > google/gwt/user/client/rpc/AsyncCallback;Ljava/lang/String;)(callback, > > error); }); > > }-*/; > > Same comment here - if you don't add the UncaughtExceptionHandler > stuff, hosted mode will miss exceptions that occur in the callback. > > > > > > > - ignore all instance fields, since GData implements getters and > > setters. > > - use the existing AjaxLoader to loading the JS libraries. > > > Pending testing. Adding overloads has been interesting, for a given > > method with n optional parameters there are 2^n overloads to be added > > - plus some JS methods have multi-type parameters so those need to be > > defined as well. > > > Here's a class from the GWT GData library (corresponds to > >http://code.google.com/apis/gdata/jsdoc/1.8/google/gdata/Who.html): > > > package com.google.gwt.gdata.client; > > import com.google.gwt.gdata.client.EntryLink; > > import com.google.gwt.gdata.client.AttendeeType; > > import com.google.gwt.gdata.client.AttendeeStatus; > > import com.google.gwt.core.client.JavaScriptObject; > > > public class Who extends com.google.gwt.core.client.JavaScriptObject { > > public static native String REL_EVENT_ATTENDEE() /*-{ return > > $wnd.google.gdata.Who.REL_EVENT_ATTENDEE; }-*/; > > public static native String REL_EVENT_ORGANIZER() /*-{ return > > $wnd.google.gdata.Who.REL_EVENT_ORGANIZER; }-*/; > > public static native String REL_EVENT_PERFORMER() /*-{ return > > $wnd.google.gdata.Who.REL_EVENT_PERFORMER; }-*/; > > public static native String REL_EVENT_SPEAKER() /*-{ return > > $wnd.google.gdata.Who.REL_EVENT_SPEAKER; }-*/; > > public static native String REL_MESSAGE_BCC() /*-{ return > > $wnd.google.gdata.Who.REL_MESSAGE_BCC; }-*/; > > public static native String REL_MESSAGE_CC() /*-{ return > > $wnd.google.gdata.Who.REL_MESSAGE_CC; }-*/; > > public static native String REL_MESSAGE_FROM() /*-{ return > > $wnd.google.gdata.Who.REL_MESSAGE_FROM; }-*/; > > public static native String REL_MESSAGE_REPLY_TO() /*-{ return > > $wnd.google.gdata.Who.REL_MESSAGE_REPLY_TO; }-*/; > > public static native String REL_MESSAGE_TO() /*-{ return > > $wnd.google.gdata.Who.REL_MESSAGE_TO; }-*/; > > public static native String REL_TASK_ASSIGNED_TO() /*-{ return > > $wnd.google.gdata.Who.REL_TASK_ASSIGNED_TO; }-*/; > > > protected Who() { } > > > public static native Who construct(JavaScriptObject opt_params) /*- > > { return new $wnd.google.gdata.Who(opt_params); }-*/; > > public static native Who construct() /*-{ return new > > $wnd.google.gdata.Who(undefined); }-*/; > > I believe that passing 'undefined' as a parameter is the same as > passing no parameters at all. In general, making the JavaScript less > verbose will make the resulting compiled code smaller to download. > Every bit helps! > > > > > > > public final native AttendeeStatus getAttendeeStatus() /*-{ return > > this.getAttendeeStatus(); }-*/; > > public final native AttendeeType getAttendeeType() /*-{ return > > this.getAttendeeType(); }-*/; > > public final native String getEmail() /*-{ return this.getEmail(); }- > > */; > > public final native EntryLink getEntryLink() /*-{ return > > this.getEntryLink(); }-*/; > > public final native String getRel() /*-{ return this.getRel(); }-*/; > > public final native String getValueString() /*-{ return > > this.getValueString(); }-*/; > > public final native void setAttendeeStatus(JavaScriptObject > > attendeeStatus) /*-{ this.setAttendeeStatus(attendeeStatus); }-*/; > > public final native void setAttendeeStatus() /*- > > { this.setAttendeeStatus(undefined); }-*/; > > public final native void setAttendeeStatus(AttendeeStatus > > attendeeStatus) /*-{ this.setAttendeeStatus(attendeeStatus); }-*/; > > public final native void setAttendeeType(JavaScriptObject > > attendeeType) /*-{ this.setAttendeeType(attendeeType); }-*/; > > public final native void setAttendeeType() /*-{ this.setAttendeeType > > (undefined); }-*/; > > public final native void setAttendeeType(AttendeeType attendeeType) / > > *-{ this.setAttendeeType(attendeeType); }-*/; > > public final native void setEmail(String email) /*-{ this.setEmail > > (email); }-*/; > > public final native void setEmail() /*-{ this.setEmail(undefined); }- > > */; > > public final native void setEntryLink(JavaScriptObject entryLink) /*- > > { this.setEntryLink(entryLink); }-*/; > > public final native void setEntryLink() /*-{ this.setEntryLink > > (undefined); }-*/; > > public final native void setEntryLink(EntryLink entryLink) /*- > > { this.setEntryLink(entryLink); }-*/; > > public final native void setRel(String rel) /*-{ this.setRel(rel); }- > > */; > > public final native void setRel() /*-{ this.setRel(undefined); }-*/; > > public final native void setValueString(String valueString) /*- > > { this.setValueString(valueString); }-*/; > > public final native void setValueString() /*-{ this.setValueString > > (undefined); }-*/; > > } > > > Bobby > > > On May 3, 9:05 pm, Eric Ayers <[email protected]> wrote: > >> I think you should make it a separate module, but at this point, I think it > >> should remain under gdata for now. I see other APIs use this namespace, > >> but > >> I will have to coordinate to see if it can truly be shared like AjaxLoader > >> apis. > > >> On Sun, May 3, 2009 at 2:51 PM, Bobby <[email protected]> wrote: > > >> > Thanks Eric, it works for me. On a related topic, there's a namespace > >> > in the GData API, google.accounts, that i think should be in its own > >> > GWT module as well: > >> >http://code.google.com/apis/gdata/jsdoc/1.8/google/accounts.html > > >> > It's used by GData to authenticate via AuthSub, but it's outside > >> > GData. > > >> > Bobby > > >> > On May 3, 6:38 am, Eric Ayers <[email protected]> wrote: > >> > > Hi guys, > >> > > The AjaxLoader API will be put in public release soon. I've made a > >> > release > >> > > branch for it under subversion athttp:// > >> > gwt-google-apis.googlecode.com/svn/releases/ajaxloader/1.0 > > >> > > -Eric. > > >> > > On Sun, May 3, 2009 at 2:40 AM, Bobby <[email protected]> wrote: > > >> > > > I'm going over the following pages carefully: > > >> > > >http://code.google.com/docreader/#p=gwt-google-apis&s=gwt-google-apis. > >> > .. > > >> > > > Some GWT APIs, such as the Maps API, already have an implementation > >> > > > of > >> > > > the AjaxLoader for loading Google JS libraries, so that's one less > >> > > > thing to do. > > >> > > > Bobby > > >> > > > On Apr 27, 2:58 am, Bobby <[email protected]> wrote: > >> > > > > I just came across some interesting docs, this one in particular > >> > > > > covers almost all the questions i had in my original post > > ... > > read more »- Hide quoted text - > > - Show quoted text -- Hide quoted text - > > - Show quoted text -- Hide quoted text - > > - Show quoted text - --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/Google-Web-Toolkit?hl=en -~----------~----~----~----~------~----~------~--~---
