Archive for the ‘ColdFusion’ Category

Here is a step by step all-in-one guide to installing and configuring Eclipse on Windows to work with ColdFusion 8:

Eclipse Setup

  1. Download Eclipse - Choose the latest version of Eclipse Classic (currently 3.3.1.1 as of 1/28/2008).
  2. Unzip the zip file into a directory of your choosing. Typically, I like to unzip this into C:\apps\. Whatever directory you choose, when you unzip this file the root for the install will be the “eclipse” directory. So, in my case, this would be C:\apps\eclipse.
  3. Open up C:\apps\eclipse\eclipse.exe. This is the executable file for the Eclipse IDE (it is a good idea to create a shortcut to this file on your desktop or toolbar).
  4. When you launch Eclipse, it will ask you what your Workspace will be. This is of more use for Java development than ColdFusion. I typically accept the default here, check the “Use this as the default and do not ask again” checkbox, and click Ok.
  5. You can close the welcome page by clicking on the X next to Welcome. This will show you the default perspective of Java. The next steps entail configuring the CFEclipse plugin for Eclipse to work on your ColdFusion applications.

Configuring CFEclipse

  1. Go to http://www.cfeclipse.org and click on the Download link.
  2. Following these directions, you should be able to easily configure the CFEclipse plugin.
  3. To use the CFEclipse perspective, inside of Eclipse, go to Window -> Open Perspective -> Other. Choose CFEclipse and click OK.
  4. To create a new CFEclipse Project (similar to a Dreamweaver site):
    • Go to File -> New -> Project.
    • In the Select a Wizard dialogue box, expand CFEclipse, click on CFML Project and click next
    • Name the Project (similar to a Dreamweaver site name), and browse to the local/network directory where the project is contained (i.e., C:\ColdFusion8\wwwroot\myapp\).

ColdFusion 8 Extensions

  1. Go to the ColdFusion downloads section of the Adobe website.
  2. Download both the ColdFusion 8 Extensions for Eclipse and the ColdFusion 8 Help Files for Eclipse.  Follow the simple instructions on the page for installing the ColdFusion 8 Help Files.
  3. To install the ColdFusion 8 Extensions for Eclipse:
    1. Go to Help -> Software Updates -> Find and Install
    2. Search for New Features to Install and click Next
    3. Click on new archived site, and find the file that you just downloaded (it’s named: cf8_extensions_for_eclipse.zip).  Click OK.
    4. Make sure that cf8_extensions_for_eclipse.zip is the only one that is checked, and click Finish.
    5. For Select Features to Install, check the box next to cf8_extensions_for_eclipse.zip and click Next.
    6. Accept the License agreement, click Next, then click Finish.  When prompted, click Install All.
    7. Once it is finished installing, you will be prompted to restart Eclipse.  Click Yes.  Eclipse will reboot, and you will be all set.

Automatic server side validation in ColdFusion can be an extremely useful feature, particularly when you need to perform a set of rather common validation tasks.

Consider this cfform, with the server side validation code:

1
2
3
4
5
6
7
8
9
10
11
12
<cfform action="myform_action.cfm">
   Name: <cfinput type="text" name="fullName" required="yes"
                  message="Your name is required" validateat="onserver" />
   <br />
   Email: <cfinput type="text" name="emailAddress" required="yes" validate="email"
                  message="You must enter a valid email address" validateat="onserver" />
   <br />
   Confirm Email: <cfinput type="text" name="confirmEmailAddress" required="yes" validate="email"
                  message="You must enter a valid confirmation email address" validateat="onserver" />
   <br />
   <cfinput type="submit" name="save" value="Submit" />
</cfform>

Very simple, very neat. However the problem is with the output:

Default cfform error

This post deals with customizing the output, so that it shows up on the same page as the form, in a typical validation fashion.

We are going to tackle this by utilizing the onError() method of the Application.cfc. First, let’s start out with an extremely basic Application.cfc, to understand what happens when we implement the onError() method.

Consider this first rendition of the Application.cfc:

1
2
3
4
5
6
7
8
9
10
<cfcomponent name="Application">
   <cfset this.name="form_validation_app" />
 
   <cffunction name="onError" returntype="void">
      <cfargument name="exception" required="true" />
      <cfargument name="eventName" type="String" required="true" />
 
      <cfdump var="#exception#">
   </cffunction>
</cfcomponent>

When an automatic validation error is triggered, it is now caught by the onError() method (in fact, all application errors are now captured here). Let’s analyze the output.

Below is the dump of the exception object (internally, it’s actually not a struct), triggered by failing form validation:

Form validation error dump

Let’s analyze each key of this structure:

Detail
This is the exact output we saw on the default validation error page (the ugly grey error). Completely useless to us.
Message
This is the message that we see on the ugly grey error page. We could use this to determine if there is a validation error, however, if future versions of ColdFusion modify this message, our code would need to be updated.
StackTrace
Extremely long, ugly, gives you an idea about how CF is built on top of Java. But, actually, fairly useful. The first entry in the trace is coldfusion.filter.FormValidationException, which is the exception object thrown by ColdFusion when a form validation error occurs. It is highly unlikely that the name of this would ever be modified, so we could test to see if exception.stackTrace contains “coldfusion.filter.FormValidationException”, and trap a validation error using this.
Tag Context
Not applicable here
Type
Type of Application is extremely common, therefore, useless here.
errors
This is a key that is particular to this type of error. It is a bunch of <li> tags, or list items, which could be used in a list to display the error. This will be very useful to us, however, it would have been much more useful had CF provided us with an array of structures, with 1 key representing the name of the field in error, and the other key representing the message (this way our display of messages would be unlimited). However, this will suffice, so we will use it.

