What are Session and Application Variables in Coldfusion?

15 February 2010

Ok, just to start, this is not a post for the seasoned coldfusion developer, this is just a “get an idea of what the heck is going on” sort of post. I was attempting to explain a simple coldfusion login and some different options to a friend, and they were simply not understanding the concept because they didn’t know about application and session variables, so I thought i’d tutorialize this for the others out there who are just confused. Sometimes it’s the simple stuff that’s the hardest to start!
First, you should be at least vaguely familiar with Structures. ok? ok!

There are a few concepts to understand when delving into the world of application and session variables, and i will do my best to avoid using techno talk so you can understand it without having to try too hard. The first, is what an application.cfm (or application.cfc) file is/does.

What an Application.cfm (or application.cfc) file is/does

An application.cfm file is a hunk of code that is executed FIRST before any page you create runs. You MUST name it “application.cfm”. It MUST be at the root of your site (well, not always, but for the basics, yes… must.)
Here is what your 1-page website should look like utilizing an application.cfm:

SITEROOT.com
–index.cfm
–application.cfm

Let’s have a look-see here and show you what this will do.

Here’s my ridiculous application.cfm file:

I'm an application.

And the index:

I'm a sweet index page.

Which will output this:

I'm an application.I'm a sweet index page.

So, we understand. Applications run first, ALWAYS. I’m sure this gets your head turning on the nice things you can now do, but this, my friend, is only the tip of the glorious application file iceberg. There are many, many things you can and should use the application file for, but I don’t want to overwhelm you, so I will just get you excited about application variables.

All right. There are some variables that coldfusion makes available to you that you can use on any page, anywhere, always. These are APPLICATION variables. any variable that you set in the application structure is available anywhere in your website, and is the SAME FOR ALL CLIENTS.

Need to have your datasource name saved? set it!

<cfset application.dsn='mydsn'>

Now you can just call your datasource name variable instead of hard coding it in. Why? you ask? because you really, really don’t want people to be able to see your DSN when an error page appears. yeah, not good. they’ll just see the variable name, though if you use the code above!

Mmk, so application variables are for any computer accessing your site, anywhere on your site.

So What is a Session Variable, then?

Unlike Application variables, which (again), once set, can be used by ANY computer, ANY where on your site, Session variables can only be used by ONE computer ANY where on your site. Here is a great example of where session variables would be perfect:

<cfset session.userid=1287>

What does the code above do? it sets up a userid that can be used anywhere on the site, but only for the one particular computer accessing your site. This is one way that you could create a secured back end area for different users without having to pass a url or form variable to every page. Maybe you would like to display a person’s name on some pages of your site, now you can! just set it on one page, and then call it when you need it from any other page. as long as the user is still on your site, their name will appear!

What is a coldfusion structure?

15 February 2010

Well, someone told me they heard the word “structure” get thrown around a lot in coldfusion, but they weren’t really clear on what it was. I thought i’d write a VERY basic overview of structures and coldfusion for those who don’t have the luxury of better-informed-colleagues to ask.
Ok, so you know how you can read variables in coldfusion, right? Well, just to be thorough, let’s review by getting the “oid” from the url:

url: website.com?oid=124

<cfoutput>#url.oid#</cfoutput>

And you get:

124

Easy peasy, right? now for those of you that don’t know, “url.oid” is, like many coldfusion variables, a STRUCTURE. Here are some other examples of structures just so we are clear:

#url.status#
#form.runadd#
#cart.items.sku#

So, in it’s most dumbed down form, it’s just a variable name with some dots thrown in the middle to make them easier to sort, like looking through a list of lists.

Did you know there are some structures available for you to use on EVERY page? YES! EVERY page! And they are super-helpful. Don’t believe me? try running this on any coldfusion page:

<cfdump var="#application#">
<cfdump var="#session#">
<cfdump var="#cgi#">

So, see all that craziness that gets dumped out? those are structures! how do you call one of the things you see… like this:

<cfoutput>#cgi.http_server#</cfoutput>

and there’s your http server’s name. excellent! Hopefully this will arm you with the ability to call just about anything you can dump.

IE Bottom Border Gap Issue

14 January 2010
Background  shows through because this picture doesn't render at the bottom in IE

Background shows through because this picture doesn't render at the bottom in IE

