RR : GWT4Gadgets : Use case / code style

20 views
Skip to first unread message

BobV

unread,
Feb 1, 2008, 7:36:37 PM2/1/08
to Google Web Toolkit Contributors
The patch is relative to the linker change branch, but it should
apply (though not compile) to the current trunk since it's mostly
additions. Please take a look at Hello and HelloPreferences; I'd like
to get comments on the API style. This is a very rough cut, so don't
pay too much attention to the implementation details yet.

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

gadgets_n_mapplets.patch
HelloGadgets_doc.tgz

joster

unread,
Feb 2, 2008, 11:31:07 AM2/2/08
to Google Web Toolkit Contributors
Hi Bob-

I am not qualified enough to make comments on your API style, but have
few questions about this package:
- Is GWT4Gadgets going to be part of standard GWT release (say 1.5)?
Will it serve as example for how to create gadgets using GWT?
- Just trying to understand the motivation of this package
- Can you elaborate on dependency-injection style API?

It would be great if this was natively integrated as part of GWT
package, so users can very easily create gadgets which can be put in
iGoolge, and myriad of other social web-pages (Facebook, MySpace, ...)

Joster

On Feb 1, 4:36 pm, BobV <b...@google.com> wrote:
> The patch is relative to the linker change branch, but it should
> apply (though not compile) to the current trunk since it's mostly
> additions. Please take a look at Hello and HelloPreferences; I'd like
> to get comments on the API style. This is a very rough cut, so don't
> pay too much attention to the implementation details yet.
>
> A hello-world iGoogle gadget:
> http://www.google.com/ig/adde?source=ignsrc1&moduleurl=http%3A//vawte...
>
> 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://vawte...
>
> Thanks.
>
> --
> Bob Vawter
> Google Web Toolkit Team
>
> gadgets_n_mapplets.patch
> 112KDownload
>
> HelloGadgets_doc.tgz
> 74KDownload

BobV

unread,
Feb 2, 2008, 1:54:34 PM2/2/08
to Google-Web-Tool...@googlegroups.com
On Feb 2, 2008 8:31 AM, joster <joste...@gmail.com> wrote:
> - Is GWT4Gadgets going to be part of standard GWT release (say 1.5)?
> Will it serve as example for how to create gadgets using GWT?

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.

John Webster

unread,
Feb 2, 2008, 2:07:12 PM2/2/08
to Google-Web-Tool...@googlegroups.com
Perfect! Thanks Bob.

I think this will be a 'very useful' feature for the user-community and will demonstrate the easy and power of GWT. Just like how GWT is address browser idiosyncrasies seamlessly, this feature will extend into the domain of gadgets integration with social network. An awesome project!

Thanks again. Look forward to seeing it in production.

Ray Cromwell

unread,
Feb 5, 2008, 2:01:23 AM2/5/08
to Google-Web-Tool...@googlegroups.com
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)

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

John Tamplin

unread,
Feb 5, 2008, 2:58:16 AM2/5/08
to Google-Web-Tool...@googlegroups.com
On Feb 5, 2008 2:01 AM, Ray Cromwell <cromw...@gmail.com> wrote:
 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)

Take a look at the actual interfaces -- they each provide a method like setIntrinsics(IntrinsicFeature feature), so when you add NeedIntrinsics you get that call with the object for the feature you added -- basically dependency injection by the generator.  All these settersare called before your init method, so in it you can call methods on the feature objects you were injected with.

--
John A. Tamplin
Software Engineer, Google

Ray Cromwell

unread,
Feb 5, 2008, 3:19:31 AM2/5/08
to Google-Web-Tool...@googlegroups.com
Oh right, I see it now. The first time I glanced at it, I saw only the
static inner class, and not the interface method at the tail end
(NeedsMaps)

-Ray

Bob Vawter

unread,
Feb 5, 2008, 3:31:44 PM2/5/08
to Google-Web-Tool...@googlegroups.com, Google-Web-Tool...@googlegroups.com
Hi 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)
>

Scott Blum

unread,
Feb 5, 2008, 7:43:31 PM2/5/08
to Google-Web-Tool...@googlegroups.com
Hey Bob,

Some initial thoughts on the API design.

1) Possible bikeshed: what do you think about the NeedsFoo interfaces using "initFooFeature" as opposed to "setFooFeature"?  I had been kind of thinking it as I went along, then I ran across NeedSetPrefts.setSetPrefsFeature. :)

2) In NeedsIntrinstics, what is value="__@GWT@__"?

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?

--Scott

BobV

unread,
Feb 7, 2008, 1:05:47 PM2/7/08
to Google-Web-Tool...@googlegroups.com
On Feb 5, 2008 4:43 PM, Scott Blum <sco...@google.com> wrote:
> 1) Possible bikeshed: what do you think about the NeedsFoo interfaces using
> "initFooFeature" as opposed to "setFooFeature"? I had been kind of thinking
> it as I went along, then I ran across NeedSetPrefts.setSetPrefsFeature. :)

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.

Scott Blum

