Now that you’ve looked at the original version of the application, take a look at the ColdFusion MX version. Open your browser to http://<your server>/devnet/cfmx, to see an exact replica of the ColdFusion 5 version. Clicking a press release causes the same workflow as before, a detailed view of the press release. In fact, this version of the application acts exactly as before, but as you will see, the code is somewhat cleaner and simpler, and also has more capabilities then the earlier version. Listing 6 shows the new and improved Application.cfm file.
Listing 6: /cfmx/Application.cfm
<cfapplication name="devnet_cfmx" sessionManagement=true>
<cfif not isDefined("application.init") or isDefined("url.reinit")>
<cfinclude template="global_vars.cfm">
</cfif>
Except for the changed application name, there is only one main difference, it contains no cflock tags. With ColdFusion MX, there is only one reason to lock application, session, or server variables, and that is the danger of a race condition. For this application, it is not a concern. Since you don’t have to worry about general memory corruption, you have absolutely no need for the cflock tags. The global_vars.cfm file is also similar to the earlier version:
Listing 7: /cfmx/global_vars.cfm
<cfset application.dsn = "devnet">
<cfset application.pr = createObject("component","pressrelease")>
<cfset application.init = true>
As in the last template, the main change is that it doesn't contain the cflock tags.
I’ve also added another application variable, application.pr,
that refers to a ColdFusion component (CFC). This article is too short to go
into detail about ColdFusion components. For now, consider a CFC as simply
a package set of methods and data. In this case, you are going to use the CFC
to handle the press release logic. For more information on CFCs, see http://livedocs.macromedia.com/coldfusion/6.1/htmldocs/building.htm and
Ben Forta's article, Introduction
to ColdFusion Components.
Take a look at Listing 8, which displays the press releases.
Listing 8: /cfmx/index.cfm <cfmodule template="/devnet/tags/layout.cfm" title="Press Releases"> <cfset getPressReleases = application.pr.getPressReleases()> <p> Welcome to Acme, Incorporated. Supplying the weapons/trap needs of coyotes everywhere! Here are our latest press releases. </p> <cfoutput query="getPressReleases"> <a href="press_release.cfm?id=#id#">#title#</a> [#dateFormat(publishDate,"m/d/yy")#]<br> #teaser#<br><br> </cfoutput> </cfmodule>
Notice that there is no query in this file. Instead, you simply use the CFC you defined earlier. The CFC handles all of the logic I mentioned before (i.e., the application only retrieves press releases that are active, and with a publish date before the current date). Notice how simple the template is. There is a much bigger separation of data and presentation now. What’s even better is that if for some reason the logic about which press releases to display changes (maybe you decide to ignore the active flag, maybe the publishDate column gets renamed to publicationDate), you don’t have to worry about updating the index file or any other file. You can simply handle any and all changes within the component itself. Let’s see how the press release display page has changed.
Listing 9: /cfmx/press_release.cfm
<!--- Make sure URL.ID was passed and it is numeric --->
<cfif not isDefined("url.id") or not isNumeric(url.id) or val(url.id) lte 0>
<cflocation url="index.cfm">
</cfif>
<cfset getPressRelease = application.pr.getPressRelease(url.id)>
<!--- Was a valid ID passed? --->
<cfif not getPressRelease.recordCount>
<cflocation url="index.cfm">
</cfif>
<cfmodule template="/devnet/tags/layout.cfm" title="#getPressRelease.title#">
<cfoutput>
<p>
Posted: #dateFormat(getPressRelease.publishDate,"m/d/yy")#
</p>
#paragraphFormat(getPressRelease.body)#
<p>
<a href="index.cfm">Return to Press Releases</a>
</p>
</cfoutput>
</cfmodule>
As in the previous version, this page ensures that the url ID variable was passed, numeric, and positive. Next, you use the CFC again, calling a method, getPressRelease. Pass the ID of the press release you want to retrieve, and as before, if the query returns nothing, you use the cflocation tag to redirect the user to the index page. The rest of the page simply displays the press release. Again, notice that you don’t have a cfquery tag. In the ColdFusion 5 version, the query on both the press release and the index page maintained the same checks (active is true, publishDate before the current date). If you added or modified checks in general, you had to update both pages. With this versio, that is no longer a concern, the component handles it.
Take a look at the administrator. As before, you don’t have any change in functionality, but this new version takes advantage of a new feature in ColdFusion MX: roles-based security. Read more about this feature at the following URL: http://livedocs.macromedia.com/coldfusion/6.1/htmldocs/appsecur.htm. Take a look at the new Application.cfm file in Listing 10.
Listing 10: /cfmx/admin/Application.cfm
<!--- Load root Application.cfm --->
<cfinclude template="../Application.cfm">
<!--- Handle logon --->
<cflogin>
<cfset variables.showLogon = true>
<cfif isDefined("form.logon")>
<cfif isDefined("form.username") and len(trim(form.username)) and
isDefined("form.password") and len(trim(form.password))>
<cfif form.username is "admin" and form.password is "admin">
<cfloginuser name="#form.username#" password="#form.password#"
roles="administrator">
<cfset variables.showLogon = false>
</cfif>
</cfif>
</cfif>
<cfif variables.showLogon>
<cfinclude template="logon.cfm">
<cfabort>
</cfif>
</cflogin>
In this version, the main difference is that you no longer check for a session
variable. Instead, you surround the authentication code with the cflogin tag.
This tag handles almost everything security-related for you. When the user
requests any page within this directory, the cflogin tag executes.
If the user is not logged in, the code inside the tags executes. Inside, the
code is pretty much the same as before. You check the username and password
against a hard-coded set of values. This time, however, when the user enters
correct values, you use the cfloginuser tag. This is all that
it takes to use the new security feature in ColdFusion MX! Another nice aspect
of this feature is that it automatically integrates with ColdFusion components.
I can easily set up a CFC so that only administrators can use certain features.
So while on the public side you had methods to get all press releases and to
retrieve one particular press release, the administrator will use methods to
add, edit, and delete press releases. You protect all of these methods by simply
adding the roles attribute to the method. Because CFCs are a bit
complex, I haven’t shown the code for this yet. After you’ve read up a bit
on CFCs, return to the code in the sample files and take a look at how easy
it was to set up.