Extending Entity to provide real POGO like qualities with names attributes

14 views
Skip to first unread message

Jeff

unread,
Jul 11, 2010, 11:51:03 AM7/11/10
to Gaelyk
Hi All,

I was looking at moving over to JDO because my Entities are becoming
quite complex. I thought that by using JDO enhanced classes that would
help bring some order to the chaos that has developed from using the
free form Entity type. Unfortunately, the current implementation of
JDO does not support SUPERCLASS for objects that are derived from some
parent class. This means that if a have a class hierarchy of say the
following:

class A (root of
hierarch
class B extends A
(subclass of A)

When I persist B it's entity type will be B and not A. My requirements
are that if I persist B its entity type will be A which is what
SUPERCLASS inheritance in JDO would provide if it were supported but
like I said the AppEngine doesn't at this time.

This then presents a challenge. How can I maintain the use of Entity
but also provide more organization to them. Can I create specialized
classes derived from Entity such as:

class Person extends
Entity{
String firstName
String lastName
Person(String
entityName, String fName, String lName){

super(entityName)
firstName =
fName
lastName = lName
}
}

class PersonWithAddress
extends Person{
String city
String
stateOrProvince
String
zipOrLocalCode

PersonWithAddress(String entityName, String fName, String lName,
String c, String
s, String z)
){

super(entityName,fName,lName)
city = c
stateOrProvince
= s
zipOrLocalCode =
z
}
}

// usage
def person = new
Person('Person','Fred','Flintstone')
def personWithAddress =
new PersonWithAddress('Person','Fred','Flintstone',
'Bedrock',
'Bedrock', '11111')
person.save() // saves
person as a Person entity

personWithAddress.save() // saves personWithAddress as a Person entity

Does the above work? Has anyone done something along similar lines?
Does this make sense? So many questions, so little time :)

I could of course make the POGOs groovier by passing hasmaps to the
constructors instead of using positional sensitive parameters.

Thanks in advance to your replies.

Jeff

Jeff Schwartz

unread,
Jul 12, 2010, 6:58:16 AM7/12/10
to Gaelyk
I wrote a simple test and discovered that this wont be possible because Entity is marked as final :)

I am now looking at using JDO again but with embedded classes. I think it will work but I need to test it.

Jeff


--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes Gaelyk.
Pour envoyer un message à ce groupe, adressez un e-mail à gae...@googlegroups.com.
Pour vous désabonner de ce groupe, envoyez un e-mail à l'adresse gaelyk+un...@googlegroups.com.
Pour plus d'options, consultez la page de ce groupe : http://groups.google.com/group/gaelyk?hl=fr




--
--
Jeff

Guillaume Laforge

unread,
Jul 12, 2010, 7:05:46 AM7/12/10
to gae...@googlegroups.com
JDO, with its initialization cost is perhpas not the best solution, is it?
You've not looked at Objectify and Twig, which are often mentioned?

I was a bit lazy hacking some code to show you that, but... it's
possible to use type coercion to convert your own classes to other
classes.
So you could have your POGO hierarchy, like Person, PersonWithAddress,
and then do person as Entity.
And vice-versa, have the reverse operation too, entity as Person.
You need to have a look at the asType(Class) method, that you can add
dynamically yourself, or in a base class for example.

--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

Jeff Schwartz

unread,
Jul 12, 2010, 7:20:24 AM7/12/10
to gae...@googlegroups.com
I hadn't heard of them and will definitely take a look at them and also investigate  type coercion. Thanks, Guillaume.

Guillaume Laforge

unread,
Jul 12, 2010, 7:36:58 AM7/12/10
to gae...@googlegroups.com
Being less lazy now, here's what it could look like:
http://groovyconsole.appspot.com/script/169001

Use GAE's own Entity class, of course.

