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 !!

Reply via email to