Stumble Upon Toolbar My blogger code: B6 d++ t++ k s u-- f i++ o+ x- e+ l+ c-- (decode it!)


Viewing by Category: ColdFusion / Main
June 14, 2007
i18n (internationalization) Made Easy
Something I've done quite a bit of in the last few years is internationalization (i18n) of ColdFusion applications.

The process makes it so that an application has no static text at all for labels or page text in the code. Everything is kept in a database and text is retrieved at runtime for display.

One way to do this is through the use of Properties files (the Java way), but I don't find that to be as easy or flexible as the way I came up with. By storing text in the tables it makes the editing process easier for customers and myself. When edits are required I export the tables to an Excel sheet which is then edited by customers and then sent back to me for loading. When new languages need to be added it is as simple as cloning the English rows, changing the "lang" field and editing rows in a single column. Then they send it back to me and 5 minutes later, voila a new language.

The technique doesn't just apply for doing different languages. It also allows for doing additional label and text sets for branding applications.

One thing to be aware of is that your JDBC connection has to be set to allow UNICODE. This ensures that the different character sets can be correctly retrieved for display.

Example
Example Source Code
Example i18n.cfc
Example application.cfc
SQL Script
Source Zip Package

May 18, 2006
Coming soon: Collective


Collective

September 4, 2005
Other CFMX Features Presentation
I'm doing half of a presentation (includes source code) on CFMX 7 stuff this week at the Atlanta Cold Fusion Users Group (ACFUG). My part covers stuff like strong encryption, changes to cfparam, cftimer,cfapplication scriptprotect, application event framework, document literal web services, and event gateways. John Mason is doing the other half of the presentation, which covers cfdocument, cfreport, and some of the other fun new stuff of CF7. The presentation links to several great example gateway applications from various sources (Tom Jordahl, Jim Schley, Matthew Woodward, etc). They put together several non-trivial examples of writing XMPP and IM gateways which you could use as the start of a real application. I'd recommend checking them out.

July 13, 2005
Happy birthday ColdFusion!
Macromedia celebrated the 10 year birthday of ColdFusion last night. There was Breeze Live broadcast for user groups which featured the founding fathers of CF (JJ, Jeremy, Sim, Ben) talking about the evolution of the product.

We celebrated it locally at the Atlanta ColdFusion Users Group by hosting a birthday party which included tons of food, beverages and the cool cake pictured below.



May 11, 2005
CF7 WS-I Basic Profile Compliance
One of the important (and barely mentioned) features of CFMX 7 is Web services compliance with WS-I Basic Profile 1.1. WS-I is an organization that promotes Web services interoperability across platforms and programming languages. They provide test tools to verify that Web services are exposed and communicate in a standard way which (in theory) should make them more interoperable. I'm not going to explore the minutae of the subject, but I encourage you to check out the WS-I site (if you're a dork like me).

To a small organization Basic Profile compliance might not mean much, but to larger organizations with disparate systems it is extremely important. Also it better positions CFMX as an interoperable development platform. Many thanks to Tom Jordahl and the CFMX development team for adding this feature during the last development cycle. Tom is the Development lead for CF and works on the Apache Axis (Web services) project.

The default settings for Web services is not compliant, but adding a style="document" to a component tag will make it comply. Here is a code sample:

<cfcomponent style="document">
   <cffunction name="testMethod" access="remote" returntype="string">

      <cfargument name="aString" type="string" required="true">

      <cfset myResult = "Message - " & arguments.aString & " Service Responded Successfully - " & Now()>

      <cfreturn myResult>
   </cffunction>
</cfcomponent>

April 1, 2005
Application Events - Application.cfc
Another one of the cool things about CFMX 7 is the introduction of Application events using Application.cfc. Application events are things like: onApplicationStart, onApplicationEnd, onSessionStart, onSessionEnd, onRequestStart, onRequest, onRequestEnd and onError. Now instead of using an Application.cfm you use Application.cfc and one or more of the methods above which will run when the appropriate event fires. This allows clean initialization of things on startups and destruction (or whatever) on end. This really solves one of the old problems of how do I know when someone has left my application. Now you can do something when the session ends if desired. People always used to come up with crazy coding solutions for this in the bad old days. Now you don't have to do that anymore.

I put together some sample code which shows using the new methods. It demonstrates the methods by having a person enter their email into a form so that they can be notified when the session and application times out. Kind of a trivial example, but you get the idea of how to use it and that it does work as designed.



Here is some sample code:

Application.cfc

