Scripted Noob: Queries (and Issues)

OK, I'm not a noob. Not even with cfscript. In fact, I love cfscript, and prefer to script as much as I can. ColdFusion 9 created a much greater degree of parity between cftags and cfscript. Unfortunately, the events of the past year and a half have left me with few opportunities to work on ColdFusion 9, so I'm playing catch-up on some of these great new enhancements. I did script the application.cfc back in October of 2009, but aside from that I was buried in writing a book, new job responsibilities, and more. I'm working to write all future ColdFusion examples in as much script as possible, but I still hit the occassional hurdle and ask for help.

So, while writing my examples for my last post, I kept hitting a snag while scripting a query. After banging my head on the wall for a while, I finally pinged the ColdFusionJedi himself for assistance. Ray probably though I was off my nutter, having never scripted a query, but we did run into something worth talking about.

First, I've gotten into a habit of scoping querynames. Why? If you didn't (in ColdFusion 8 or earlier) they were part of the VARIABLES scope. This can give you unintentional results, if you aren't careful, so I'd gotten into scoping querynames.

view plain print about
1<cffunction name="getSiteId" output="false" access="public" returntype="struct">
2     <cfargument name="cgiScope" required="true" type="struct" />
3 <cfset var LOCAL = StructNew() />
4 <cfset LOCAL.retVal = StructNew() />
5 <cfset LOCAL.retVal['success'] = true />
6 <cftry>
7     <cfquery name="LOCAL.qSiteId" datasource="#VARIABLES.instance.dsn#">
8     SELECT    siteId
9 FROM    sites
10 WHERE    urlAddress = <cfqueryparam cfsqltype="cf_sql_varchar" value="#ARGUMENTS.cgiScope.server_name#" />
11 </cfquery>
12 <cfif LOCAL.qSiteId.recordCount>
13     <cfset LOCAL.retVal['result'] = LOCAL.qSiteId />
14 <cfelse>
15     <cfthrow type="My_Custom" errorcode="001" message="No siteId was found for this domain." />
16 </cfif>
17 <cfcatch type="any">
18     <cfset LOCAL.retVal['success'] = false />
19 <cfset LOCAL.retVal['message'] = CFCATCH.message />
20 <!--- Any other error handling --->
21 </cfcatch>
22 </cftry>
23 <cfreturn LOCAL.retVal />
24 </cffunction>

We'll come back to that in just a minute. I also like to pass argumentCollections into functions. Maybe it's just me, but it's something I do. So, I created a collection to pass into the constructor of a new Query.

view plain print about
1// THIS DIDN'T WORK!!!
2
3 /**
4 * FUNCTION getSiteIdByUrl
5 * @access public
6 * @returnType struct
7 * @output false
8 */

9 function getSiteIdByUrl(required struct cgiScope) {
10 LOCAL.retVal = {};
11 LOCAL.retVal['success'] = true;
12 LOCAL.qPrms = {};
13 LOCAL.qPrms.name = "LOCAL.qSiteId";
14 LOCAL.qPrms.datasource = VARIABLES.instance.dsn;
15 LOCAL.qPrms.sql = "SELECT siteId
16 FROM sites
17 WHERE UrlAddress = :urlAddress";
18 LOCAL.q = new Query(argumentCollection = LOCAL.qPrms);
19 LOCAL.q.addParam(name = "urlAddress", value = ARGUMENTS.cgiScope.urlAddress,
20 cfsqltype = "cf_sql_varchar");
21         try {
22     LOCAL.retVal['queryResult'] = LOCAL.q.execute();
23 if (!LOCAL.retVal.queryResult.recordCount) {
24     throw (type = "My_Custom",errorcode = "001",message = "No siteId was found for this domain.");
25 }
26 } catch (any excpt) {
27     LOCAL.retVal['success'] = false;
28 LOCAL.retVal['message'] = excpt.message;
29 // other error handling here
30 }
31 return LOCAL.retVal;
32 }