unread,
Feb 7, 2008, 1:46:25 PM2/7/08
to Google-Web-Tool...@googlegroups.com
On Feb 7, 2008 1:05 PM, BobV <bo...@google.com> wrote:
  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.

That seems like a good idea to me.  I think it will probably also be clearer with some more doc on the SetPrefs types.

Scott


Ray Cromwell

unread,
Feb 7, 2008, 2:06:01 PM2/7/08
to Google-Web-Tool...@googlegroups.com
One of the things I've seen people frequently do with Gadget
preferences is store JSONized objects as strings to allow more complex
information to be saved via setprefs. OpenSocial takes this to an
extreme where apps store serialized object trees into the personal app
data.

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

BobV

unread,
Feb 7, 2008, 2:34:04 PM2/7/08
to Google-Web-Tool...@googlegroups.com
On Feb 7, 2008 11:06 AM, Ray Cromwell <cromw...@gmail.com> wrote:
> 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.

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.

Andrés Testi

unread,
Feb 7, 2008, 2:43:57 PM2/7/08
to Google Web Toolkit Contributors
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?

-- Andrés


On 7 feb, 16:06, "Ray Cromwell" <cromwell...@gmail.com> wrote:
> One of the things I've seen people frequently do with Gadget
> preferences is store JSONized objects as strings to allow more complex
> information to be saved via setprefs. OpenSocial takes this to an
> extreme where apps store serialized object trees into the personal app
> data.
>
> 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
>

John Tamplin

unread,
Feb 7, 2008, 2:57:17 PM2/7/08
to Google-Web-Tool...@googlegroups.com
On Feb 7, 2008 2:43 PM, Andrés Testi <andres....@gmail.com> wrote:

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?

I think you can avoid most of these problems by simply saying you have JSONObject stores in preferences, and you don't try and serialize GWT objects.  The developer would write their own code to do what they want with the JSON objects.  Granted, it is more work for them, but at least it doesn't set expectations we  won't be able to meet.

Ray Cromwell

unread,
Feb 7, 2008, 3:23:31 PM2/7/08
to Google-Web-Tool...@googlegroups.com
By using the term JSON, I didn't mean the "official" JSON, but rather,
a string syntax representing the serialized object that can be read
and written to by the same gadget. The format can be completely opaque
in this sense, since only the gadget itself can read and write this
data. There is an exception to this, which is the inter-gadget
Publish/Subscribe stuff that iGoogle supports, but that kind of
messaging can be handed via a more transparent interface if desired.
I agree, cyclical graphs would be problematic for JSON. The real
issue is simply choosing a serialization format that won't break your
gadget if you compile with a future version of GWT, so if we did use
GWT RPC serialization, we'd have to settle on a version that must be
bound with Gadget apps and won't change.

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

Andrés Testi

unread,
Feb 7, 2008, 6:15:33 PM2/7/08
to Google Web Toolkit Contributors
Right, I agree with you now. Since GWT-RPC serialization is based in
JSON, just removing the security preffix ( "////OK" ) Serializable
objects would be stored as JSON.

-- Andrés

On 7 feb, 17:23, "Ray Cromwell" <cromwell...@gmail.com> wrote:
> By using the term JSON, I didn't mean the "official" JSON, but rather,
> a string syntax representing the serialized object that can be read
> and written to by the same gadget. The format can be completely opaque
> in this sense, since only the gadget itself can read and write this
> data. There is an exception to this, which is the inter-gadget
> Publish/Subscribe stuff that iGoogle supports, but that kind of
> messaging can be handed via a more transparent interface if desired.
> I agree, cyclical graphs would be problematic for JSON. The real
> issue is simply choosing a serialization format that won't break your
> gadget if you compile with a future version of GWT, so if we did use
> GWT RPC serialization, we'd have to settle on a version that must be
> bound with Gadget apps and won't change.
>
> 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
>

BobV

unread,
Feb 7, 2008, 10:05:44 PM2/7/08
to Google-Web-Tool...@googlegroups.com, Miguel Méndez, Kelly Norton
On Feb 5, 2008 12:31 PM, Bob Vawter <bo...@google.com> wrote:
> Once I get back into the office, I'll add this as a branch in the
> galgwt project and solicit further feedback.

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/

chris

unread,
Apr 4, 2008, 2:03:47 PM4/4/08
to Google Web Toolkit Contributors
So I've played around with the code for a bit, and I have a question.
Is hosted mode supposed to work with this? It seems to work ok until
I start adding in the Preferences stuff...

Chris

On Feb 7, 8:05 pm, BobV <b...@google.com> wrote:

Miguel Méndez

unread,
Apr 21, 2008, 10:59:47 AM4/21/08
to Google-Web-Tool...@googlegroups.com
Hosted mode won't work well with Gadgets out of the box because gadgets have to be served from a gadget container which is not available in stock hosted mode.  Bob has mentioned doing things like including Apache's gadget container impl -- we need to do some more research to see how this could be improved.  For now, you will need to use --noserver to make it work.

What problems are you experiencing with preferences?
--
Miguel
Reply all
Reply to author
Forward
0 new messages