<cfcomponent>
    <cfset this.name = "TestApplication">
    <cfset this.clientmanagement = "false">
    <cfset this.loginstorage = "Session">
    <cfset this.sessionmanagement = "True">
    <cfset this.sessiontimeout = "#createtimespan(0,0,10,0)#">
    <cfset this.applicationtimeout = "#createtimespan(0,1,0,0)#">
    

    <cfif IsDefined("url.reinit")>
        <cfobject type="component" name="application.myObj" component="test">        
    </cfif>
    

    <cffunction name="onApplicationStart" output="true">
        <!--- onApplicationStart body goes here --->
        <cfoutput>onApplicationStart executed<br></cfoutput>
        

        <!--- This is where you would put code to initialize any application variables --->
        

                 <cfobject type="component" name="application.myObj" component="test">        

        <cfset application.aEmails = ArrayNew(1)>        
    </cffunction>
    <cffunction name="onApplicationEnd" output="true">
        <cfargument name = "ApplicationScope" required=true/>
        <!--- onApplicationEnd body goes here --->

                 <cfif isArray(arguments.ApplicationScope.aEmails)>
            <cfloop index="i" from="1" to="#ArrayLen(arguments.ApplicationScope.aEmails)#">
                <cfmail to="#arguments.ApplicationScope.aEmails[i]#" from="testapp@atl.frb.org" subject="Application scope has expired">
                Application scope has expired #Now()#
                </cfmail>            
            </cfloop>
        </cfif>
    </cffunction>
    

    <cffunction name="onSessionStart" output="true">
        <!--- onSessionStart body goes here --->
        <cfoutput>onSessionStart executed<br></cfoutput>

                 <!--- This is where you would put code to initialize any session variables --->

                 <cfset session.aEmails = ArrayNew(1)>        
    </cffunction>
    <cffunction name="onSessionEnd" output="true">
        <cfargument name = "SessionScope" required=true/>
        <cfargument name = "ApplicationScope" required=true/>
        <!--- onSessionEnd body goes here --->

        <cfif isArray(arguments.SessionScope.aEmails)>
            <cfloop index="i" from="1" to="#ArrayLen(arguments.SessionScope.aEmails)#">
                <cfmail to="#arguments.SessionScope.aEmails[i]#" from="testapp@atl.frb.org" subject="Session scope has expired">
                Session scope has expired #Now()#
                </cfmail>            
            </cfloop>
        </cfif>
    </cffunction>         

    <cffunction name="onRequestStart" output="true">
        <!--- OnRequestStart body goes here --->
        <cfoutput>OnRequestStart executed<br><br></cfoutput>
    </cffunction>
    <cffunction name="onRequestEnd" output="true">
        <!--- OnRequestEnd body goes here --->
        <cfoutput>OnRequestEnd executed<br></cfoutput>
    </cffunction>        

              <!--- onError is equivalent to CFERROR in application.cfm --->
    <cffunction name="onError">
        <cfargument name="Exception" required=true/>
         <cfargument type="String" name="EventName" required=true/>
         <!--- Log all errors. --->
             <cflog file="#This.Name#" type="error"
                 text="Event Name: #Arguments.Eventname#" >

                              <cflog file="#This.Name#" type="error"
                 text="Message: #Arguments.Exception.message#">

                          <cflog file="#This.Name#" type="error"
             text="Root Cause Message: #Arguments.Exception.rootcause.message#">

                  <!--- Display an error message if there is a page context. --->
     <cfif NOT (Arguments.EventName IS "onSessionEnd") OR
             (Arguments.EventName IS "onApplicationEnd")>
         <cfoutput>
             <h2>An unexpected error occurred.</h2>
             <p>Please provide the following information to technical support:</p>
             <p>Error Event: #Arguments.EventName#</p>
             <p>Error details:<br>
             <cfdump var=#Arguments.Exception#></p>
         </cfoutput>
     </cfif>
    </cffunction>
</cfcomponent>

test.cfc

<cfcomponent>
    <cffunction name="addEmailToSession" access="public" returntype="void">
        <cfargument name="email" type="string" required="true">

                 <cfset temp = ArrayAppend(session.aEmails,arguments.email)>

                 <cfreturn>
    </cffunction>

         <cffunction name="addEmailToApplication" access="public" returntype="void">
        <cfargument name="email" type="string" required="true">

                 <cfset temp = ArrayAppend(application.aEmails,arguments.email)>

                 <cfreturn>
    </cffunction>
</cfcomponent>

testform.cfm

<cfif IsDefined("form.email")>
    <cfscript>
    application.myObj.addEmailToSession(form.email);
    application.myObj.addEmailToApplication(form.email);
    </cfscript>

         Your email address has been added to the application and session.<br />
    When those scopes expire you will receive an email that they have passed away.<br />
    The session should live for 10 minutes.<br />
    The application should live for 1 hour.<br />
</cfif>

<!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=iso-8859-1" />
<title>Test Form</title>
</head>

<body>

<cfform action="testform.cfm" method="post" format="flash" height="200">    
    <cfinput type="text" name="email" label="Email" width="200" required="yes" validate="email" validateat="onsubmit">
    <cfinput name="submit" type="submit" value="submit" />
