Yes, I am back in the race, stupid flu stopped me for almost a week :( Let me post here a working CRUD, based on the information from http://wiki.openbluedragon.org/wiki/index.php/GoogleAppEngine:Datastore and the responses above in this thread so far.
I have the following setup: - OpenBD for GAE - ColdBox 3.0.0.Beta2 - ColdSpring 1.2 I have got my OpenBD up and running in the same way as Paul Kukiel posted over here http://blog.kukiel.net/2009/09/coldfusion-on-google-app-engine-with.html. I had to make some minor tweaks in Coldbox to get it running, and I have not implemented ColdSpring via the plugin of ColdBox (could not get that running either, so pushed that forward in time). For now this setup is running well, let's get over the code. BTW: Checkout the abstract Service, it makes my model a little bit more manageable when implementations of GAE in OpenBD changes in future! Please, let me know what you think of this setup: -------- Bean.cfc -------- Bean.cfc is an abstract bean, that is extended by al of my beans (the data objects). It makes sure that al of my beans got an id property, and a getMemento function. In this getMemento function you see, that I create an instance struct out of the properties from the variables scope. Later, hopefully, the properties which are stored into the datastore come from the defined <cfproperty> properties (Vince???). <cfcomponent displayname="Bean"> <cfset variables.id = "" /> <!--- getMemento ---> <cffunction name="getMemento" access="public" output="false" returntype="struct"> <cfset var local = StructNew() /> <cfset local.instance = StructNew() /> <cfset local.aMetaData = getMetaData(this).properties /> <cfloop from="1" to="#ArrayLen(local.aMetaData)#" index="local.intMetaDataKey"> <cfset local.instance[local.aMetaData[local.intMetaDataKey].name] = variables[local.aMetaData[local.intMetaDataKey].name]> </cfloop> <cfreturn local.instance> </cffunction> <!--- getId ---> <cffunction name="getId" access="public" output="false" returntype="string"> <cfreturn variables.id /> </cffunction> <!--- setId ---> <cffunction name="setId" access="public" output="false" returntype="void"> <cfargument name="id" type="string" required="true" /> <cfset variables.id = arguments.id /> </cffunction> </cfcomponent> ----------- Country.cfc ----------- Country.cfc is my Country bean, extending my abstract Bean <cfcomponent displayname="Country" extends="model.Bean" persistent="true"> <!--- decalre properties for ORM ---> <cfproperty name="id" fieldType="id" generator="uuid" notnull="false" getter="true" setter="true" /> <cfproperty name="countryCode" type="string" length="2" notnull="true" getter="true" setter="true" /> <cfproperty name="tld" type="string" length="2" notnull="true" getter="true" setter="true" /> <cfproperty name="googleAnalyticsAccountNr" type="string" length="12" notnull="false" getter="true" setter="true" /> <cfproperty name="verifyV1" type="string" length="44" notnull="false" getter="true" setter="true" /> <cffunction name="init" access="public" output="false" returntype="Country"> <cfargument name="id" type="string" default="" /> <cfargument name="countryCode" type="string" default="" /> <cfargument name="tld" type="string" default="" /> <cfargument name="googleAnalyticsAccountNr" type="string" default="" / > <cfargument name="verifyV1" type="string" default="" /> <cfscript> variables.id = arguments.id; variables.countryCode = arguments.countryCode; variables.tld = arguments.tld; variables.googleAnalyticsAccountNr = arguments.googleAnalyticsAccountNr; variables.verifyV1 = arguments.verifyV1; return this; </cfscript> </cffunction> <!--- getters and setters ---> </cfcomponent> --------------------------------- Country.cfc (ColdBox Handler CFC) --------------------------------- This is the handler which I use to get a list of my countries, create a new one, edit an existing one, or delete one of them. <cfcomponent extends="coldbox.system.EventHandler" cache="true" cachetimeout="0" output="false"> <!--- remove the cache in development!!! ---> <!--- index ---> <cffunction name="index" access="public" output="false" returntype="void"> <cfargument name="event" required="true"> <cfscript> var rc = arguments.event.getCollection(); rc.aCountries = application.CountryService.getCountries(); arguments.event.setView("admin/country/index"); </cfscript> </cffunction> <!--- editor ---> <cffunction name="editor" access="public" output="false" returntype="void"> <cfargument name="event" required="true"> <cfscript> var rc = arguments.event.getCollection(); rc.Country = application.CountryService.getCountry(event.getValue ("id","")); arguments.event.setView("admin/country/editor"); </cfscript> </cffunction> <!--- save ---> <cffunction name="save" access="public" output="false" returntype="void"> <cfargument name="event" required="true"> <cfscript> var rc = arguments.event.getCollection(); rc.Country = application.CountryService.getCountry(event.getValue ("id","")); populateModel(rc.Country); application.CountryService.saveCountry(rc.Country); flash.put("message", "Country saved!"); setNextEvent("admin.country.index"); </cfscript> </cffunction> <!--- delete ---> <cffunction name="delete" access="public" output="false" returntype="void"> <cfargument name="event" required="true"> <cfscript> var rc = arguments.event.getCollection(); application.CountryService.deleteCountry(event.getValue("id","")); flash.put("message", "Country deleted!"); setNextEvent("admin.country.index"); </cfscript> </cffunction> </cfcomponent> ------------------ CountryService.cfc ------------------ My CountryService.cfc uses functions like entityNew, entityLoad, entitySave, and entityDelete, as implemented in CF9 ORM. I let my Services extend my abstract Service, where I 'translate' the CF9 ORM to the OpenBD GAE implementation as it is right now. When Vince later on implement also the CF9 ORM thingy in OpenBD GAE, I only have to remove the extension of my abstract Service in all my Services ;-) <cfcomponent displayname="CountryService" extends="model.Service"> <!--- init ---> <cffunction name="init" access="public" output="false" returntype="CountryService"> <cfreturn this /> </cffunction> <!--- saveCountry ---> <cffunction name="saveCountry" access="public" output="false" returntype="void"> <cfargument name="Country" type="Country" required="true" /> <cftransaction> <cfset entitySave(arguments.Country) /> </cftransaction> </cffunction> <!--- getCountry ---> <cffunction name="getCountry" access="public" output="false" returntype="Country"> <cfargument name="id" type="string" required="true" /> <cfscript> if (len(arguments.id)) { var Country = entityLoad(name="Country",id=arguments.id); if (not isNull(Country)) { return Country; } } return entityNew("Country"); </cfscript> </cffunction> <!--- getCountries ---> <cffunction name="getCountries" access="public" output="false" returntype="any"> <cfargument name="asQuery" type="boolean" default="false" /> <cfargument name="filterCriteria" type="struct" default="#StructNew() #" /> <cfscript> var aCountries = entityLoad (name="Country",filterCriteria=arguments.filterCriteria); if (arguments.asQuery) { return entityToQuery(aCountries); } return aCountries; </cfscript> </cffunction> <!--- deleteCountry ---> <cffunction name="deleteCountry" access="public" output="false" returntype="void"> <cfargument name="id" type="string" required="true" /> <cfset var Country = 0 /> <cftransaction> <cfset Country = getCountry(arguments.id) /> <cfif not isNull(Country)> <cfset entityDelete(Country) /> </cfif> </cftransaction> </cffunction> </cfcomponent> ----------- Service.cfc ----------- This is my abstract Service, translating the CF9 ORM 'way' to the OpenBD-GAE implementation of this moment. <cfcomponent displayname="Service"> <!--- init ---> <cffunction name="init" access="public" output="false" returntype="any"> <cfreturn this /> </cffunction> <!--- entityNew ---> <cffunction name="entityNew" access="public" output="false" returntype="any"> <cfargument name="component" type="string" required="true" /> <cfreturn application.beanFactory.getBean(arguments.component) /> </cffunction> <!--- entitySave ---> <cffunction name="entitySave" access="public" output="false" returntype="void"> <cfargument name="object" type="any" required="true" /> <cfscript> var kind = listLast(getMetaData(arguments.object).name,"."); if (len(arguments.object.getId()) eq 0) { arguments.object.setId(CreateUUID()); } GoogleWrite(arguments.object,kind,arguments.object.getId()); </cfscript> </cffunction> <!--- entityLoad ---> <cffunction name="entityLoad" access="public" output="false" returntype="any"> <cfargument name="name" type="string" required="true" /> <cfargument name="id" type="string" default="" /> <cfargument name="filterCriteria" type="struct" default="#StructNew() #" /> <cfargument name="sortOrder" type="string" default="" /> <cfargument name="options" type="string" default="" /> <cfscript> var queryString = 'select from #arguments.name#'; if (len(arguments.id) gt 0) { return GoogleRead(kind=arguments.name,keyName=arguments.id); } else { return GoogleQuery(queryString); } </cfscript> </cffunction> <!--- entityDelete ---> <cffunction name="entityDelete" access="public" output="false" returntype="void"> <cfargument name="object" type="any" required="true" /> <cfscript> GoogleDelete(arguments.object); </cfscript> </cffunction> </cfcomponent> -- Open BlueDragon Public Mailing List http://www.openbluedragon.org/ http://twitter.com/OpenBlueDragon mailing list - http://groups.google.com/group/openbd?hl=en !! save a network - please trim replies before posting !!
