<?xml version="1.0" encoding="utf-8"?>
			
			<rss version="2.0">
			<channel>
			<title>&lt;!--- CFChris ---&gt;</title>
			<link>http://www.cfchris.com/cfchris/index.cfm</link>
			<description>The blog of Chris Phillips, a ColdFusion developer with a passion for improvement.</description>
			<language>en-us</language>
			<pubDate>Sun, 05 Sep 2010 08:08:57 -0700</pubDate>
			<lastBuildDate>Thu, 20 May 2010 14:34:00 -0700</lastBuildDate>
			<generator>BlogCFC</generator>
			<docs>http://blogs.law.harvard.edu/tech/rss</docs>
			<managingEditor>me@cfchris.com</managingEditor>
			<webMaster>me@cfchris.com</webMaster>
			
			
			
			
			
			<item>
				<title>PSA: Facebook App ColdFusion Showstopper</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2010/5/20/PSA-Facebook-App-ColdFusion-Showstopper</link>
				<description>
				
				I am in the R&amp;D stages of building a Facebook application for my employer (&lt;a href=&quot;http://www.dealerpeak.com&quot; target=&quot;_blank&quot;&gt;DealerPeak&lt;/a&gt;). I just spent hours trying to figure out why I couldn&apos;t get my tab page to show up when being loaded by Facebook. I was getting the following error:
&lt;div style=&quot;padding: 0 10px;&quot;&gt;&lt;h2 style=&quot;color:red&quot;&gt;Errors while loading page from application&lt;/h2&gt;&lt;h2 style=&quot;color:red&quot;&gt;Parse errors:&lt;/h2&gt;&lt;pre&gt;FBML Error (line 20): illegal tag &quot;body&quot; under &quot;fb:tab-position&quot;&lt;/pre&gt;&lt;pre&gt;FBML Error (line 35): illegal tag &quot;body&quot; under &quot;fb:tab-position&quot;&lt;/pre&gt;&lt;h2 style=&quot;color:red&quot;&gt;Runtime errors:&lt;/h2&gt;&lt;pre&gt;URLExceptionInvalid scheme for url (javascript:history.back())&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
				 [More]
				</description>
						
				
				<category>ColdFusion</category>				
				
				<pubDate>Thu, 20 May 2010 14:34:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2010/5/20/PSA-Facebook-App-ColdFusion-Showstopper</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>Textarea Auto Grow</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2010/5/3/Textarea-Auto-Grow</link>
				<description>
				
				I have seen instances where I&apos;m on a form on a website and there is some mechanism by which the textarea automatically grows to fit what I&apos;m typing. I&apos;ve also seen this not work too well, and eventually half the bottom line is cut off or the bottom of the textarea has expanded further than it needs to.

A while ago a super simple solution to this popped into my head. And today I happened to need just such a solution. So, I wrote up a vary small JavaScript function to add to our utility library.
				 [More]
				</description>
						
				
				<category>JavaScript</category>				
				
				<category>Web 2.0</category>				
				
				<pubDate>Mon, 03 May 2010 16:34:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2010/5/3/Textarea-Auto-Grow</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>PSA: Browser Back Button Differences</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2010/1/11/PSA-Browser-Back-Button-Differences</link>
				<description>
				
				At work, we had some old display code that was supposed to prevent users from submitting the same form twice. In the form&apos;s submit event, there was a window scoped boolean being set. If validation errors needed to be displayed, then the boolean was un-set. And at the very top of the submit action it would just &apos;return&apos; if it saw the boolean. Maybe it will make more sense if you look at the submit event handler.
				 [More]
				</description>
						
				
				<category>JavaScript</category>				
				
				<category>Web 2.0</category>				
				
				<pubDate>Mon, 11 Jan 2010 16:37:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2010/1/11/PSA-Browser-Back-Button-Differences</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>CFUnited 2009: Adam Lehman - ColdFusion 9, What&apos;s New</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2009/8/14/CFUnited-2009-Adam-Lehman--ColdFusion-9-Whats-New</link>
				<description>
				
				First up was &lt;strong&gt;Server.cfc&lt;/strong&gt;. However that is a bit of a misnomer. You can actually point the administrator to any CFC. That CFC simply needs to have an onServerStart() method. This should be quite a boon for getting sites that have an expensive (read &quot;slow&quot;) first request all spun up and ready for traffic.

Next up was &lt;strong&gt;nested cftransaction&lt;/strong&gt;. Not a lot to explain here. From what I saw, it should satisfy you if you ever said to yourself &quot;I really wish I could nest transactions in CF&quot;.

Then we got introduced to &lt;strong&gt;cffinally/finally&lt;/strong&gt;. I personally have never used this even in languages that I have access to it. Basically it gives you this syntax: &quot;try { ... } catch (e) { ... } finally { ... }&quot;. If someone wants to explain an &lt;em&gt;compelling&lt;/em&gt; use case for &quot;finally&quot;, I would love to hear it...

And then there was &lt;strong&gt;cfcontinue&lt;/strong&gt; and it was good. Seriously! I mean, I&apos;m excited about this one and at the same time amazed it took them this long.
				 [More]
				</description>
						
				
				<category>Conferences</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Fri, 14 Aug 2009 06:32:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2009/8/14/CFUnited-2009-Adam-Lehman--ColdFusion-9-Whats-New</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>CFUnited 2009: Peter Bell - Requirements and Estimating</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2009/8/12/CFUnited-2009-Peter-Bell--Requirements-and-Estimating</link>
				<description>
				
				Peter looks at projects in roughly 3 categories.

&lt;ul&gt;
&lt;li&gt;Configuration &lt; $8000 - free spec (just set up something already built)
&lt;li&gt;Customization &lt; $50,000 - paid spec (requirements gathering, setting up and customizing packages)
&lt;li&gt;Exploration $50,000 - no spec (hard to even define scope)
&lt;/ul&gt;

&lt;h3&gt;Configuration&lt;/h3&gt;
These projects are all about efficiency. You will need to simplify the specs for these types of projects. You will need to have/use configurable code to implement deliverable. That could be via something with a setting file or configuration wizard. In some cases you might use DSLs (domain specific languages). And for very simple stock types of things you can even reuse prior specification documents (copy and paste, or compile stock specs as you go).

&lt;h3&gt;Customization&lt;/h3&gt;
I think here he was talking about a site that will use a lot of code that you or someone else already wrote.
				 [More]
				</description>
						
				
				<category>Conferences</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Wed, 12 Aug 2009 11:57:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2009/8/12/CFUnited-2009-Peter-Bell--Requirements-and-Estimating</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>Using argumentCollection And Overriding Arguments</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2009/5/28/Using-argumentCollection-And-Overriding-Arguments</link>
				<description>
				
				I ran some test code the other day just to make sure that I correctly understand how arguments passed in to functions in CFML work. If you know everything there is to know about functions and arguments in ColdFusion, then feel free not to read the rest of this. But, if you&apos;re curious...

Here is the code:
&lt;code&gt;
&lt;cfoutput&gt;
	&lt;cffunction name=&quot;ExtraArgs&quot; access=&quot;public&quot; returntype=&quot;string&quot;&gt;
		&lt;cfargument name=&quot;Arg1&quot; required=&quot;false&quot; type=&quot;string&quot; /&gt;
		&lt;cfargument name=&quot;Arg2&quot; required=&quot;false&quot; type=&quot;string&quot; /&gt;
		&lt;cfargument name=&quot;Arg3&quot; required=&quot;false&quot; type=&quot;string&quot; /&gt;
		&lt;cfargument name=&quot;Arg4&quot; required=&quot;false&quot; type=&quot;string&quot; /&gt;
		&lt;cfif structKeyExists(arguments,&apos;Arg4&apos;)&gt;
			&lt;cfreturn arguments.Arg4 /&gt;
		&lt;cfelse&gt;
			&lt;cfreturn &apos;undefined&apos; /&gt;
		&lt;/cfif&gt;
	&lt;/cffunction&gt;
	&lt;cfset args3 = {Arg1=&apos;value1&apos;, Arg2=&apos;value2&apos;, Arg3=&apos;value3&apos;} /&gt;
	&lt;cfset args4 = {Arg1=&apos;value1&apos;, Arg2=&apos;value2&apos;, Arg3=&apos;value3&apos;, Arg4=&apos;value4&apos;} /&gt;
	&lt;br/&gt; 1) #ExtraArgs(argumentCollection=args3)# 						&lt;!--- output = &quot;undefined&quot; ---&gt;
	&lt;br/&gt; 2) #ExtraArgs(argumentCollection=args4)# 						&lt;!--- output = &quot;value4&quot; ---&gt;
	&lt;br/&gt; 3) #ExtraArgs(argumentCollection=args4, Arg4=&apos;SomeOtherValue&apos;)# &lt;!--- output = &quot;SomeOtherValue&quot; ---&gt;
