A hello-world iGoogle gadget:
http://www.google.com/ig/adde?source=ignsrc1&moduleurl=http%3A//vawter.org/hellogadgets/com.google.gwt.sample.hello.client.Hello.gadget.xml
Things like OpenSocial and Google Mapplets are just gadgets that use
additional features. This is why we're going with a
dependency-injection style of API. Tell the system what you need, and
you'll get it at runtime.
A simple mapplet demo:
http://maps.google.com/ig/add?synd=mpl&pid=mpl&moduleurl=http://vawter.org/hellomaps/com.google.gwt.sample.hellomaps.client.HelloMaps.gadget.xml
Thanks.
--
Bob Vawter
Google Web Toolkit Team
I expect that it will be integrated into gwt-google-apis project (aka GALGWT).
> - Just trying to understand the motivation of this package
The motivation is as you've described; there are a number of
containers that support the Gadgets spec and we want GWT to be the
easiest way to produce and deploy Gadgets.
> - Can you elaborate on dependency-injection style API?
Sure. Dependency injection is a style of coding where you write your
application code against an interface and allow some other mechanism
to provide the concrete implementation. There are a lot of different
DI frameworks on the market that have different degrees of
configurability and magic, but the coding style remains pretty much
constant.
In the Gadgets sample, you'll notice that the Hello class implements
several NeedsFoo interfaces. Each NeedsFoo interface defines a setter
that accepts a FooFeature object that provides access to the feature
at runtime. By explicitly declaring the feature requirements and
other properties of the Gadget in the type system, it allows us to
write a GWT Generator that can automatically produce the Gadget
manifest file.
Secondly, I have a question. Is there a reason you use marker
interfaces (NeedsBlah...) vs annotations (@RequireFeature("Blah")) I
didn't see any .gwt.xml rules checking for these types, nor any
instanceof expressions or methods taking them as type parameters. Alot
of noise was made after the introduction of annotations in Tiger about
marker interfaces no longer being neccessary (in most cases)
Otherwise, I love it, and will probably be using it to do this
(http://timepedia.blogspot.com/2008/01/project-syndroidsynthesis-of-gwt-and.html)
-Ray
Secondly, I have a question. Is there a reason you use marker
interfaces (NeedsBlah...) vs annotations (@RequireFeature("Blah")) I
didn't see any .gwt.xml rules checking for these types, nor any
instanceof expressions or methods taking them as type parameters. Alot
of noise was made after the introduction of annotations in Tiger about
marker interfaces no longer being neccessary (in most cases)
-Ray
The NeedsFoo interfaces define setters for API objects that the gadget
will use to access that feature. With a slight tweak from the current
formulation, it should allow enough flexibility to mock out API
features or to take care of variations between container API
implemetations (just in case the Foo Gadget container were to expose
setTitle differently). With the explicit injection style, there's no
way you could fail to register a need for a specific API, whereas with
a static factory or explicit GWT.create, there's the chance that the
developer would waste non-trivial amounts of time debugging a missing
@Requires annotation on the gadget.
Once I get back into the office, I'll add this as a branch in the
galgwt project and solicit further feedback.
--BobV.
Sent from the field.
On Feb 4, 2008, at 23:01, "Ray Cromwell" <cromw...@gmail.com> wrote:
>
> Bob,
> First, kick ass!
>
> Secondly, I have a question. Is there a reason you use marker
> interfaces (NeedsBlah...) vs annotations (@RequireFeature("Blah")) I
> didn't see any .gwt.xml rules checking for these types, nor any
> instanceof expressions or methods taking them as type parameters. Alot
> of noise was made after the introduction of annotations in Tiger about
> marker interfaces no longer being neccessary (in most cases)
>
Ok.
>
> 2) In NeedsIntrinstics, what is value="__@GWT@__"?
It's the value of FeatureName.INTRINSIC, to indicate that a feature
is built into the container and does not need a <requires> manifest
entry.
>
> 3) I don't necessarily have a better alternative, but the Preferences stuff
> seems clunky. The design of SetPrefsFeature.set() raises questions for me,
> like: where do you get the Preference object you're passing in? Does it
> need to be the same one you received during init() or can you construct a
> new one on the fly? Does only the getName() of the passed-in pref matter
> (and if so, maybe this should just take a String?) or does its getValue()
> mean anything?
>
> I wonder if this would be slightly simpler to understand if Preference<T>
> just had a setter?
The number of preferences is fixed, based on the contents of the
Gadget manifest, so having an API that looks like you can define more
preferences at runtime would be a source of confusion. This is why
the SetPrefs API is defined in terms of an instance of a Preference.
I could make the Preference type hierarchy have only package-protected
constructors to prevent mis-use; the only possible way to get an
instance of a Preference at runtime is to call a getter function on
your Gadget's UserPreferences subtype.
As far as having a Preferences.set() function, that would work, but
it would have to take a SetPrefsFeature as an argument. Setting
preferences is an optional API, and I can imagine that many Gadget
implementations simply don't need to configure their own Preferences.
The number of preferences is fixed, based on the contents of the
Gadget manifest, so having an API that looks like you can define more
preferences at runtime would be a source of confusion. This is why
the SetPrefs API is defined in terms of an instance of a Preference.
I could make the Preference type hierarchy have only package-protected
constructors to prevent mis-use; the only possible way to get an
instance of a Preference at runtime is to call a getter function on
your Gadget's UserPreferences subtype.
Perhaps it might be worthwhile to make a Preference type using
datatype="hidden" that can take IsSerializable/Serializable objects
and store them JSON-encoded or RPC-encoded.
Something like:
@PreferenceAttributes(options = Options.JSON)
public Foo foo(); // return deserialized foo
public void setFoo(Foo f); // serialize and set foo
Having it work for Collection<T> would be cool too.
-Ray
I like the general idea, the RPC wire format just isn't stable enough
for long-term persistence. It seems like this particular problem and
many other interop issue would be solved by having a more
general-purpose JSON-like RPC serializer.
This type of JSONization is not trivial:
1 - There are a lot of JSON variants: JSON for ASP, JSON for DWR,
JSPON, etc. What type of JSON will be allowed?
2 - JSON is plain by default, cyclic references are not allowed. An
explicit id attribute would solve this, like the JSPON solution, but
this would override a class field.
3 - Will inheritance be allowed? How? Deserialization of subclasses
requires to know what class must be instantiated. Will a class
identifier be stored in the JSON Object?
It so happens that in the majority of cases, JSON (the real JSON) will
work, because most people are simply storing POJOs or collections of
POJOs, without cycles.
Using the JSON classes directly would work, but pretty much negate the
point of any extension, since you can already do that today with Bob's
classes by using String preferences, Options.HIDDEN. The only point
to adding anything above and beyond string preference would be if the
compiler was going to do the heavy lifting of serialization for you.
-Ray
I've added the Gadgets support on a branch in the GALGWT project.
http://gwt-google-apis.googlecode.com/svn/branches/gadgets/
Once the Linker has been merged into the GWT trunk, this change branch
can be folded into the GALGWT trunk. Until then, you'll have to build
against
http://google-web-toolkit.googlecode.com/svn/changes/bobv/linker/