Hi:

While exploring list-property and merge-join from this talk
http://code.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html 
i concur with your value proposition.

Initially, i plan to build a singleton long id generator to reproduce
and self-manage datastore Key of the application entity graph. Then use
the low-level datastore to create list-property and merge-join: User ->
Message -> MessageIndex or User -> Activity -> ActivityIndex (of
different properties such as Interest, Checkout, MesurableEvent, etc).
Please:
  1) Explain the difference from objectify-appengine with this simple-
mind approach in the immediate and long term project.
  2) It is excellent to show an example of both list-property and merge-
join as well as best practices to leverage the zig-zag search of the app
engine.
  3) Configuration with appengine-java-sdk if there is any significant
change beside a small jar from objectify-appengine.

Thanks

Duong BaTien
DGBROUPS and BudhNet


On Wed, 2010-01-20 at 23:45 -0800, Marcel Overdijk wrote:
> This really looks great!
> 
> On 13 jan, 18:28, Jeff Schnitzer <[email protected]> wrote:
> > http://code.google.com/p/objectify-appengine/
> >
> > I probably should have called this project "Goldilocks", because it's
> > a little bit how I feel.  Despite being a longtime Hibernate user
> > (since the 1.0 days), the JDO/JPA abstraction just doesn't make me
> > happy on appengine - it's too big, too complicated, and too far
> > removed from the nature of the beast.  The low-level API has an
> > elegant simplicity, but it lacks type safety.  I tried the
> > alternatives - Siena, Twig, SimpleDS, and Slim3.  There are good
> > things I can say about these projects but none were "just right" for
> > me.
> >
> > So, in time-honored tradition, I wrote my own and now I'm offering it
> > to the world.  Here is what "just right" means to me.  Maybe it's just
> > right for you too:
> >
> >  * An interface that reflects the four fundamental datastore
> > operations - get, put, delete, query - including their batch variants.
> >
> >  * Persisting real typed POJO classes - no detaching, no lifecycle,
> > serialize at will.
> >
> >  * Keys inObjectifyare generified and typed.  Instead of Key you use
> > OKey<MyEntity>.  This generic typing extends to OQuery<MyEntity> and
> > OPreparedQuery<MyEntity>.
> >
> >  * Because Kind ~= POJO Class, Key should not be used for an object's
> > id.  The object's id and its (optional) parent plus the class is
> > complete; an entity that has a Key identifier contains a redundant
> > (and potentially inaccurate) kind.  Nevertheless, a Key is necessary
> > for loading entities or referencing entities, and forms a fundamental
> > part of the API.  This dichotomy is something I don't feel had been
> > done right yet.
> >
> >  * Queries are modeled after the human-friendly GAE/Python Query
> > class:  query.filter("field >", 123).sort("-field").  You can filter
> > and sort on id fields almost as if they are normal properties.
> >
> >  * Transactional behavior is contained within theObjectifyinterface
> > (analogous to DatastoreService) instance rather than a thread local.
> > You can easily have several transactions (or nontransactional
> > sessions) running concurrently.
> >
> >  * You can use your entities in GWT-RPC without modification - even
> > with OKey fields.  They're just POJOs and they serialize fine.
> >
> >  * Builtin facilities to help with renaming fields and transforming
> > data during schema migration.
> >
> >  * Configurable automatic retries for DatastoreTimeoutExceptions
> > (finally get rid of the 0.1% trickle of failures!).
> >
> >  * Zero external dependencies - no Spring, no Guice, not even a logger
> > (it just wasn't necessary). Just one lonely 36K jar.
> >
> >  *Objectifywill work nicely with your DI framework.  Static
> > singletons are not required.
> >
> >  * Negligible impact on cold start time.
> >
> >  * Thorough unit test suite.
> >
> >  * Simple, easy-to-read, well-documented code.  Not counting the
> > tests, there's actually only ten source files plus three annotations.
> > About 2,000 lines including whitespace and javadocs.
> >
> > There is ample documentation 
> > athttp://code.google.com/p/objectify-appengine/, but some code examples
> > should make this clear:
> >
> > Basic operations:
> >
> > @Entity
> > class Car {
> >    @Id String vin; // Can be Long, long, or String
> >    String color;
> >    Date registered;
> >
> > }
> >
> > Objectifyofy = ObjectifyService.begin();
> > ofy.put(new Car("123123", "red"));
> > Car c = ofy.get(Car.class, "123123");
> > ofy.delete(c);
> >
> > OQuery<Car> query = ObjectifyService.newQuery(Car.class);
> > query.filter("registered <", lastYear).sort("color");
> > List<Car> cars = ofy.prepare(query).asList();
> >
> > Some more sophsticated examples:
> >
> > @Entity
> > class Employee {
> >    @Id long id; // primitive long is never autogenerated
> >    @Parent OKey<Company> employer;
> >
> >    // field getting renamed
> >    @OldName("boss") OKey<Employee> manager;
> >
> >    String firstName;
> >    String lastName;
> >
> >    // we used to store fullName, now we store first and last separately
> >    @OldName("fullName") public void oldWay(String fullName)
> >    {
> >        String[] split = fullName.split(" ");
> >        firstName = split[0];
> >        lastName = split[1];
> >    }
> >
> > }
> >
> > Here's an example of interleaving a transactional session with a
> > nontransactional session:
> >
> > ObjectifyofyNoTxn = ObjectifyService.begin();ObjectifyofyTxn = 
> > ObjectifyService.beginTransaction();
> > try
> > {
> >        Foo f = ofyTxn.get(Foo.class, "k123");
> >        Bar b = ofyNoTxn.get(f.barKey);
> >
> >        if (b.wantsUp())
> >                f.increment();
> >        else
> >                f.decrement();
> >
> >        ofyTxn.put(f);
> >
> >        ofyTxn.getTxn().commit();}
> >
> > finally
> > {
> >        if (ofy.getTxn().isActive())
> >                ofy.getTxn().rollback();
> >
> > }
> >
> > The full docs are here:
> >
> > http://code.google.com/p/objectify-appengine/
> >
> > What doesn't it do?
> >
> >  * It doesn't work with any datastore other than GAE.
> >
> >  * It doesn't manage relationships for you - if you want cascading
> > deletes, collection proxies, and all the advantages and disadvantages
> > of that - you want JDO/JPA.  I find managing this myself pretty easy,
> > and well worth the transparency.
> >
> >  * No support yet for polymorphism.  It won't require major structural
> > changes to add though.
> >
> >  * It doesn't suck.  Or so I am told.
> >
> > Jeff

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" 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-appengine-java?hl=en.


Reply via email to