&lt;/cfoutput&gt;
&lt;/code&gt;

All of the arguments are specified as &apos;not required&apos; with no &apos;default&apos; value. The function looks for the existence of the fourth argument and either returns that or the string &quot;undefined&quot;.

The first time it is called with the &quot;args3&quot; struct that omits the &quot;Arg4&quot; argument, it returns &quot;undefined&quot;.

The second time it is called with the &quot;args4&quot; struct, which contains &quot;Arg4&quot;, it returns &quot;value4&quot; (the value of &quot;Arg4&quot; in the args4 struct).

The third time it is called with the &quot;args4&quot; struct &lt;i&gt;and&lt;/i&gt; also the &quot;Arg4&quot; argument in addition to that, it returns &quot;SomeOtherValue&quot;. This, I think, is the most interesting one. With this behavior, you could store structs containing the default arguments for certain operations, and then call those operations overriding defaults as needed.
				
				</description>
						
				
				<category>ColdFusion</category>				
				
				<pubDate>Thu, 28 May 2009 10:46:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2009/5/28/Using-argumentCollection-And-Overriding-Arguments</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>How To: Prototype Resize Handle</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2009/2/18/How-To-Prototype-Drag-Corner</link>
				<description>
				
				This is just a short post to share some JavaScript that I wrote to be able to add a drag corner to an html element to make it resizable.

