If you create a lot of objects to store data in and are constantly creating get/set methods to handle the setting of those properties then, this will probably save you some time. Its a nice trick not to have to write all that code anymore (or even have to maintain that code if you use some sort of code generator).

Here is our component:


<!--- 
    Author: Steve Ross http://blog.stevensross.com
    Disclaimer: Free to use and distribute, please leave in the credit!
    --->
<cfcomponent output="false"  displayname="Simple on Missing Method Example" hint="Will let you do custom getters and setters w/o writing the code">

    <cffunction name="OnMissingMethod" returnType="any" access="public" output="true" hint="Handles getters and setters">
        <cfargument name="MissingMethodName" type="string" required="true" hint="The name of the missing method">
        <cfargument name="MissingMethodArguments" type="struct" required="true" hint="The arguments passed in to the missing method">

        <cfif LCase(arguments.MissingMethodName) CONTAINS "get">
            <cfreturn getValue(replace(arguments.MissingMethodName, "get", ""))/>
        <cfelseif LCase(arguments.MissingMethodName) CONTAINS "set">
            <cfif StructKeyExists(arguments.MissingMethodArguments, "2")>

            <cfelse>
                <cfset setValue(replace(arguments.MissingMethodName, "set", ""), arguments.MissingMethodArguments)/>
            </cfif>
        </cfif>
    </cffunction>

    <cffunction name="setValue" returnType="void" access="private" output="true" hint="internal setter method" >
        <cfargument name="name" type="string" required="true" hint="name of property to set">
        <cfargument name="value" type="any" required="true" hint="value of property">
            <cfset this[arguments.name] =  arguments.value.1 />
    </cffunction>

    <cffunction name="getValue" returnType="any" access="private" output="true" hint="internal getter method" >
        <cfargument name="name" type="string" required="true" hint="name of property to set">
            <cfif StructKeyExists(this, arguments.name)>
                <cfreturn this[arguments.name]>
            <cfelse>
                <cfreturn ""/>
            </cfif>
    </cffunction>

</cfcomponent>

I’m not really going to go into how this works, put simply all I am doing is a string replace to get the name and then I’m taking the argument and putting it as the data for that variable. Then when you call the getter I’m just striping out the word ‘get’ and finding your data. Now if you haven’t set the data we return empty string.

So save the above example and call it “Simple.cfc”

Create another CFM file in the same directory and call it “test.cfm”

Now you can see this work by putting this code in test.cfm:

<cfset testObj = CreateObject("Component", "Simple")/>
<cfset testStruct = {foo='bar'}/>

<cfset testObj.setTestStruct(testStruct)/>

<h4>We call the testObj.getTestStruct() Method</h4>
<cfdump var="#testObj.getTestStruct()#">

<h4>Notice the "testStruct" property</h4>
<cfdump var="#testObj#" label="dumping the entire object">

A more practical example:


<cfset User = CreateObject("Component", "Simple")/>

<cfset User.setFirstName('Steven')/>
<cfset User.setLastName('Ross')/>

<cfset tmpInfo = {password='dont do it', id='XXX'}/>

<cfset User.setInfo(tmpInfo)/>

<cfdump var="#User#" label="dumping the entire object">

Hope this helps someone out on what you can do with MissingMethod in ColdFusion 8

Just thought I’d point out that there is some odd behavior in XMLSearch() results. See the example below:


<cfxml variable="test">
<test>
    <node>
        <nodes>
        <nodeline>node1</nodeline>
        </nodes>
        <nodes>
        <nodeline>node2</nodeline>
        </nodes>
        <nodes>
        <nodeline>node3</nodeline>
        </nodes>
    </node>
</test>
</cfxml>

<cfset results = XMLSearch(test, "//nodes")/>

<cfset results1 = results[1]/> 

<cfdump var="#results1#"> 

Now if you run this you will see a dump that shows the root node as nodes but, if you try to reference the results as: results1.nodes.nodeline you will get an error. You have to reference the array as the root result. So the path to the nodelines becomes result.nodeline.

Hope that saves someone out there some headaches. I think that XMLSearch needs some major modification but, that may break backward compatibility so I guess Adobe is kinda locked in to how it works currently. For example, XMLSearch has some powerful features built in via XPath. However the way that ColdFusion returns the results is a bit bizzare. Well maybe not bizzare but, definately too verbose. So if you ask ColdFusion to return just the text assigned to the nodelines in the above example, it will return a full xml doc instead of just an array of values. So you end up parsing the data again. It would be really nice to just get an array of results back instead of an array of xml docs back. But, I digress.

If you want to learn XPath, just check out the docs here

If you aren’t aware, yes you can cache the results of stored procs in ColdFusion 8 using cachedwithin. However, be aware that ColdFusion only caches the first result set so If you are returning multiple result sets you are only going to get the first result set. So if you happen to be thinking ahead while you are coding and start out by setting the cachedwithin parameter you will never see multiple result sets.

To give credit where credit is due, my co-worker, Matt Hintze discovered this yesterday when we were trying to figure out why we weren’t getting multiple result sets back from a proc that we knew returned multiple sets every time it ran.

Hopefully this will be addressed by Adobe as caching multiple result sets would be the expected behavior inside a proc.

I noticed that there was a bug in the code. If you had a function ie: <cfset Request.something = “something”> and you put your cursor on the “Request” it would send you to the docs for <cfset> I fixed it so that it correctly sends you to whatever your cursor is on. Here is the text file for the bundle and instructions on installing it.