And notice that I'm using a Groovy "category".
And a Gaelyk plugin allows you to add your own category, so that it's
transparent (ie. you don't even have to say use(MyCat) {} at all, it's
just available by default in all your groovlets and templates).

So you can create a plugin for that.
You'll have your own type hierarchy, and will be able to easily
convert back'n forth between that and the low-level Entity class.

I've copied it here too:

class Entity {
Map props = [:]
}

class Person {
String name
int age
}

class PersonWithAddress extends Person {
String address
}

def p = new Person(name: "Guillaume", age: 33)
def pa = new PersonWithAddress(name: "Marion", age: 2, address: "Paris")

class CoercionCategory {
static asType(Object self, Class clazz) {
if (clazz == Entity) {
def e = new Entity()
self.properties.each { k, v ->
if (!(k in ['class', 'metaClass'])) {
e.props[k] = v
}
}
return e
} else if (self.class == Entity) {
return clazz.newInstance(self.props)
} else throw new RuntimeException("Can't coerce
${self.class.name} into ${clazz}")

}
}

use (CoercionCategory) {
def pEntity = p as Entity
def paEntity = pa as Entity

assert pEntity.props.name == "Guillaume"
assert pEntity.props.age == 33

assert paEntity.props.name == "Marion"
assert paEntity.props.age == 2
assert paEntity.props.address == "Paris"

def person = new Entity(props: [name: "Guillaume", age: 33]) as Person
def personWA = new Entity(props: [name: "Marion", age: 2,
address: "Paris"]) as PersonWithAddress

assert person.name == "Guillaume"
assert person.age == 33

assert personWA.name == "Marion"
assert personWA.age == 2
assert personWA.address == "Paris"

Guillaume Laforge

unread,
Jul 12, 2010, 7:37:40 AM7/12/10
to gae...@googlegroups.com
Thinking about it, perhaps it's something I could even add by default
to Gaelyk :-)
But experiment with a plugin with this kind of category, and tell me
how it suits your needs.

Jeff Schwartz

unread,
Jul 12, 2010, 8:10:00 AM7/12/10
to gae...@googlegroups.com
Thank you Guillaume. I know how busy you are and appreciate you taking the time on this. I love the category idea. It is simple and groovieish. However, the problem is that all my datastore code is in named packages (and hence compiled) and the plugin system only makes plugin functionality available to groovlets (n the war/WEB-INF/groovy folder ) and templates (in the war folder). If this weren't the current restriction I would love to use it but I see a benefit in modeling services in packages and having them precompiled. Is there any way to get around this restriction with plugins or will that have to wait for Java 7 and Gaelyk precompilation?

Guillaume Laforge

unread,
Jul 12, 2010, 9:21:08 AM7/12/10
to gae...@googlegroups.com
You can use the category in your pre-compiled Groovy classes as well.
use(MyCategory) { /* do something */ }

If you use groovlets and templates, but delegate to pre-compiled
Groovy classes, I think you don't even need the use(MyCategory) {}
stuff, as automatically everything will be under that category, under
the scope of the request, in that thread.

And categories have nothing to do with package (or absence thereof).

Jeff Schwartz

unread,
Jul 12, 2010, 9:53:40 AM7/12/10
to gae...@googlegroups.com
Hi,

I familiarized myself a little with the plugin system by reading the doc on the gaelyk site. I think I understand how it works, both on the development side and the consumer side.

So I can implement a plugin to provide the use category functionality in groovlets and templates and its functionality will also be available in my compiled groovy classes as well? It is this last part which is throwing me :(.

How will its functionality be available in my packaged/compiled classes if gaelyk's binding only applies to groovlets and templates? If I do use(MyCategory) { /* do something */ } in my packaged classes how will the category get resolved? Wont the compiler complain about not being able to resolve it?

Sorry if the answer to this is obvious :)

Guillaume Laforge

unread,
Jul 12, 2010, 9:59:45 AM7/12/10
to gae...@googlegroups.com
Hi,

On Mon, Jul 12, 2010 at 15:53, Jeff Schwartz <jeffts...@gmail.com> wrote:
> Hi,
>
> I familiarized myself a little with the plugin system by reading the doc on
> the gaelyk site. I think I understand how it works, both on the development
> side and the consumer side.
>
> So I can implement a plugin to provide the use category functionality in
> groovlets and templates and its functionality will also be available in my
> compiled groovy classes as well? It is this last part which is throwing me
> :(.

Groovy is a dynamic language, so there's always a runtime aspect to
any method call, even if the code is pre-compiled.

If a request comes in, to a groovlet or template, the code in those
scripts will be "under" the Gaelyk category, and your plugins'
categories.
The code that is called from within those groovlets and templates will
also fall under the categories.
So if you call your services or whatever from those artifacts, they
will "see" the new behaviour provided by the categories.

> How will its functionality be available in my packaged/compiled classes if
> gaelyk's binding only applies to groovlets and templates?

The bindings are another story.
The binding variables won't be available.
So you won't be able to call datastore, etc, but instead have to use
DatastoreServiceFactory.datastoreService.
BUT, the methods added to DatastoreService through the categories will
be available.

> If I do
> use(MyCategory) { /* do something */ } in my packaged classes how will the
> category get resolved? Wont the compiler complain about not being able to
> resolve it?

Nope.

> Sorry if the answer to this is obvious :)

Groovy newbieness applied ;-)
But don't worry, it's not a bad disease to have, LOL :-)