Yet another thing IE does that we wish it didn’t do. This is simply an image that is SUPPOSED to show up at the bottom of my div, and would therefore hide my background. Does it? Not in IE. What’s the problem, you say? After a little googling, I tried changing my code from this attractive and easy to read version:

   <img src="images/banner_bottom.jpg" />
</div>

To this ugly version that will give me headaches later…

<img src="images/banner_bottom.jpg" /></div>

yes. IE decided that empty space was a page break. Good work IE.

Zero Body Margin in Firefox and IE

14 January 2010

I was working on a project recently where I needed to have my div’s align to the VERY top of the page, not 10-30px off as is the default preset. Easy? I thought it would be. You can achieve this by using css positioning, but as I had a div within a div, and (as is commonly seen) I wanted the inner div to align to the center, I had a problem. Again, it sounds easy, but it was more of a pain than it should have been. Here is a simplified version of what I came up with:

the page…

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<link rel="stylesheet" type="text/css" href="teststyle.css"/>
</head>
 
<body>
 
<div id="outer_body">
	<div id="inner_body">
               <div id="header_text">
			<h1>Here's a Title!</h1>
			a tag line here...
		</div>
	</div>
</div>
 
</body>
</html>

stylesheet…

@charset "utf-8";
/* CSS Document */
 
body{background-color:#e2d6a9;
	font:Arial, Helvetica, sans-serif;
	margin:0px;
	padding:0px;
	position: absolute; 
	top: 0; 
	left: 0; 
	right: 0; 
	bottom: 0;
}
 
#outer_body{background:url(images/outer_bg.jpg) repeat-x #0c2110;
top:0px; position:relative;
	width:100%;
	height:200px;
	margin:0px;
	padding:0px;
 
}
 
#inner_body {
	margin:0px auto;
	position:relative;
	top:0px;
	padding:0px;
	width:200px;
	height:225px;
	background:#0F0
}
 
#header_text{
	margin-top:40px;
	width:190px;
}
Firefox has failed, it's not easy to align divs at the very top...

Firefox has failed, it's not easy to align divs at the very top...

This does NOT work by itself, though. Here’s the trick. You have to put something in every div you want to align at the very top of the page that has a margin and a padding of 0px, or you’re out of luck. I settled on an image named “spacer.gif”, which I then made have a width and height of 0px. Let’s see the difference…

<!--the index page-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<link rel="stylesheet" type="text/css" href="teststyle.css"/>
</head>
 
<body>
 
<div id="outer_body">
	<div id="inner_body">
		<img src="images/logo_bnr.jpg" width="0" height="0" id="spacer" />
                <div id="header_text">
			<h1>Here's a Title!</h1>
			a tag line here...
		</div>
	</div>
</div>
 
</body>
</html>

stylesheet…

@charset "utf-8";
/* CSS Document */
 
body{background-color:#e2d6a9;
	font:Arial, Helvetica, sans-serif;
	margin:0px;
	padding:0px;
	position: absolute; 
	top: 0; 
	left: 0; 
	right: 0; 
	bottom: 0;
}
 
spacer {
margin: 0; padding: 0; width:0px; height:0px; float:left;
}
 
#outer_body{background:url(images/outer_bg.jpg) repeat-x #0c2110;
top:0px; position:relative;
	width:100%;
	height:200px;
	margin:0px;
	padding:0px;
 
}
 
#inner_body {
	margin:0px auto;
	position:relative;
	top:0px;
	padding:0px;
	width:200px;
	height:225px;
	background:#0F0
}
 
#header_text{
	margin-top:40px;
	width:190px;
}

With the invisible spacer, added, now everything aligns to the top!

With the invisible spacer, added, now everything aligns to the top!


Now, a not about IE… IE + float = issues. you might have to play around to get what you want in IE. this solution did work in IE for me, but if you have other elements that are also floating, it could mess those up.

AJAX/Javascript/Coldfusion Dependent Dropdowns with Optional Text Box

18 December 2009

Here’s a common problem. You have a form where you want one select box in a form to be dependent on the other. Coldfusion makes this ridiculously easy with its built in AJAX functionality. Let’s take a gander:

