|
ObjectifyWithGWT
Using Objectify with Google Web Toolkit
fr , en Got CRUD?This must be the most common "design pattern" when developing web applications:
However, there is often an impedance mismatch between the data tier and the presentation tier in web development tools. Because, for example, Hibernate or JDO proxies cannot be passed through GWT RPC, developers are often forced to construct Data Transfer Objects to shuffle data back and forth. Sometimes this is a good idea (say, when you have sophisticated program logic in your entities) but sometimes this is a laborious pain in the arse. No More DTOsWith a tiny amount of care, your entity objects can be passed through GWT serialization and used as-is in the presentation layer. Simply write your entity as if it is a GWT client class!
Simply add this to your module.gwt.xml: <inherits name="com.googlecode.objectify.Objectify" /> You can now manipulate your entity objects in GWT and seamlessly pass them back and forth to the server through GWT-RPC. Objectify enables you to use Key<?>, Key (the datastore version), and all the datastore basic types (Link, Email, GeoPt, etc) in your client code. TransienceA careful distinction must be made between @Transient (the javax.persistence annotation) fields and transient (the Java keyword) fields:
AnnotationsIn general GWT will ignore annotation on your classes. It is not necessary to include them in your gwt include modules. Annotations like @Entity, @LoadAlso, and the like will be ignored during GWT serialization. Client-Side AccessNone of the Objectify action objects (Objectify, ObjectifyService, ObjectifyFactory, DAO) can be used from GWT client code. Basically only entities (and their associated data (types) are allowed to cross the GWT Service boundaries). As of Objectify 3.0, constructing Key<?> objects client-side is now considerably more difficult. You can only useĀ one constructor, the one which takes a native datastore Key. The other constructors do not exist in the Key<?> super-source. See this discussion. ExampleA very simple example can be found here. Request FactoryDavid Chandler wrote an article on Using Objectify with RequestFactory. | |
This must be the most common request in relation to new 'things' on the web.
Please, please, please create a simple, fully working, example. This will save hours of frustration trying to understand your documentation when a working example makes it so much easier. Maybe just populate a grid with a list of cars, edit one, and save it. It's impossible to adopt Objectify if we can't get it to work.
Thanks
I didn't have much trouble getting it to work pretty generically but it was tricky kinda.
The big thing is any entity you want to pass back has to implement the GWT IsSerializable? interface and follow its rules (have a blank constructor, etc).
The nice part about that is you can make your RPC servlet methods generic using Key<IsSerializable> and IsSerializable?.
The way I have it set up is I have a Data servlet (RPC) that GWT interacts with. It passes Keys or Strings to search for or whatever to the various methods, and there're a couple 'getAll' methods for some objects e.g. Map<Key<IsSerializable>, IsSerializable?> getAll(Class class) or something along those lines.
this is a really nice tool for gwt. but please create a simple example! it's so much easier to understand objectify by playin around with an example than reading a documentation!
thank you!
it sounds good but need an example
Where is an Example? please!
Mmm, you say no more DTO's. Looks true when you only use primitive types or build-in Objectify classes, but what about loading an entity in an entity?
class Contact { ... Key<Address> address }
When I show a Contact, I want to show the Address as well, but that's impossible. They key itsself is terribly useless on the GWT side, so I'll have to build a DTO anyway, right?
There are a couple ways around this. One is to build a DTO, another is to include a @Transient Address object on your entity and populate it before you send your Contact to the client.
By the way, unless you're deconflicting Address objects and sharing them among Contacts, you almost always want to use @Embedded or @Serialized for little dependent objects like this. This is one area where GAE-based application design and RDBMS-based application design differs.
Yes I doubted including a @Transient object, however then it makes slightly more sense to make a Dto anyway. I'll try the @Embedded way, tnx.
A couple of working examples can be found here:
http://www.fishbonecloud.com/2010/11/use-objectify-to-store-data-in-google.html
There is a change in Objectify version 3.0, which affects the creation of Key<T> objects on client side. This change is discussed here:
http://groups.google.com/group/objectify-appengine/browse_thread/thread/5d6171c6a4956719/2d5004df1d7e20ee?hl=en_US&lnk=gst&q=polymorphism+gwt#2d5004df1d7e20ee
You'll receive a GWT compiler error saying: "The constructor Key<T>(Class<T>, ...) is undefined"
I may not be quite knowledgable enough to understand why the Key<T>(Class<T>, ...) constructor doesnt work anymore. Is there some alternative way of setting the key attribute for my objects? For example, I have this code inside my "Child.java" constructor: public void setParent(String key) { parent = new Key<Parent>(Parent.class, key); } How do i refactor that to work with 3.0? or am i just better sticking with 2.2.3 and waiting for these issues to be fixed in a future release
You could store the key as a string instead of an actual key object if you want to keep that design. Then you can construct the key on the server when you need it.
Hi,
Objectify 3.0.1 with GWT 2.4, GAE 1.5.5
Development mode exception
java.io.NotSerializableException?: com.googlecode.objectify.impl.ObjectifyImpl?
while it works fine in production mode.
Any suggestion...