I did this using prototype.js. As an example the two divs below have been made resizable. (Go ahead. Drag the bottom right corner around.)

&lt;div id=&quot;SomeDiv&quot; style=&quot;position: relative; width: 200px; height:100px; border: 2px solid black; padding: 3px;&quot;&gt;
	Div One
	&lt;div class=&quot;corner&quot; id=&quot;DragHandle&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;DivTwo&quot; style=&quot;position:relative; width:150px; height:75px; border:1px dashed red;&quot;&gt;
	Div Two
	&lt;div class=&quot;corner&quot; id=&quot;DragHandleTwo&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;

&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt;
	
	function DragCorner(container, handle) {
		var container = $(container);
		var handle = $(handle);
		
		/* Add property to container to store position variables */
		container.moveposition = {x:0, y:0};
		
		function moveListener(event) {
			/* Calculate how far the mouse moved */
			var moved = {
							x:(event.pointerX() - container.moveposition.x),
							y:(event.pointerY() - container.moveposition.y)
						};
			/* Reset container&apos;s x/y utility property */
			container.moveposition = {x:event.pointerX(), y:event.pointerY()};
			/* Border adds to dimensions */
			var borderStyle = container.getStyle(&apos;border-width&apos;);
			var borderSize = borderStyle.split(&apos; &apos;)[0].replace(/[^0-9]/g,&apos;&apos;);
			/* Padding adds to dimensions */
			var paddingStyle = container.getStyle(&apos;padding&apos;);
			var paddingSize = paddingStyle.split(&apos; &apos;)[0].replace(/[^0-9]/g,&apos;&apos;);
			/* Add things up that change dimensions */
			var sizeAdjust = (borderSize*2) + (paddingSize*2);
			/* Update container&apos;s size */
			var size = container.getDimensions();
			container.setStyle({
					height: size.height+moved.y-sizeAdjust+&apos;px&apos;,
					width:size.width+moved.x-sizeAdjust+&apos;px&apos;
				});
		}
		
		/* Listen for &apos;mouse down&apos; on handle to start the move listener */
		handle.observe(&apos;mousedown&apos;, function(event) {
			/* Set starting x/y */
			container.moveposition = {x:event.pointerX(),y:event.pointerY()};
			/* Start listening for mouse move on body */
			Event.observe(document.body,&apos;mousemove&apos;,moveListener);
		});
		
		/* Listen for &apos;mouse up&apos; to cancel &apos;move&apos; listener */
		Event.observe(document.body,&apos;mouseup&apos;, function(event) {
			Event.stopObserving(document.body,&apos;mousemove&apos;,moveListener);
		});
	}
	
	DragCorner(&apos;SomeDiv&apos;,&apos;DragHandle&apos;);
	
	DragCorner(&apos;DivTwo&apos;,&apos;DragHandleTwo&apos;);
	
&lt;/script&gt;

&lt;style type=&quot;text/css&quot;&gt;
	div.corner {
		background-color: silver;
		cursor: se-resize;
		height: 25px;
		width: 25px;
		position: absolute;
		bottom: 0px;
		right: 0px;
	}
&lt;/style&gt;

And below is the code that makes it possible. If you take a look at it and read the comments, You&apos;ll see that it&apos;s actually pretty simple. The thing that had me stuck for a while was asking Prototype how tall or wide something is isn&apos;t the whole story. Border and padding add to width and height. I have some code in there that will compensate for that. However, I only covered situations where the border/passing were uniform all the way around. Anyway, love to hear what you think about this.

&lt;code&gt;
&lt;div id=&quot;SomeDiv&quot; style=&quot;position: relative; width: 200px; height:100px; border: 2px solid black; padding: 3px;&quot;&gt;
	Div One
	&lt;div class=&quot;corner&quot; id=&quot;DragHandle&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&quot;DivTwo&quot; style=&quot;position:relative; width:150px; height:75px; border:1px dashed red;&quot;&gt;
	Div Two
	&lt;div class=&quot;corner&quot; id=&quot;DragHandleTwo&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;