Guillaume

Jeff Schwartz

unread,
Jul 12, 2010, 10:13:44 AM7/12/10
to gae...@googlegroups.com
Great. This will be perfect then. I will play around with it and follow-up here afterward. I looked at objectify and twig and I thought objectify to be the better of the 2 but if I can avoid using either then all the better. I want to keep things as simple as possible and your solution does just that. I hadn't previously seen any value in my using the plugin system prior to this but this new use has certainly served to open my eyes that much wider to its value as well as the dynamic nature of groovy itself.

Thanks so much Guillaume.

Jeff Schwartz

unread,
Jul 12, 2010, 6:25:27 PM7/12/10
to gae...@googlegroups.com
Hi Guillaume,

I am trying to figure out how to actually create the plugin. I've read the docs but I am still confused. Do I need to create a separate project in Eclipse for the plugin and using Eclipse what project type should I use and how then do I use that project's war in my appengine app? Are there any concrete examples of a plugin that I can download into eclipse?

Thanks.

Jeff

Jeff Schwartz

unread,
Jul 12, 2010, 6:27:09 PM7/12/10
to gae...@googlegroups.com
By the way, I am using Eclipse 3.6 (Helios) with the GAE and Groovy plugins.
--
--
Jeff

Guillaume Laforge

unread,
Jul 12, 2010, 6:38:24 PM7/12/10
to gae...@googlegroups.com
I'm soon heading to bed (soon 1am here).
No need to create another project.
Just add the plugins.groovy file, your plugin descriptor, etc, as
advertised in the tutorial, everything in your own project.

Jeff Schwartz

unread,
Jul 12, 2010, 6:42:09 PM7/12/10
to gae...@googlegroups.com
OK, thank you and goodnight :)

Marcel Overdijk

unread,
Jul 13, 2010, 10:46:24 AM7/13/10
to Gaelyk
Using Objectify or Twig is very straightforward imo.