For this example, I set up a cfc called “ajax” (clever, eh?). Here is the function inside it…

 
<cffunction name="getstates" access="remote" returntype="array" hint="lookup states for dropdown">
	<cfargument name="country" type="string" required="true" default="">
 
		<!--- Define variables --->
		<cfset var data="">
		<cfset var i=0>
		<cfset var result=ArrayNew(2)>
 
		<!--- Do search --->
		<cfquery datasource="#variables.dsn#" name="data">
		SELECT state,postal_code
		from tblstates
		where country=<cfqueryparam value="#ucase(arguments.country)#" cfsqltype="cf_sql_varchar">
		order by state
		</cfquery>
 
		<!--- Build result array --->
		<!--- Convert results to array --->
        <cfloop index="i" from="1" to="#data.RecordCount#">
            <cfset result[i][1]=data.postal_code[i]>
            <cfset result[i][2]=data.state[i]>
        </cfloop>
 
		<!--- And return it --->
		<cfreturn result>
	</cffunction>

Mmk, Now let’s look at the actual code on my form page:

<!---here's a query for filling my select box...--->
<cfquery name="rscountry" datasource="#application.db#">
SELECT *
FROM tblcountries
ORDER BY country ASC
</cfquery>
 
<!---here's my form--->
<cfform method="post" name="form1" action="join.cfm?dealeruname=#this_dealer_username#">
     <cfselect name="country" id="country" required="yes" message="Please select your country of residence." query="rscountry" value="country" display="country" selected="United States"></cfselect>
 
     <cfselect name="stateprov" bindonload="true" bind="cfc:ajax.getstates({country})" /> 
</cfform>

That’s it, folks. easy.

But what about when I don’t have a State listing for say… Uganda. Well, we have to have some way of getting the state/province if we don’t have a populated dropdown. Now there’s more to do. There are probably more elegant solutions out there, but this is what I did, and it seems to work pretty well.

Now we’re going to need to use some javascript and a bit more ajax. Let’s do it!

First, let’s get our form prepped:

 
<!---here's my sexier form--->
<cfform method="post" name="form1" action="join.cfm?dealeruname=#this_dealer_username#">
     <!---Notice, I've added an onchange event to this field.--->
     <cfselect name="country" id="country" required="yes" message="Please select your country of residence." query="rscountry" value="country" display="country" selected="United States" 
onChange="showwhich()"></cfselect>
 
   <!---wrap each field in a uniquely identified div--->
    <div id="dd_state">
	<cfselect name="stateprov" bindonload="true" bind="cfc:ajax.getstates({country})" /> 
   </div>
   <!---add a new text input, and hide it with the div--->
   <div id="type_state" style="display:none">
	<cfinput name="stateprovt" type="text" />   
   </div>
</cfform>

OK, we have our text field. It’s hidden. We’ve got all the other stuff in place, we just need to write the stuff that makes it work!

First, we need to make a new cffunction in our ajax cfc. The function will return a boolean value for whether or not the country has states/provinces within it. You could probably set this up to work with your first function, but I went with a smaller query to reduce some load.

<cffunction name="arestates" access="remote" returntype="boolean" hint="are there states?">
	<cfargument name="country" type="string" required="true" default="UNITED STATES">
 
		<!--- Define variable --->
		<cfset var data="">
 
		<!--- Do search --->
		<cfquery datasource="#variables.dsn#" name="data">
		SELECT state
		from tblstates
		where country=<cfqueryparam value="#ucase(arguments.country)#" cfsqltype="cf_sql_varchar">
		LIMIT 1
		</cfquery>
 
		<cfif data.recordcount>
			<cfreturn true>
		<cfelse>
			<cfreturn false>
		</cfif>
	</cffunction>

Ok, not too bad. Now, let’s bind our page to the ajax cfc so we can use this function. Stick this baby at the top of everything on the page:

   <cfajaxproxy cfc="ajax" jsclassname="respond">

Now we need to write the javascript to make the magic happen.

  function showwhich(){
	  var r= new respond();
	  sforc=document.form1.country.value;
	  toshow= r.arestates(sforc);
	  if (toshow == true) 
	  	{
	  	//unhide dropdown, hide text box.
		document.getElementById("dd_state").style.display='inline',
		document.getElementById("type_state").style.display='none',
		document.form1.stateprovt.value=""
		}
	  else {
		//hide dropdown, unhide text box.
		document.getElementById("type_state").style.display='inline',
		document.getElementById("dd_state").style.display='none',
		document.form1.stateprovt.value=""
	  }
 
}