Now let’s modify the Application.cfc.

  1. We will trap validation errors, while throwing all other errors up to the next level of error handling (either a site-wide error handler or the ugly grey message).
  2. If we catch a validation error, we need to capture the exception.errors field, and forward the user to the page they came from (we can use cgi.HTTP_REFERER). Since we need to use cflocation to forward the user, we must put exception.errors into a persistent scope - we’ll use the session scope for this and delete the key immediately after we display the errors.
  3. We will also create a method to display these validation errors, right in the Application.cfc (you could certainly put it elsewhere; this is simply for ease of implementation.)
  4. Finally, we need to be able to pre-populate the form, using the submitted data (depending on business rules, the actual population can vary, i.e., we likely won’t populate password fields). To do this, we will simply create another temp session variable, and a function in the application.cfc to access this (and destroy it).

The new Application.cfc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<cfcomponent name="Application">
   <cfset this.name="form_validation_app" />
   <cfset this.sessionManagement = "true" />
 
   <cffunction name="onRequestStart" returntype="boolean">
      <cfargument name="targetPage" type="String" required="true" />
      <!--- Capture this instance of the Application.cfc into the request
      so that other pages can call custom functions on the Application.cfc --->
      <cfset request.app = this />	    
      <cfreturn true />
   </cffunction>
 
   <cffunction name="onSessionStart" returntype="void">
      <cfset session.validationError = "" />
      <cfset session.stFormData = structNew() />
   </cffunction>
 
   <cffunction name="onError" returntype="void">
      <cfargument name="exception" required="true" />
      <cfargument name="eventName" type="String" required="true" />
 
      <cfif isDefined('exception.StackTrace') AND isDefined('exception.errors')
      AND exception.StackTrace contains 'coldfusion.filter.FormValidationException'>
         <cfset session.validationError = exception.errors />
         <cfset session.stFormData = duplicate( form ) />
         <cflocation url="#cgi.HTTP_REFERER#" addtoken="false" />
      <cfelse>
         <cfthrow object="#exception#" />
      </cfif>
   </cffunction>
 
   <cffunction name="displayValidationError" access="public" returntype="void"
               output="true">
      <cfif len( session.validationError )>
         <ul class="validationError">#session.validationError#</ul>
         <cfset session.validationError = "" />
      </cfif>
   </cffunction>
 
   <cffunction name="getStFormData" access="public" returntype="struct">
      <cfset var stRet = duplicate( session.stFormData ) />
      <cfset session.stFormData = structNew() />
 
      <cfreturn stRet />
   </cffunction>
</cfcomponent>

And we now add 2 lines of code to our form page, above the cfform:

<cfset variables.stFormData = request.app.getStFormData() />
<cfoutput>#request.app.displayValidationError()#</cfoutput>

We can now reference variables.stFormData, to prepopulate each of the form fields that need to be prepopulated.

Now, our output upon an error is as follows:

Customized Error Message

We could further extend this now, to even perform custom validation in our action page, by simply using cfthrow (for example, when the email address and confirmation email do not match), and catching this cfthrow inside of our cferror. Of course, I leave that for you to do :)

Ok, there are three basic ways to call Custom Tags in ColdFusion.
spacer.gif
<cf_NameOfTag>

This is by far the simplest, but is quite limiting in that it relies on the custom tag file being in the appropriate place in order to be found. Also, when calling tags in this fashion, it becomes impossible to have more than one custom tag with the same name.

<cfmodule>

Up until recently, I used this approach with the template attribute. It works perfectly well, but to me, it’s just not aesthetically pleasing looking at several <cfmodule>’s and </cfmodule>’s all over the place. However, this does solve the problem of cf_.

<cfimport> with Xml Namespace reference

  1. Use the <cfimport> tag to act as a reference to the directory which contains the custom tag(s) you’ll need on your page (if you need custom tags in multiple directories, simply include a <cfimport> for each directory). For each, assign a unique and meaningful prefix.
  2. To call the custom tag, simply reference the appropriate prefix followed by a “:”, then the name of the tag. Attributes can be passed in however you wish.
Example:
Let’s say my page has three custom tags I need, wrapper.cfm which exists in a subdirectory called “customtags/common”, head.cfm and body.cfm in a subdirectory called “customtags/secure”.

<— Use cfimport to get a reference to the directories which contain the custom tags you will call on this page —>
<cfimport prefix=“common” taglib=“customtags/common” />
<cfimport prefix=“secure” taglib=“customtags/secure” />

<— Using the prefixes which correspond to the appropriate tag, simply call the tags as follows —>
<common:wrapper>
<secure:head title=”Hello World” />
<secure:body>

Hello World
</secure:body>
<common:wrapper>

spacer.gif
The end result, is more readable, XML-esque code. By looking at this, I can easily tell that my wrapper tag, is part of some common package that is probably used by all of my application(s). The head and body tags are part of a package called secure, which possibly means that they are only being used in the secure part of my application. One of the reason ColdFusion is such a wonderful language, is because the code, when written appropriately, is extremely readable. And of all solutions for calling customtags, this is by far the most readable and easiest to maintain.