&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt;

	function DragCorner(container, handle) {
		var container = $(container);
		var handle = $(handle);
		
		/* Add property to container to store position variables */
		container.moveposition = {x:0, y:0};
		
		function moveListener(event) {
			/* Calculate how far the mouse moved */
			var moved = {
							x:(event.pointerX() - container.moveposition.x),
							y:(event.pointerY() - container.moveposition.y)
						};
			/* Reset container&apos;s x/y utility property */
			container.moveposition = {x:event.pointerX(), y:event.pointerY()};
			/* Border adds to dimensions */
			var borderStyle = container.getStyle(&apos;border-width&apos;);
			var borderSize = borderStyle.split(&apos; &apos;)[0].replace(/[^0-9]/g,&apos;&apos;);
			/* Padding adds to dimensions */
			var paddingStyle = container.getStyle(&apos;padding&apos;);
			var paddingSize = paddingStyle.split(&apos; &apos;)[0].replace(/[^0-9]/g,&apos;&apos;);
			/* Add things up that change dimensions */
			var sizeAdjust = (borderSize*2) + (paddingSize*2);
			/* Update container&apos;s size */
			var size = container.getDimensions();
			container.setStyle({
					height: size.height+moved.y-sizeAdjust+&apos;px&apos;,
					width:size.width+moved.x-sizeAdjust+&apos;px&apos;
				});
		}
		
		/* Listen for &apos;mouse down&apos; on handle to start the move listener */
		handle.observe(&apos;mousedown&apos;, function(event) {
			/* Set starting x/y */
			container.moveposition = {x:event.pointerX(),y:event.pointerY()};
			/* Start listening for mouse move on body */
			Event.observe(document.body,&apos;mousemove&apos;,moveListener);
		});
		
		/* Listen for &apos;mouse up&apos; to cancel &apos;move&apos; listener */
		Event.observe(document.body,&apos;mouseup&apos;, function(event) {
			Event.stopObserving(document.body,&apos;mousemove&apos;,moveListener);
		});
	}
	
	DragCorner(&apos;SomeDiv&apos;,&apos;DragHandle&apos;);
	
	DragCorner(&apos;DivTwo&apos;,&apos;DragHandleTwo&apos;);
	
&lt;/script&gt;
&lt;/code&gt;
				
				</description>
						
				
				<category>JavaScript</category>				
				
				<category>Web 2.0</category>				
				
				<pubDate>Wed, 18 Feb 2009 15:01:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2009/2/18/How-To-Prototype-Drag-Corner</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>Die Spammers Die! (Painfully Please)</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2009/1/15/Die-Spammers-Die-Painfully-Please</link>
				<description>
				
				My blog has been absolutely hammered with comment spam lately. If any of you were subscribed to any of those comments and were forwarded the offensive spam, I am very sorry. 