</cfform>

Application
<cfdump var="#application#">

Session
<cfdump var="#session#">

</body>
</html>

Comments



March 29, 2005
Presentation - XML Technologies Buzzwords
I'm giving a presentation on several buzzword-compliant XML technologies (XHTML,RSS,Web Services) at an upcoming internal development conference in May. It gives a quick and dirty overview of the what, why and how all crammed into a 30 minute presentation. There isn't any code, but there are some great links to resources.

March 28, 2005
Fun with Cross-Site Scripting (XSS)
Every year Home & Garden TV (HGTV) gives away a million-dollar dream home. They open up the sweepstakes to online entries where you can submit one entry per day per email address through an online form. I really wanted to win the dream home, but didn't feel like going to their site every day to do it so I came up with a more creative solution. It took me about 5 minutes to scrape their entry form page for all of the necessary fields to cross-site script it and another 5 to write the code. I didn't figure that they would allow any type of XSS (as a safe coder wouldn't) but it worked like a little champion. Then I just scheduled the script to run each day until the sweepstakes ended, making sure to send an email to myself to let me know the entry had been made. I wasn't the winner, but I'll try again next year using the same technique (assuming they haven't wised up).

Here is the code:

dreamhome.cfm

<cfhttp url="http://web.hgtv.com/hgtv/web/contest/processEntryTrans/1,7754,,00.html" method="post" resolveurl="no">
    <cfhttpparam type="formfield" name="fvEmail" value="email@email.com">
    <cfhttpparam type="formfield" name="fvFirstName" value="FirstName">
    <cfhttpparam type="formfield" name="fvLastName" value="LastName">
    <cfhttpparam type="formfield" name="fvConfirmEmail" value="email@email.com">
    <cfhttpparam type="formfield" name="fvAddress1" value="Address1">
    <cfhttpparam type="formfield" name="fvCity" value="City">
    <cfhttpparam type="formfield" name="fvState" value="GA">
    <cfhttpparam type="formfield" name="fvZip" value="30310">
    <cfhttpparam type="formfield" name="fvAreaCode" value="555">
    <cfhttpparam type="formfield" name="fvPhone" value="555-5555">
    <cfhttpparam type="formfield" name="fvBirthYear" value="1969">
    <cfhttpparam type="formfield" name="fvGender" value="m">
    <cfhttpparam type="formfield" name="fvContestId" value="DH2005">
    <cfhttpparam type="formfield" name="fvSuccessPage" value="http://www.hgtv.com/hgtv/pac_ctnt_947/text/0,1783,HGTV_19176_26636,FF.html">
    <cfhttpparam type="formfield" name="fvErrorPage" value="http://www.hgtv.com/hgtv/pac_ctnt_947/text/0,1783,HGTV_19176_26638,FF.html">
    <cfhttpparam type="formfield" name="submitButton" value="Enter for a chance to win!">
</cfhttp>


<cfif cfhttp.statuscode CONTAINS "200" AND cfhttp.filecontent CONTAINS "dh05_th_thankstitle.jpg">
    <cfmail to="email@email.com" from="email@email.com" subject="Dream Home Entry Submitted Success">
    Dream Home Entry Submitted Success #Now()#
    </cfmail>
<cfelse>
    <cfmail to="email@email.com" from="email@email.com" subject="Dream Home Entry Submitted Failure">
    Dream Home Entry Submitted Failure #Now()#
    </cfmail>
</cfif>

February 24, 2005
MVC Framework hotfix
Amar Lungare identified a potential issue with the FrontController.cfc component of MVCF-CF on CFMX 7. I haven't been able to duplicate his observed behavior, but since his fix tests out on my environment there is no reason to not post it. I'll be updating the reference code and documentation ASAP. I will also test against a 1.5 JVM and see if that is the difference. My suspicion is that Tomcat could be the culprit. Thanks to Amar for identifying the issue and coming up with a fix.

His environment:
CFMX 7 J2EE
Tomcat 5.5
Windows XP SP2
JVM 1.5.0_01

My environment:
CFMX 7 J2EE
JRUN 4
Windows 2003 Server
JVM 1.4.2_05

Code change:

FrontController.cfc Line 229

Current Code:
<cffile action="read" file="#expandPath('.')#\#thisControllerFile#" variable="controllerConfig">

Fix/Workaround Code -
<cffile action="read" file="#GetDirectoryFromPath(GetCurrentTemplatePath())#\#thisControllerFile#" variable="controllerConfig">

Comments


February 22, 2005
Using CFDOCUMENT for web grabbing
One of the many cool features of CFMX 7 is CFDOCUMENT. I've had to do several projects in the past with PDF generation from "grabbed" web content, primarily using ActivePDF Server WebGrabber. It is a great product, but can be a pain to setup and code for. CFDOCUMENT makes that all go away, plus it adds FlashPaper as an output option. Here is a simple code example of a self-posting form which allows you to specify the page you want to grab and how you want to output it.