You’ll notice I’ve added a line to clear the value of the text field on each change. This is just idiot-proofing so you don’t have someone come in and enter text, then decide they really did live in the US after all. I have further idiot proofed by adding this code before my form processes:

<cfif isdefined("form.stateprov") and TRIM(form.stateprov) neq ''>
	<cfset use_state=form.stateprov>
<cfelseif isdefined("form.stateprovt") and TRIM(form.stateprovt) neq ''>
	<cfset use_state=form.stateprovt>
<cfelse>
 	<cfset runadd="no">
	<cfset message=message &"<br />The State/Province you entered is invalid.">
</cfif>

Again, I’m sure there are “prettier” ways to accomplish this, but this worked for me!

cffile Disappearing Backslashes

12 November 2009

I’ve never encountered this one, so I thought I’d share…

I was running this simple rename command on an xml response handler page… very, very simple, right?

<cffile action = "rename" source = "c:\inetpub\mysite\images\tn_0000.png" destination = "c:\inetpub\mysite\images\renamed.png">

But here was the error I was getting:

Attribute validation error for tag CFFILE. The value of the attribute source, which is currently c:inetpubmysiteimages tn_0000.png, is invalid.

Whaaat? where did all my backslashes go?? Well, I don’t know… I guess the bermuda triangle of Coldfusion. Either way, after some trial and error, I found the solution:

<cffile action = "rename" source = "c:/inetpub/mysite/images/tn_0000.png" destination = "c:/inetpub/mysite/images/renamed.png">

just change them all to forward slashes… it worked!

Flowplayer + SWFObject = Error

9 November 2009

I was recently using both flowplayer and SWFobject on the same page. I noticed if I placed the javascript for SWFobject before calling the flowplayer container, flowplayer would spit out the error “Flowplayer cannot Access Element: player”. However, placing the javascript AFTER calling the player element made the error disappear. Good to know!

Flixcloud to Influxis File Transfers

4 November 2009

I’ve recently been working on a project that had a user upload a video, and then that video was sent to our transcoding service, Flixcloud. After transcoding took place, Flixcloud claimed they would upload the video wherever we needed, so I had it sent to our FMS hosting provider, Influxis. Problem: the jobs were completing successfully, but my video files were not uploading to Influxis as promised. oh dear. After much back and forth between both companies, here is what we learned:

Flixcloud ONLY sends via FTP in passive mode. Influxis ONLY receives via FTP in active mode. An impasse.

Luckily, it was suggested trying SFTP. Behold! It Worked! So the next time you are using this duo for your transcoding and FMS needs, just remember to use SFTP.

xml post as Bytearray

24 October 2009

I was working recently on creating a response handler for the flixcloud API.  Fairly standard procedure,

<cfset xmlstr = GetHTTPRequestData().content>
<cfset xmldata = XmlParse(xmlstr)>

Apparently not. It was easy enough to test successfully with my own XML, but running against the actual API yielded this error message every time:

ByteArray objects cannot be converted to strings.

After some investigating, I found the culprit… and, with a simple tostring() around my data, it’s fixed!

<cfset xmlstr = tostring(GetHTTPRequestData().content)>
<cfset xmldata = XmlParse(xmlstr)>

Since we’re talking about working with API’s, another problem I encountered while working with the flixcloud API was syntactically invalid xml names. For examlpe, here in an excerpt from the XML returned:

<job>
<thumbnail-media-file>
   <url>ftp://ftp.MYDOMAIN.com/4F173CA4-3048-7B4D-7B5655ECA9D97CCC.png/tn_</url>
   <total-size>41817</total-size>
   <number_of_thumbnails>1</number_of_thumbnails>
   <cost>9</cost>
 </thumbnail-media-file>
</job>

If you parse this into a coldfusion variable called “xmldata”, you’d think you could get to the “total-size” xml text in this way:

<cfoutput>#xmldata.job.thumbnail-media-file.total-size.xmltext#</cfoutput>

However, you would be wrong. Coldfusion does not like those dashes. Here’s how to call it correctly:

<cfoutput>#xmldata.job["thumbnail-media-file"]["total-size"].xmltext#</cfoutput>

and if you thought you should double quote to escape any database issues, it doesn’t seem to work. just leaving the single quotes worked fine.