You don’t need to get the CFTextmate Bundle for this to work in Textmate. Hopefully the command will be included in the next release.

How to add this command to Textmate:

  1. Copy the contents of this text file
  2. Load textmate and then select bunde > bundle editor > show bundle editor (ctrl option cmd B)
  3. Create a new command (you can just click on your bundle name and add it there) settings for the new command: Save: Nothing, command(s): Paste code here, Input: None, Output: Show as HTML, Key Equivilent (I chose option, cmd L), scope selector: text, html, cfm
  4. Open Bundles > Bundle Editor > Reload Bundles

If you want to start CF from the command line instead of using the launcher just do this:

sudo /Applications/JRun4/bin/jrun -autorestart -nohup -start cfusion

No idea why that was so hard to find (really it wasn’t just had to dig though some shell scripts in the bin directory) Just figured I’d post it for those that would rather see std out in the terminal. I have trouble with the Coldfusion Launcher as well. Half the time it hangs on firing up the server.

After looking over the shoulder of one of my peers after he downloaded the latest Coldfusion 8 support for Homesite (yes, I said Homesite), I saw him use the good old F1 on a tag/method to the help docs. Homesite! The product that refuses to die. Adobe is still supporting it so there must be a bunch of CF developers out there still refusing to give it up. Well I’m not switching back to windows for Homesite (I really didn’t use it then either).

After he installed the code support for CF 8 he simply placed his cursor over a tag and hit F1 and bang the help docs come up. It started to bug me that this wasn’t in Textmate and I thought it would be useful. After all its in Homesite! So I worked on this command for Textmate which does the same thing except it uses the CF 8 Livedocs as the source. It supports all the current tags and functions. So head on over to the CF Textmate Google group and grab a copy. Hopefully it will be in the next release of CFTextmate.

Below is the link and the instructions are included in the jump (4th message down). While your at it why don’t you jump in and contribute to the CFTextmate bundle?

Coldfusion 8 Help Docs for Textmate

Also, I hear everyone is looking for a new CF IDE from Adobe. I’m perfectly happy with Textmate, I’d rather them concentrate on adding features to CF than building an IDE. Just seems like a waste.

Enjoy the addition to Textmate!

Https, SSL Certs and Coldfusion

February 27th, 2007

So you are tasked with using SSL (either in cfhttp or some other protocol). Here are the issues: #1 you don't have the cert and #2 when you get the cert you find out that it has been generated in a way that CF doesn't approve of (the name doesn't match the dns entry or the name in the cert is something arbitrary and you are using the IP to connect to the server).

Read the rest of this entry

I recently had a need to grab a binary file from an http response and write that back to the output stream instead of writing the file to the disk. The reason was because we were using the flash client to play the file and it was requesting the file from a cfc call.

Read the rest of this entry

If you have ever needed to create a or translate a java epoch (time in seconds since 1/1/1970) and were lost looking at how to do this then here is the solution:

Convert a date object to epoch:

<cfset epochTime = DateDiff("s", "January 1 1970 00:00", TheDateObject) />

Now change it back:

<cfset theDate = DateAdd("s", epochTime, "January 1 1970 00:00:00") />

I needed a way to do this and came up with a version that you can use to even pass in an array of xml objects and it will properly handle it and you can specify which part of the object you want to use in the array.

Read the rest of this entry

UPDATE Adobe is now providing a compiled version of mod_jrun22.so you can get it here: http://www.adobe.com/support/coldfusion/ts/documents/8001e97/wsconfig.zip Once you unzip it is in the wsconfig.jar\connectors\apache\intel-win\prebuilt path.

I followed this guide for getting all of this setup however, I had already switched out apache 1.3 for apache 2.2 (rails plays better with apache 2.2 in the setup I wanted to run). So I spent the better part of a day trying to get modjrun2.so built (thats the connector for apache). It drove me nutz but this is how I got it to finally work. You should follow the guide in the link above to get everything setup except when it comes to compiling the modjrun part. After you do that then come back here and use this info to get it finished.

Ok, so you have to go get the latest version of the wsconfig.jar unzip it from the archive and you'll have a wsconfig.jar file.

Next fire up a terminal and navigate to the desktop

cd Desktop

Extract that to a directory (just unzip the jar file):

unzip wsconfig.jar -d wsconfig

Now cd to the directory where the source for mod_jrun22 is:

cd wsconfig/connectors/src

Now you compile:

/opt/local/apache2/bin/apxs -c -Wc,-w -n jrun22 -S LIBEXECDIR=/Applications/JRun4/lib/wsconfig/1 mod_jrun22.c jrun_maptable_impl.c jrun_property.c jrun_session.c platform.c jrun_mutex.c jrun_proxy.c jrun_ssl.c jrun_utils.c

One more thing run one more compile task:

/opt/local/apache2/bin/apxs -i -n jrun22 -S LIBEXECDIR=/Applications/JRun4/lib/wsconfig/1 mod_jrun22.la

Next chmod your mod_jrun22.so:

chmod 775 /Applications/JRun4/lib/wsconfig/1/mod_jrun22.so

Hey your finished (well almost) just a couple more notes:

For your httpd.conf configuration you need to remove the AddModule line (that isn't used in apache 2+) and also you need to change the IfModule line to ready mod_jrun22.so

And there you have it restart apache and you should be serving up CF from apache 2