Alright, it seems to look OK, right? So why is it erroring? Well, Ray first told me to break it down some. Make it simple, remove the param, stuff like that. No dice. Then he said use getResult() after the execute statement. Uh huh. Then I decided to take the LOCAL scope out (it's local anyway, right?) Still no dice. Finally Ray said "Don't use argumentCollection." Use the set methods instead. Bam! It worked! I thanked Ray for the assist, and went back to recreating the full function.

Whoops! Not working again. Could not find retVal.qSiteId in LOCAL (or something like that). Now what? But then I saw I had put the LOCAL scope back on the query name. Took it off, and it worked like a charm.

view plain print about
1//    THIS WORKS GREAT!
2
3 /**
4 * FUNCTION getSiteIdByUrl
5 * @access public
6 * @returnType struct
7 * @output false
8 */

9 function getSiteIdByUrl(required struct cgiScope) {
10 var retVal = {};
11 retVal['success'] = true;
12 var sql = "";
13 var q = new Query();
14 q.setName("qSiteId");
15 q.setDatasource(VARIABLES.instance.dsn);
16 sql = "SELECT siteId
17 FROM sites
18 WHERE UrlAddress = :urlAddress";
19 q.setSQL(sql);
20 q.addParam(name = "urlAddress", value = ARGUMENTS.cgiScope.urlAddress,
21 cfsqltype = "cf_sql_varchar");
22         try {
23     retVal['queryResult'] = q.execute().getResult();
24 if (!retVal.queryResult.recordCount) {
25     throw(type = "My_Custom",errorcode = "001",message = "No siteId was found for this domain.");
26 }
27 } catch (any excpt) {
28     retVal['success'] = false;
29 retVal['message'] = excpt.message;
30 // other error handling here
31 }
32 return retVal;
33 }

Now, I should go back and test argumentCollection without the LOCAL scope on the query name, but for now I'm just happy that it works. I really do love scripting, and see where this really brings ColdFusion (once again) to another level as a language choice.

MSOC Part 3: Setting Up Your Applications

In part two we setup our web server to handle trafficing multiple domains to our single codebase, but now we have to get our applications setup. This is where we have to start thinking about separation. Since each domain is driven off the same set of physical files, we now have to consider how we separate one domain's sessions/actions/resources from another. You don't want one user's session to be cross domain in any way, and it wouldn't be good to have the media assets of one site displaying on another. Where do we begin? With the code.

[More]

New Custom Tag for Google Maps: CFGMap

Two years back I had to write a new mapping implementation for my former employer, who wanted to move away from MapQuest. We chose Google Maps, for a number of reasons. I wrote the implementation using Scott Mebberson's implementation, the Google Maps Tag. I was quick and easy, and ultimately we had to ditch it at the last minute. Why? Google's licensing at the time was too restrictive for our use case. Running almost 2,000 sites of of one codebase, we would have had to get a separate license key for each site, or get an enterprise license through Google. We were going down that path originally, but the cost at the time was almost $40k, and required some work on their part that they couldn't make our deadline (during the holidays), so when the autorenewal kicked in on (cheaper) MapQuest we just rolled with it.

Last month my former employer once again wanted to get rid of MapQuest. First we looked at our implementation, realizing that the same hurdles were in place. Next we looked at ColdFusion 9's new cfmap tags. That implementation works the same way, requiring the API key per domain. Luckily, I remembered seeing a tweet from someone about changes to Google's Maps API. A change that wouldn't require an API key anymore. So, I went to check it out.

The latest version of the Google Maps Javascript API is very nice, and has one very significant change.

The JavaScript Maps API V3 is a free service, available for any web site that is free to consumers.

This was perfect, as all of our sites were free to consumers. The first thing I did was try to make some adjustments to my initial implementation from Scott's tags. This didn't work, as there were some major differences in Google's new implementation. I ended up rewriting the entire implementation to work with the new API, creating my own custom tag. In forking Scott's code, I had to keep the license the same, which allows me to put it back out to the community at large (and with the approval of my old boss).

CFGMap is now available on RIAForge for download. My simple example source code is included with the download, and all code is heavily documented. My example uses JQuery for the basic DOM manipulation involved, but JQuery is not required to use the tag itself. You'll want to pay special attention to the testmap.js file, which shows how you can access your map object to plot directions and stuff. The tag puts a map on the page, and plots the points you've fed to it. It will even trigger a callback method, that you define, for passing lat/lng info that's been goelocated back to your database, reducing the geolocation hits on subsequent map visits.

It's only the first go-around with the updated library, and I'm sure that changes will need to be made at some point. I welcome any and all feedback, questions, and suggestions.

MSOC Part 2 - Web Server Configuration

When you're writing an application to run on multiple domains, but using a single copy of code, the first thing you have to work out is your Web Server Configuration. Basically there will be a DNS entry for each domain pointed to your server's IP Address. Then your web server will have to be configured to handle those domains. Rarely, in an MSOC environment, will you need a separate site entry for each site you're serving, requiring one entry to serve all sites. If you're working with IIS on Windows you could just use the Default Web Site entry in your IIS manager. Apache is a little different.

[More]

Many Sites, One Codebase

The ultimate of reusable code: using one codebase to serve many sites. Not copies of that codebase mind you, but one actual set of code templates. Update a template to fix a bug or add a feature and...? Presto! You've just updated X number of sites at once. Genius! Or is it?

[More]

New Book: Learning Ext JS 3.2

I've been pretty busy this year, starting with my new position at work. And, having worked on major side projects the last three years running, I also took my after work time to spend some overdue quality time with my family. But, I did make time to work with Shea, Colin, and new author Nigel White, to work on the second edition of our Ext JS book, now titled Learning Ext JS 3.2. Released last Monday by Packt Publishing, our latest book brings Ext JS developers up to date in working with the 3.x framework, updating the content to cover many changes to the library as well as introducing several new chapters on key bits about Menus and Buttons, Plugins, Charting, and Ext.Direct.

Sencha (formerly Ext LLC) released Ext JS 3.3 on the same day that Learning Ext JS 3.2 shipped from Packt. There are several new and exciting features added in 3.3, but the core content of the book still aligns with the core of the framework itself, giving developers the tools and information they need to get off the ground running. There were several important changes to the framework between the last book (finalized just before the release of 2.2) and this one, and it was important to get that information out to those ready to learn. In the new chapter about Ext.Direct, I dissect the ColdFusion Server-side Stack, written by Sencha's Aaron Conran, to give the bare bones info needed for writing one's own server-side data marshalling services, going through the pieces step-by-step. Changes to the Data package were just one of the reasons to write this book. I know that Colin, Nigel, Shea, and myself, hope that everyone enjoys our latest work.

Introducing Sencha

Great things are coming. Great things are here!

On June 14th, Ext JS LLC rebranded as part of their announced partnership with the principles of the JQTouch and Raphael projects, creating Sencha. The Ext JS library is still one of their major offerings, but they have also created Sencha Labs as a repository of various Open Source Projects under the MIT License (Like JQTouch, Raphael, and Ext Core). Great things were on the way!

Having David Kaneda (JQTouch) and Dmitry Baranovskiy (Raphael) join forces with the Ext JS crew is huge, and really plays well in understanding a series of recent blog posts around HTML5, CSS3, and what HTML5 means to developers today. But, it gets better.

This morning, Sencha launched their first joint product in public beta, Sencha Touch. Sencha Touch is a cross-platform mobile application framework built to leverage HTML5, CSS3, and JavaScript. It gives you the same sort of consistent API that you've come to expect from the Ext JS team, with a familiar syntax, great documentation, user forums for support, and many samples included with the download to help you learn. I've had the opportunity to preview this code for a while, and it is outstanding work. There will be some interesting apps to come out of this.

The future looks bright for Sencha, and I can't wait to see what they do next. Judging from their post on the rebranding, my prediction are changes to ExtDesigner (possibly to become SenchaDesigner), that would allow a developer to build both Ext JS and Sencha Touch interfaces from the same tool. My guess. (Man, that would be really cool.)

My CF + ExtJs Preso for cf.Objective() 2010

ColdFusion + ExtJsAttached to this is my slide deck and sample code from my ColdFusion + ExtJs presentation here at cf.Objective() 2010. Overall it seemed to go really well, despite the typical technical difficulties, and though Ray said I needed to be a little more introductory (Thanks Ray. I appreciate the feedback.) I heavily commented the JavaScript in my source code, so hopefully that will help to fill in the gaps for people. If anyone has any questions, feel free to use the contact link at the bottom of the page.

I want to shout out to Aaron Conran of ExtJs, for providing me with a license for their new ExtDesigner to giveaway in my presentation. I pinged him last minute on this, and he really came through (Hope you like it Lance. Drop me your info to give back to Aaron.) For those who haven't checked it out yet, it's a fantastic tool, really well done, and more than worth the small price tag on it.

On a side note, I'm using a "work-in-progress" version of CFQueryReader in this sample. I'm in the process of refactoring to support some advanced features of Ext.Direct, and the new version will only be compatible with 3.2 and above. When I put it into SVN I'll add some notes on which revision is the cutoff for previous versions of ExtJs.

Update: I've added notes to the readme.txt file of the sample download with instructions on how to make the examples work in ColdFusion 8 as well.

I Am Speaking at cf.Objective() 2010

I'll be speaking on building applications with ColdFusion and ExtJs at cf.Objective 2010. I was very honored to be asked to submit a topic alongside so many fantastic speakers and developers. I'll post more as the details are refined.

Can We Extend the ColdFusion Server

I love playing around with new toys. So, I'm ecstatic now that ColdFusion 9 has been officially released to the world, and even more so after what I'm about to tell you. Oh sure, I've been playing around with the betas, but mostly in testing the cfajax/ExtJs 3 upgrades (and I'll be posting more on that in the coming months). Time has been somewhat limited for me, so playtime has had to take a back burner. But, I wish I had gotten into this a bit sooner.

Yesterday I finally got around to working with some of the new cfscript implementations. I find these upgrades to be one of the key features for me personally. One, It's a faster coding style for me. Two, I was getting tired of bouncing between script and tags. Three, I really like the economy of code associated with script, finding it to be far less verbose. So, I'm lovin' the fact that I can write all of my CFC's, including my Application.cfc, in pure script. Now I can keep the tags with the display. But, as someone pointed out to me in a recent comment, there are still a few tags (anyone know which ones?) that haven't yet gotten script implementations. What can we do about that?

So, in diving right into playing with script enhancements, I ran into a few roadblocks. Minor errors, stemming from me not properly understanding the implementation. Now, the first place I went was to the documentation. Ray Camden keeps saying to me "Why don't people read the documentation?" I'm one of those that agrees with him. Yes, the documentation has some holes, and even bad examples, but you would be surpised what you can learn. (Read on, you'll see where I'm going with this!)

[More]

Previous Entries / More Entries