Fred's methods are rock solid, look near the middle of the page for
the super-source hack needed to make Key happy for the client side.
There are very few restrictions on what can go into the client side,
{file operations and bytecode enhancements, mainly}. To make life
easier, don't try to use any appengine stuff except annotations in
your client package; they are used by the gwt compiler, but never make
it into the actual code. ...And be careful using Long keys, I hear
that you can only retrieve data with long keys using queries, and not
the persistence or entity managers... Something about private
indexing and not being able to use them for root level getObjectById()
s or something. I can't remember, and am too tired and new to
appengine to tell you for sure. Just saying that if your
getObjectById fails, it's because it wants a String or Key key.
There's another problem I'm sure you're about to run into: Bytecode
enhancement. The dataNucleus tool uses Bytecode enhancement to make
objects that can be retrieved from the server, sent to the client,
modified there and then returned to the server and persisted back
without having to manually copy values. It's a sweet enhancement, but
like I said before, these enhancements can fail on GWT {because it
uses an Object[] with various datatypes in it, and GWT can't get
access to it because it's an "invisible" field}. The solution is to
make your entities non-detachable:
@PersistenceCapable(identityType = IdentityType.APPLICATION,
detachable = "false")
public class Foo{....}
Of course, this will be a pain, because now you can send the data to
gwt, but it can't put it back into the datastore. Luckily, the
Timelord, Ray Cromwell, has fixed this for us:
http://timepedia.blogspot.com/2009/04/google-appengine-and-gwt-now-marriage.html
I also posted a hack there to make his fix fully bean-compatible, in
case you're using existing code. The code I use internally is a
little different than the piece I posted there, but you get the
drift. You don't need it if you make sure that, for all of your
persistent objects, you define a getValue() setValue() pair, with
identical names. Using isValue() for booleans requires my hack.
If you want to get gwt + appengine datastore running, you have to use
Fred's super-source method on Key, in the client side, and Ray's
reflection-save method on the server-side. Also, if you want a little
more security and smaller transfers across the wire, don't forget to
mark any persistent fields that gwt won't need {like your Keys} with
@Transient. It tells RPC to skip the field, so you can keep sensitive
data where it belongs; out of the browser! {password fields, anyone?}