Fortunately, one of the bots wasn&apos;t submitting something correctly. So, instead of getting a few thousand spam comments I got a few thousand error emails. :-(

Anyway, I just took the time to add &lt;a href=&quot;http://cfformprotect.riaforge.org/&quot; target=&quot;_blank&quot;&gt;CFFormProtect&lt;/a&gt; to my comment form. It was super easy. There was really no excuse for me not to do this sooner. So, again, I apologize.

Just to show you how easy it is, here is the implementation code from the docs.

&lt;code&gt;
Put
&lt;cfinclude template=&quot;/cfformprotect/cffp.cfm&quot;&gt;
somewhere between your form tags. 

&lt;!--- On your processing page include the following code: ---&gt;
&lt;cfset Cffp = CreateObject(&quot;component&quot;,&quot;cfformprotect.cffpVerify&quot;).init() /&gt;
&lt;!--- now we can test the form submission ---&gt;
&lt;cfif Cffp.testSubmission(form)&gt;
       &lt;!--- The submission has passed the form test.  Place processing here ---&gt;
&lt;cfelse&gt;
       &lt;!--- The test failed.  Take appropriate failure action here. ---&gt;
&lt;/cfif&gt; 
&lt;/code&gt;

Of course there are lots of things you can do to customize it&apos;s behavior. But, that is the basics. So please go checkout &lt;a href=&quot;http://cfformprotect.riaforge.org/&quot; target=&quot;_blank&quot;&gt;CFFormProtect&lt;/a&gt; for all your &apos;spam form submission&apos; needs. Because, seriously, Captcha is the suck.
				
				</description>
						
				
				<category>Blogging</category>				
				
				<category>Security</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Thu, 15 Jan 2009 11:47:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2009/1/15/Die-Spammers-Die-Painfully-Please</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>Real World AJAX Presentation Code</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/11/14/Real-World-AJAX-Presentation-Code</link>
				<description>
				
				Last night I presented my &quot;Real World AJAX&quot; talk to PDXRIA (our local Portland Adobe User Group). I said I would post the code. So, here it is! (Download link below)

I have included the PDF slide presentation too. There are not a lot of slides. This is a code heavy talk. It uses a very simple CRUD application to demonstrate adding AJAX to an existing application. There are three versions in the zip. One completely paged based. Another one with some &apos;partial page update&apos; style AJAX to improve the user experience. And a final one with some DHTML and DOM building. The code uses an in memory query object instead of a database. So, you should be able to drop it in a folder and run it with no setup.

When I give the presentation, I show how you can turn JavaScript off and the second version still works (it gracefully degrades). I really need to add about 10 more slides with some of the stuff that I ramble off while I&apos;m showing the code examples. If I get around to polishing it off, I&apos;ll re-post the updated slides and code.

Also, I built the slides in OpenOffice.org Impress. If you would like to give this talk to your user group, or somewhere else, let me know.
				
				</description>
						
				
				<category>JavaScript</category>				
				
				<category>Web 2.0</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Fri, 14 Nov 2008 19:52:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/11/14/Real-World-AJAX-Presentation-Code</guid>
				
				<enclosure url="http://www.cfchris.com/cfchris/enclosures/RealWorldAJAX.zip" length="230208" type="application/zip"/>
				
			</item>
			
		 	
			
			
			<item>
				<title>Database Abstraction With Illudium and onMissingMethod()</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/11/12/Database-Abstraction-With-Illudium-and-onMissingMethod</link>
				<description>
				
				This is the long overdue wrap-up post in my series about using &lt;a href=&quot;http://cfcgenerator.riaforge.org/&quot; target=&quot;_blank&quot;&gt;Illudium&lt;/a&gt; outside it&apos;s Flex front end as a service to generate CFCs.

To recap: I explained &lt;a href=&quot;http://www.cfchris.com/cfchris/index.cfm/2008/3/1/Impetus-For-A-Database-Abstraction-System&quot;&gt;why I was doing&lt;/a&gt; this and with these tools. Then I showed how you could &lt;a href=&quot;http://www.cfchris.com/cfchris/index.cfm/2008/3/4/Illudium--Outside-Its-Flex-FrontEnd&quot;&gt;call Illudium outside of it&apos;s Flex front-end&lt;/a&gt;. And I showed how we could &lt;a href=&quot;http://www.cfchris.com/cfchris/index.cfm/2008/3/13/Creating-A-CFC-Generator-Object-With-Illudium&quot;&gt;bundle that generation code up into a CFC&lt;/a&gt;.

So, here&apos;s where it really gets fun. Now, I can generate CFCs to whatever specification that I need. But, I definitely do not want to be writing a bunch of CreateObject()s everywhere with hard coded paths to beans and Gateways. So, I decided that a dbService (service object to hide the implementation details of my database CFCs) would be a very good idea. I also decided that, like &lt;a href=&quot;http://www.reactorframework.com/&quot; target=&quot;_blank&quot;&gt;Reactor&lt;/a&gt;, I would do run-time generation to speed up developing code for new tables.

I also decided that I would create an API where methods have the name of the table in them (like getUserGateway(), getNewUser(), and getUserByID(userid). This is made possible by the onMissionMethod() method of CFCs in ColdFusion 8. The code for that is below. There is a lot going in it. So, take a look and we&apos;ll talk about it below when you&apos;re ready.

&lt;code&gt;
&lt;cffunction name=&quot;onMissingMethod&quot; access=&quot;public&quot; returntype=&quot;component&quot; 
			hint=&quot;Secret sauce that makes (get[thing]ByID(thingID),getNew[thing](),get[thing]Gateway()) method calls work.&quot;&gt;
	&lt;cfargument name=&quot;missingMethodName&quot; type=&quot;string&quot; /&gt;
	&lt;cfargument name=&quot;missingMethodArguments&quot; type=&quot;struct&quot; /&gt;
	
	&lt;cfset var table = &quot;&quot; /&gt;
	&lt;cfset var argsList = &quot;&quot; /&gt;
	&lt;cfset var args = {} /&gt;
	
	&lt;cfif left(missingMethodName,6) EQ &apos;getNew&apos;&gt;
	
		&lt;!--- New empty record ---&gt;
		&lt;cfset table = mid(missingMethodName,7,len(missingMethodName)) /&gt;
		&lt;cfreturn getBean(table).init() /&gt;
		
	&lt;cfelseif left(missingMethodName,3) EQ &apos;get&apos; AND right(missingMethodName,4) EQ &apos;ByID&apos;&gt;
		
		&lt;!--- Record object loaded from DB ---&gt;
		&lt;cfset table = mid(missingMethodName,4,len(missingMethodName)-7) /&gt;
		&lt;cfset argsList = StructKeyList(missingMethodArguments) /&gt;
		&lt;cfif listLen(argsList) GT 1&gt;
			&lt;!--- Multiple Arguments: just pass them through ---&gt;
			&lt;cfset args = missingMethodArguments /&gt;
		&lt;cfelse&gt;
			&lt;cfif argsList EQ &quot;1&quot;&gt;
				&lt;!--- Single Positional Argument: Try to create PK by convention ---&gt;
				&lt;cfset args[getPKForTable(table)] = missingMethodArguments[argsList] /&gt;
			&lt;cfelse&gt;
				&lt;!--- Single Non-Positional Argument: Pass it through ---&gt;
				&lt;cfset args[argsList] = missingMethodArguments[argsList] /&gt;
			&lt;/cfif&gt;
		&lt;/cfif&gt;
		&lt;cfreturn getBean(table).init(argumentCollection=args).load() /&gt;
		
	&lt;cfelseif left(missingMethodName,3) EQ &apos;get&apos; AND right(missingMethodName,7) EQ &apos;Gateway&apos;&gt;
		
		&lt;!--- Table Gateway Object ---&gt;
		&lt;cfset table = mid(missingMethodName,4,len(missingMethodName)-10) /&gt;
		&lt;cfreturn getGateway(table) /&gt;
		
	&lt;cfelse&gt;
		
		&lt;cfthrow type=&quot;dbService.UnhandledMissingMethod&quot;
				 message=&quot;Method (#missingMethodName#) was called on com.dealerpeak.dbService and I don&apos;t know how to handle it.&quot; /&gt;
		
	&lt;/cfif&gt;
&lt;/cffunction&gt;
&lt;/code&gt;

Hope I didn&apos;t loose you. This method is using some simple string functions to determine what type of object the caller wants back and for what table. Then it makes calls to utility methods that do the work. For example, say I have a handle on an instance of the dbService in a variable called &apos;dbService&apos;. If I call this code &quot;user = dbService.getNewUser()&quot;, then the onMissionMethod calls &quot;&amp;lt;cfreturn getBean(table).init() /&amp;gt;&quot;. And getBean() looks like this.

&lt;code&gt;
&lt;cffunction name=&quot;getBean&quot; access=&quot;public&quot; output=&quot;false&quot; returntype=&quot;component&quot; 
			hint=&quot;Given a table name, return an instance of a bean. (w/ runtime CFC generation).&quot;&gt;
	&lt;cfargument name=&quot;Table&quot; required=&quot;true&quot; type=&quot;string&quot; /&gt;
	&lt;cfset var beanPath = getCFCPath(arguments.Table) /&gt;
	&lt;cfset var bean = {} /&gt;
	&lt;cftry&gt;
		&lt;cfset bean = CreateObject(&apos;component&apos;,beanPath)._setDBService(this) /&gt;
		&lt;cfcatch&gt;
			&lt;!--- Runtime Generation ---&gt;
			&lt;cfset generateCFCs(arguments.Table) /&gt;
			&lt;!--- Return bean ---&gt;
			&lt;cfset bean = CreateObject(&apos;component&apos;,beanPath)._setDBService(this) /&gt;
		&lt;/cfcatch&gt;
	&lt;/cftry&gt;
	&lt;cfreturn bean /&gt;
&lt;/cffunction&gt;
&lt;/code&gt;

I&apos;m sure you can guess what the other utility methods for Gateways and DAOs look like based on that. You can also see how the runtime generation of CFCs occurs. Also, each object instantiated, gets a pointer back to the dbService.

Early on I decided that I wanted all of the SQL in the Gateways and DAOs. But, I wanted the beans to expose an Active Record like API for persistence operations. So each base bean (that will always be over-written when regenerated) has load(), save(), and delete() methods. Take a look below at how one of those works.

&lt;code&gt;
&lt;!--- Convenience method so bean can save itself ---&gt;
&lt;cffunction name=&quot;save&quot; access=&quot;public&quot; returntype=&quot;component&quot; output=&quot;false&quot;
			hint=&quot;Convenience method so bean can save itself. Calls out to dbService.&quot;&gt;
	&lt;cfargument name=&quot;LoadAfterSave&quot; type=&quot;boolean&quot; required=&quot;false&quot; default=&quot;true&quot; /&gt;
	&lt;cfset variables.dbService.getDAO(variables.TableName).save(this,LoadAfterSave) /&gt;
	&lt;cfreturn this /&gt;
&lt;/cffunction&gt;
&lt;/code&gt;

I won&apos;t go any farther into the details of how I customized the generated CFCs. I&apos;ll let you do your own exploration there. It has been a very iterative process. And I&apos;m still tweaking my generator templates.

I hope you get some good ideas from this series. Please remember, this is only one way of doing it. Work politics forced me to do it this way. But, now, I&apos;m glad that I got the chance. In the future when I&apos;m using &lt;a href=&quot;http://www.transfer-orm.com/&quot; target=_blank&quot;&gt;Transfer&lt;/a&gt; or Hibernate, I will appreciate how much work went into making them so flexible and powerful.
				
				</description>
						
				
				<category>Database Abstraction</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Wed, 12 Nov 2008 19:15:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/11/12/Database-Abstraction-With-Illudium-and-onMissingMethod</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>OT: Riding In To Work (Motorcycle)</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/9/3/OT-Riding-In-To-Work-Motorcycle</link>
				<description>
				
				I have been riding in to work by motorcycle for the last 4 months. I got my motorcycle endorsement at the end of April. I took the &lt;a href=&quot;http://teamoregon.orst.edu/TO_Web/ridertraining.html&quot; target=&quot;_blank&quot;&gt;Team Oregon Basic Rider Training&lt;/a&gt; before getting my endorsement. It was a very fun class. And I really felt prepared to ride on the road after it. So, I&apos;d recommend it or it&apos;s equivalent in your state.

There were a few reasons that I got a motorcycle. One was to just do something different. You know, shake things up. Another was to save some money. With selling my car and getting a cheap motorcycle, I was able to knock a few grand off my credit cards. :-) Also, I&apos;m getting about 55 MPG. When I fill up, it&apos;s like $8. Oh, and insurance is like $160/year.

Since I was a new rider, I figured I should get a very cheap bike. That way, I wouldn&apos;t cry if I happened to lay it down. So, I got a 1981 Honda CM400 Custom. Here is a picture of my commuter bike. I&apos;ve already put on almost 2000 miles.

&lt;img src=&quot;http://www.cfchris.com/cfchris/images/Honda_400_2.jpeg&quot; width=&quot;480&quot; /&gt;

Anyone else ride a motorcycle in to work?
				
				</description>
						
				
				<category>Personal</category>				
				
				<pubDate>Wed, 03 Sep 2008 16:08:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/9/3/OT-Riding-In-To-Work-Motorcycle</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>SQL Server - Insert Not Working</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/7/11/SQL-Server--Insert-Not-Working</link>
				<description>
				
				Just wanted to share a bit of fun I had yesterday. (Actually it wasn&apos;t very fun). I had a cfquery that was supposed to copy &quot;Template&quot; records linked to one entity inserting them linked to another entity. So, the file was using an Insert/Select. Never seen one? OK, it looks like this.

&lt;code&gt;
	&lt;cfquery datasource=&quot;#request.DSN#&quot;&gt;
		INSERT INTO
			[Template]
			(
				TemplateName,
				OwnerID,
				...
			)
		SELECT
			TemplateName,
			&lt;cfqueryparam value=&quot;#attributes.Target_OwnerID#&quot; cfsqltype=&quot;cf_sql_integer&quot;&gt;,
			...
		FROM
			[Template]
		WHERE
			OwnerID = &lt;cfqueryparam value=&quot;#attributes.Template_OwnerID#&quot; cfsqltype=&quot;cf_sql_integer&quot;&gt;
			...
	&lt;/cfquery&gt;
&lt;/code&gt;

So, we can all agree that insert/select is a great thing. However, this particular one was not working (on the live server). I tried the normal things. I cut the SQL from the .cfm and pasted it into SQL Server Management Studio (SSMS), replaced the params with the values I knew it would be using and ran it (inside of a transaction, of course). Guess what? It worked. So, it works running in SSMS but, not in a cfquery. Hmmm... So, next, I added an &quot;output&quot; clause to the insert/select. That way I could see any records it would be inserting, just to make sure it really wasn&apos;t inserting them. Then I added a cfdump that would only run for me. &quot;What&apos;s an output clause?&quot; you say. Here I&apos;ll show you.

&lt;code&gt;
	&lt;cfquery name=&quot;insTemplates&quot; datasource=&quot;#request.DSN#&quot;&gt;
		INSERT INTO
			[Template]
			(
				TemplateName,
				OwnerID,
				...
			)
		OUTPUT
			INSERTED.*
		SELECT
			TemplateName,
			&lt;cfqueryparam value=&quot;#attributes.Target_OwnerID#&quot; cfsqltype=&quot;cf_sql_integer&quot;&gt;,
			...
		FROM
			[Template]
		WHERE
			OwnerID = &lt;cfqueryparam value=&quot;#attributes.Template_OwnerID#&quot; cfsqltype=&quot;cf_sql_integer&quot;&gt;
			...
	&lt;/cfquery&gt;
	&lt;cfdump var=&quot;#insTemplates#&quot; label=&quot;insTemplates&quot; /&gt;
&lt;/code&gt;

I ran that and guess how many records were inserted... 0. At this point I&apos;m a bit frustrated. But, it begins to dawn on me that I&apos;ve seen similar behavior before from SQL Server. There are time when the SQL Server will cache a bad plan for some SQL. In these cases, you can either have the database flush it&apos;s entire plan cache or you can alter the SQL enough to force it to make a new plan for your SQL. So, I added &quot;AND 1=1&quot; to my &quot;where&quot; clause.

Guess what? It works now.

This is a fairly edge case. I have not seen it very often. But, if you are positive that a cfquery is not returning what it should, before you jump out of your office window, try adding something innocuous to your &quot;where&quot; clause. 

If it does work, feel free to send some happy thoughts my way and curse MS under your breath. :-)
				
				</description>
						
				
				<category>SQL Server</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Fri, 11 Jul 2008 13:09:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/7/11/SQL-Server--Insert-Not-Working</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>I&apos;m an Adobe UG Co-Manager!</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/7/8/Im-an-Adobe-UG-CoManager</link>
				<description>
				
				As part of a new Adobe initiatives user groups are supposed to have co-managers. So, I will be the new co-manager for the PDXRIA group. The title feels a little like &quot;Assistant to the Regional Manager&quot; ;-). And in more exiting news, Simeon Bateman will be stepping back up as the main manager.