On Jul 12, 4:13 pm, Jeff Schwartz <jefftschwa...@gmail.com> wrote:
> Great. This will be perfect then. I will play around with it and follow-up
> here afterward. I looked at objectify and twig and I thought objectify to be
> the better of the 2 but if I can avoid using either then all the better. I
> want to keep things as simple as possible and your solution does just that.
> I hadn't previously seen any value in my using the plugin system prior to
> this but this new use has certainly served to open my eyes that much wider
> to its value as well as the dynamic nature of groovy itself.
>
> Thanks so much Guillaume.
>
> On Mon, Jul 12, 2010 at 9:59 AM, Guillaume Laforge <glafo...@gmail.com>wrote:
>
>
>
> > Hi,
>
> > On Mon, Jul 12, 2010 at 15:53, Jeff Schwartz <jefftschwa...@gmail.com>
> > > On Mon, Jul 12, 2010 at 9:21 AM, Guillaume Laforge <glafo...@gmail.com>
> > > wrote:
>
> > >> You can use the category in your pre-compiled Groovy classes as well.
> > >> use(MyCategory) { /* do something */ }
>
> > >> If you use groovlets and templates, but delegate to pre-compiled
> > >> Groovy classes, I think you don't even need the use(MyCategory) {}
> > >> stuff, as automatically everything will be under that category, under
> > >> the scope of the request, in that thread.
>
> > >> And categories have nothing to do with package (or absence thereof).
>
> > >> On Mon, Jul 12, 2010 at 14:10, Jeff Schwartz <jefftschwa...@gmail.com>
> > >> wrote:
> > >> > Thank you Guillaume. I know how busy you are and appreciate you taking
> > >> > the
> > >> > time on this. I love the category idea. It is simple and groovieish.
> > >> > However, the problem is that all my datastore code is in named
> > packages
> > >> > (and
> > >> > hence compiled) and the plugin system only makes plugin functionality
> > >> > available to groovlets (n the war/WEB-INF/groovy folder ) and
> > templates
> > >> > (in
> > >> > the war folder). If this weren't the current restriction I would love
> > to
> > >> > use
> > >> > it but I see a benefit in modeling services in packages and having
> > them
> > >> > precompiled. Is there any way to get around this restriction with
> > >> > plugins or
> > >> > will that have to wait for Java 7 and Gaelyk precompilation?
>
> > >> > On Mon, Jul 12, 2010 at 7:36 AM, Guillaume Laforge <
> > glafo...@gmail.com>
> > jefftschwa...@gmail.com>
> > >> >> wrote:
> > >> >> > I hadn't heard of them and will definitely take a look at them and
> > >> >> > also
> > >> >> > investigate  type coercion. Thanks, Guillaume.
>
> > >> >> > On Mon, Jul 12, 2010 at 7:05 AM, Guillaume Laforge
> > >> >> > <glafo...@gmail.com>
> > >> >> > wrote:
>
> > >> >> >> JDO, with its initialization cost is perhpas not the best
> > solution,
> > >> >> >> is
> > >> >> >> it?
> > >> >> >> You've not looked at Objectify and Twig, which are often
> > mentioned?
>
> > >> >> >> I was a bit lazy hacking some code to show you that, but... it's
> > >> >> >> possible to use type coercion to convert your own classes to other
> > >> >> >> classes.
> > >> >> >> So you could have your POGO hierarchy, like Person,
> > >> >> >> PersonWithAddress,
> > >> >> >> and then do person as Entity.
> > >> >> >> And vice-versa, have the reverse operation too, entity as Person.
> > >> >> >> You need to have a look at the asType(Class) method, that you can
> > >> >> >> add
> > >> >> >> dynamically yourself, or in a base class for example.
>
> > >> >> >> On Mon, Jul 12, 2010 at 12:58, Jeff Schwartz
> > >> >> >> <jefftschwa...@gmail.com>
> > >> >> >> wrote:
> > >> >> >> > I wrote a simple test and discovered that this wont be possible
> > >> >> >> > because
> > >> >> >> > Entity is marked as final :)
>
> > >> >> >> > I am now looking at using JDO again but with embedded classes. I
> > >> >> >> > think
> > >> >> >> > it
> > >> >> >> > will work but I need to test it.
>
> > >> >> >> > Jeff
>
> > >> >> >> > On Sun, Jul 11, 2010 at 11:51 AM, Jeff <jefftschwa...@gmail.com
> ...
>
> read more »