generateDocument.cfm
<cfif NOT(IsDefined("form.submit"))>

<!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=iso-8859-1" />
<title>CFDOCUMENT</title>
</head>

<body>
<cfform action="generateDocument.cfm" method="post" name="getDocument" preloader="no">
URL: <input name="theUrl" value="http://www.yahoo.com" type="text" size="100" /><br /><br />

CFDocument Type <select name="cfdoctype" size="1"> <option value="pdf">pdf</option> <option value="flashpaper" selected>flashpaper</option> </select><br /><br />

Page Type <select name="pagetype" size="1"> <option value="letter" selected>letter</option> <option value="legal">legal</option> </select><br /><br />

Page Orientation <select name="orientation" size="1"> <option value="portrait" selected>portrait</option> <option value="landscape">landscape</option> </select><br /><br />

Background visible? <select name="backgroundvisible" size="1"> <option value="true" selected>true</option> <option value="false">false</option> </select><br /><br />

Embed fonts? <select name="fontembed" size="1"> <option value="true">true</option> <option value="false" selected>false</option> </select><br /><br />

<input name="submit" type="submit" value="submit" />
</cfform>
</body>
</html>

<cfelse>
    <cfhttp url="#form.theUrl#" resolveurl="yes"></cfhttp>

    <cfdocument
    format="#form.cfdoctype#"
    pagetype="#form.pagetype#"
    orientation="#form.orientation#"
    backgroundvisible="#form.backgroundvisible#"
    fontembed="#form.fontembed#" >

    <cfoutput>#cfhttp.filecontent#</cfoutput>
    </cfdocument>
</cfif>

February 7, 2005
Blackstone shipping today!
I haven't had much to say lately on my blog about ColdFusion because I've been waiting on the new version to go gold. As an Alpha, Beta and RC tester you're under NDA (non-disclosure agreement), so I was very careful not to discuss any of the cool new stuff in public. Well that time is over, Blackstone is here! In the upcoming weeks/months you should see plenty of posts here about the awesome stuff in this release. In the meantime you can find product info here and some new articles about developing new version specific functionality here.

August 25, 2004
MVCF-CF
Have finally got around to documenting and sharing my Model-View-Controller Framework - ColdFusion (MVCF-CF) code. I've done four applications with it and am still going strong.

I developed this framework as a reusable ColdFusion MX based alternative to STRUTS for MVC development. MVCF-CF was inspired by STRUTS and the ideas of Benoit Hediard. You can find a presentation that he did on MVC here. It has great ideas of how to code Entity components which are totally compatible with the MVCF-CF implementation.

If you decide to use it as the basis for your application development, put a shout-out on your homepage (like mine to Ray Camden for using his blog code), and share it with friends and colleagues. I'm open to ideas for improving the core codebase, so feel free to comment or send errors, omissions and suggestions.

Here is a high-level presentation on the framework.

Here is the technical documentation.

Here is the code.

July 15, 2004
Nadsat Translator Web Service
I wrote a Nadsat translating web service awhile back as a proof-of-concept for ColdFusion MX based services, so I thought why not put it up here. In case you didn't know, Nadsat is the language of "A Clockwork Orange" (my favorite movie). If you want to play around with it in your web browser click the Nadsat Translator link on your left (My links). To consume it as a web service, the WSDL is : http://www.illumineti.com/nadsat/nadsat.cfc?WSDL. If you don't know what a web service or WSDL is, I can't help you with that unless you bring your checkbook;P

March 31, 2004
CF Server Status Monitor
The ColdFusion Server Status Monitor (CFSSM) is an application that I wrote to provide a safe, read-only way of looking at the configuration and health of a CF server. Features include: Datasource and Verity Collection status monitoring, log and mail spool viewers, ability to dump scoped variables, and all CF configuration information. Provides all of the things a developer might need to troubleshoot CF problems without having to access the ColdFusion administrator. Great for servers where a developer does not have access to the CF administrator. The code can be found here. Feel free to give feedback or suggestions of enhancements. Should work on all versions of CF, but definitely works on CF5 & CFMX.

February 8, 2004
ColdFusion Exception Handling and Cross-Site Script Blocking Presentation
This is a presentation I did on Exception Handling and Cross-Site Script Blocking in ColdFusion. The cf_xssblock tag can be found here.

February 8, 2004
SQL Server for CF Developers Presentation
This is a presentation I did last year on SQL Server for ColdFusion developers. It is a little thin, as I had about 2 hours notice that the DBA who was originally supposed to present had called in sick. Turns out he had such a fear of public speaking that became ill over it.