We will both do our best to provide engaging presentations and valuable opportunities for networking. For more details see &lt;a href=&quot;http://blog.simb.net/2008/07/08/pdx-ria-is-in-top-gear/&quot;&gt;Simeon&apos;s blog.&lt;/a&gt;

P.S. I&apos;m going to try and blog more often.
				
				</description>
						
				
				<category>Personal</category>				
				
				<category>ColdFusion</category>				
				
				<pubDate>Tue, 08 Jul 2008 10:28:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/7/8/Im-an-Adobe-UG-CoManager</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>Download Firefox 3 Today!</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/6/17/Download-Firefox-3-Today</link>
				<description>
				
				You will probably hear this elsewhere also. But, considering how indespensible Firefox has come to be to me as a Web Developer, I couldn&apos;t not tell you about this.
&lt;br/&gt;
&lt;br/&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;a href=&quot;http://www.spreadfirefox.com/en-US/worldrecord/&quot;&gt;
&lt;img border=&quot;0&quot; title=&quot;Click to go get Firefox 3. Do it now!&quot; src=&quot;http://farm4.static.flickr.com/3108/2586455290_12c90be6d5.jpg?v=0&quot; align=&quot;center&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;
				
				</description>
						
				
				<category>Firefox</category>				
				
				<pubDate>Tue, 17 Jun 2008 09:35:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/6/17/Download-Firefox-3-Today</guid>
				
			</item>
			
		 	
			
			
			<item>
				<title>java.lang.ref.SoftReference in CFML</title>
				<link>http://www.cfchris.com/cfchris/index.cfm/2008/5/7/javalangrefSoftReference-in-CFML</link>
				<description>
				
				So, one of the coolest things I learned at the conference was about how Transfer does it&apos;s caching. Part of that is using the Java &lt;a href=&quot;http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/SoftReference.html&quot; target=&quot;_blank&quot;&gt;SoftReference&lt;/a&gt; class. Soft reference objects are cleared at the discretion of the garbage collector in response to memory demand. Let me show you what I mean.