Jeff Schwartz

unread,
Jul 13, 2010, 12:26:16 PM7/13/10
to gae...@googlegroups.com
Yes, they are. I have read each libs docs and they are very straight forward. I think though that the use method along with category classes provided via the plugin system is also very straight forward now that I understand how the plugins are actaully created.

This bring me to a slight critique of the plugin documentation. I've asked another developer to look at it and they too were confused by it. We both agreed that the docs make it appear that a plugin is provided via a war and that to develop it it requires a project structure as per the diagram. I think it would be worth mentioning in the docs that this is not the case, that a plugin is just a bunch of files as is accurately described in the docs and these files go in certain places in your application's folders in order to be used as is also accurately described in the docs.

Other than that, I love the simplicity of the plugin system. It's as simple as just dropping the right file into the right directory. And I think if the docs made it that clear it would help alleviate some of the confusion that I and future developers might encounter.

 KISS to me is almost a mantra :)

Jeff

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes Gaelyk.
Pour envoyer un message à ce groupe, adressez un e-mail à gae...@googlegroups.com.
Pour vous désabonner de ce groupe, envoyez un e-mail à l'adresse gaelyk+un...@googlegroups.com.
Pour plus d'options, consultez la page de ce groupe : http://groups.google.com/group/gaelyk?hl=fr




--
--
Jeff

Guillaume Laforge

unread,
Jul 13, 2010, 1:51:34 PM7/13/10
to gae...@googlegroups.com
On Tue, Jul 13, 2010 at 16:46, Marcel Overdijk <marcelo...@gmail.com> wrote:
> Using Objectify or Twig is very straightforward imo.

I'll have to play with them some day for the fun, as they sound interesting.

Guillaume Laforge

unread,
Jul 13, 2010, 1:54:12 PM7/13/10
to gae...@googlegroups.com
On Tue, Jul 13, 2010 at 18:26, Jeff Schwartz <jeffts...@gmail.com> wrote:
> Yes, they are. I have read each libs docs and they are very straight
> forward. I think though that the use method along with category classes
> provided via the plugin system is also very straight forward now that I
> understand how the plugins are actaully created.

Thanks :-)

> This bring me to a slight critique of the plugin documentation. I've asked
> another developer to look at it and they too were confused by it. We both
> agreed that the docs make it appear that a plugin is provided via a war and

Via a zip, I would say, for distribution purpose, if people want to
share their plugins.
But it's not necessarily mandatory :-)
You can indeed just put the right files in the right places too! (as
you did and figured out)

> that to develop it it requires a project structure as per the diagram. I
> think it would be worth mentioning in the docs that this is not the case,
> that a plugin is just a bunch of files as is accurately described in the
> docs and these files go in certain places in your application's folders in
> order to be used as is also accurately described in the docs.

Exactly.
So the doc can be improved to make things clearer.

> Other than that, I love the simplicity of the plugin system. It's as simple
> as just dropping the right file into the right directory. And I think if the
> docs made it that clear it would help alleviate some of the confusion that I
> and future developers might encounter.

You know, I highly welcome even documentation contributions ;-)))

>  KISS to me is almost a mantra :)

On first read, I read "KISS me is almost a mantra", and I was a bit
confused that I really had to kiss you, LOL ;-D

Guillaume

--

Jeff Schwartz

unread,
Jul 13, 2010, 2:52:05 PM7/13/10
to gae...@googlegroups.com
That was Keep It Sweet and Simple lol also known as the KISS principle. I am glad you reread it :0)

I will go through the doc for plugin and get back to you with a suggestion or 2.

Thanks Guillaume.

Guillaume Laforge

unread,
Jul 13, 2010, 4:02:39 PM7/13/10
to gae...@googlegroups.com
On Tue, Jul 13, 2010 at 20:52, Jeff Schwartz <jeffts...@gmail.com> wrote:
> That was Keep It Sweet and Simple lol also known as the KISS principle. I am
> glad you reread it :0)