&lt;code&gt;
&lt;cfloop query=&quot;OrderedUserQry&quot;&gt;
	&lt;cfif NOT structKeyExists(application.UserCache, OrderedUserQry.UserIdentity)&gt;
		&lt;cfset user = dbService.getUserByID(OrderedUserQry.UserID) /&gt;
		&lt;cfset application.UserCache[OrderedUserQry.UserIdentity] = user /&gt;
	&lt;/cfif&gt;
	&lt;cfset application.maxUserInt = OrderedUserQry.UserIdentity /&gt;
&lt;/cfloop&gt;
&lt;/code&gt;

This code mimics a caching mechanism that would put a hard reference in the application.UserCache to a &quot;User&quot; object. I just ran this repeatedly this morning until CF would not respond with anything but &quot;java.lang.OutOfMemoryError&quot;. Fun yeah?

Change that code to this:
&lt;code&gt;
&lt;cfloop query=&quot;OrderedUserQry&quot;&gt;
	&lt;cfif NOT structKeyExists(application.UserCache, OrderedUserQry.UserIdentity)&gt;
		&lt;cfset user = dbService.getUserByID(OrderedUserQry.UserID) /&gt;
		&lt;cfset application.UserCache[OrderedUserQry.UserIdentity] = CreateObject(&apos;java&apos;,&apos;java.lang.ref.SoftReference&apos;).Init(user) /&gt;
	&lt;/cfif&gt;
	&lt;cfset application.maxUserInt = OrderedUserQry.UserIdentity /&gt;