Don't worry, I knew what KISS meant, but I'm so used to "speed
reading" (my tons of daily emails) that sometimes you get some bad
reads :-)

> I will go through the doc for plugin and get back to you with a suggestion
> or 2.

Thank you!

Jeff Schwartz

unread,
Jul 13, 2010, 6:23:48 PM7/13/10
to gae...@googlegroups.com
I took a speed reading class but the instructor read so fast that the class ended 15 minutes after it started... badabing!

OK. The documentation isn't that bad. It is just missing some details and hints that would make things a little more obvious:

1) Show the plugins.groovy and routes.groovy files in the WEB-INF folder in the Gaelyk project diagram. They are currently absent from the diagram.

2 Put a star or some other icon next to the mandatory plugins folder and the 2 mandatory plugin files (plugins.groovy and the plugin descriptor file) in the diagram. This will help show that one just needs to mix in in these files with the rest of their own project's files.

Everything else is pefecto mundo!

Jeff Schwartz

unread,
Jul 13, 2010, 6:37:13 PM7/13/10
to gae...@googlegroups.com
Just one more thing. In the How To Distribute section of the plugin doc I think it is misleading to say that one would just unzip the distro into their war. I don't know about linux or apple os but that wont work under windows where you will be prompted if you want to replace folders and files that already exist.
--
--
Jeff

Guillaume Laforge

unread,
Jul 13, 2010, 7:17:20 PM7/13/10
to gae...@googlegroups.com
Thanks for the suggestions Jeff.
I've made some changes to the tutorial, and I'll update the site for
the next version probably.
I hope it'll address your concerns.
Thanks again for the ideas of improvements!

Guillaume

Jeff Schwartz

unread,
Jul 13, 2010, 7:27:00 PM7/13/10
to gae...@googlegroups.com
It's the least I can do.

Jeff

unread,
Jul 21, 2010, 9:01:04 AM7/21/10
to Gaelyk
I've done a total 180 on this. Using category worked well but it meant
that I would still have to code all the boilerplate datastore api code
myself. If I could avoid having to do that then all the better. I then
went about reevaluating the available options and decided to use
Objectify as it appears to be very well maintained and its authors and
committers are very active on their Google Code group. I also like the
fact that their documentation is very well organized and
understandable as is the Objectify API itself.

I've contributed a Gaelyk plugin that provides Objectify support to
Gaelyk applications. You can download its distro from
http://code.google.com/p/gaelyk-objectify-plugin/downloads/list.

Jeff

On Jul 13, 12:26 pm, Jeff Schwartz <jefftschwa...@gmail.com> wrote:
> Yes, they are. I have read each libs docs and they are very straight
> forward. I think though that the use method along with category classes
> provided via the plugin system is also very straight forward now that I
> understand how the plugins are actaully created.
>
> This bring me to a slight critique of the plugin documentation. I've asked
> another developer to look at it and they too were confused by it. We both
> agreed that the docs make it appear that a plugin is provided via a war and
> that to develop it it requires a project structure as per the diagram. I
> think it would be worth mentioning in the docs that this is not the case,
> that a plugin is just a bunch of files as is accurately described in the
> docs and these files go in certain places in your application's folders in
> order to be used as is also accurately described in the docs.
>
> Other than that, I love the simplicity of the plugin system. It's as simple
> as just dropping the right file into the right directory. And I think if the
> docs made it that clear it would help alleviate some of the confusion that I
> and future developers might encounter.
>
>  KISS to me is almost a mantra :)
>
> Jeff
> On Tue, Jul 13, 2010 at 10:46 AM, Marcel Overdijk
> <marceloverd...@gmail.com>wrote:
> ...
>
> read more »
Reply all
Reply to author
Forward
0 new messages