&lt;/cfloop&gt;
&lt;/code&gt;

And you can run it all day long. I also created a page to go through the cache and get rid of keys that the soft-referenced object had been GCed. With help from SoftReference, the JVM was able to reclaim memory as needed. So, after I got to about 100,000 users having been put into cache, I ran the culling page and the cache only had arount 18,000 keys left.

&lt;code&gt;
&lt;!--- Culling Code ---&gt;
&lt;cfloop list=&quot;#StructKeyList(application.UserCache)#&quot; index=&quot;key&quot;&gt;
	&lt;cfset user = application.UserCache[key].get() /&gt;
	&lt;cfif NOT structKeyExists(variables,&apos;user&apos;)&gt;
		&lt;cfset structDelete(application.UserCache,key) /&gt;
	&lt;/cfif&gt;
&lt;/cfloop&gt;
&lt;/code&gt;

I definitely will be using this in caching systems in the future. There may be cases where you want a hard-reference cache. But, there are plenty more I think, where it would be fine if some objects in your cache were GCed to give the JVM the memory it needs.
				
				</description>
						
				
				<category>ColdFusion</category>				
				
				<pubDate>Wed, 07 May 2008 11:53:00 -0700</pubDate>
				<guid>http://www.cfchris.com/cfchris/index.cfm/2008/5/7/javalangrefSoftReference-in-CFML</guid>
				
			</item>
			
		 	
			</channel></rss>