Shaun Mccran

My digital playground
 
25
M
A
R
2010

Pre loading object (CFC) references in your Application.cfc

One of the best practices that I've been using more and more is ColdFusion's ability to add CFC object references to scopes. By this I mean that it is possible to create a shorter friendlier scoped variable that you use to reference your CFC's.

In your Application.cfc you can map out all your CFC references, this gives you a much shorter variable name to type each time, and it caches the CFC.

view plain print about
1<cffunction name="onApplicationStart">
2
3<!--- scope out all the objects as application level vars --->
4<cfset application.formObj= createObject('component','dir.objName ')>
5<cfset application.siteObj= createObject('component','dir.objName')>
6<cfset application.mailObj= createObject('component','dir.objName')>
7<cfset application.config=createObject('component','dir.objName').getConfig(id=N)>
8
9</cffunction>

Put any references like this in the 'onApplicationStart' function. You do not need to lock the scope in this function, and if the code within it does not run successfully then it does not continue running the application. It will try again on the next page request.

The caching functionality here is great, not only will Coldfusion create a handy short name for CFC, but it will actually run through the code, and stop on any errors. If you deliberately introduce a code error into one of your objects you will see the Application halt and show you the error. For me this is reason enough to move all my business logic into CFC's. This essentially means that it is not possible for a user to get part of the way through a application and find an object based error.

Using this in conjunction with a framework such as FuseBox allows you to load, parse and cache the CFC object, all before your actual display layer has been invoked.

The example below uses the FuseBox function 'onFuseboxApplicationStart' of starting an Application.

view plain print about
1<cffunction name="onFuseboxApplicationStart">
2    <cfset super.onFuseboxApplicationStart() />
3<!--- scope out all the objects as application level vars --->
4
5<cfset application.formObj= createObject('component','dir.objName ')>
6<cfset application.siteObj= createObject('component','dir.objName')>
7<cfset application.mailObj= createObject('component','dir.objName')>
8<cfset application.config=createObject('component','dir.objName').getConfig(id=N)>
9
10
11</cffunction>

Changing the 'fusebox_parameters.mode' value allows you to set this caching at an environmental level, so no caching for development, or caching for live

view plain print about
1<cfset FUSEBOX_PARAMETERS.mode = "development-full-load">
2Or
3<cfset FUSEBOX_PARAMETERS.mode = "production">

 
22
D
E
C
2009

Using Isapi / Apache rewriting to mask URL strings, for cosmetics and security

One of the more recent additions to my Coldfusion frameworks is masking the more ugly URL's using Isapi rewrite. In this article I'll be using Helicon's Isapi ReWrite, but Apache re write works in much the same way.

Usually in your Coldfusion frameworks, most other technologies as well, you are passing around a variable or two to control the page content, and more often than not it is in the url. It never looks particularly clean if your URL has a long name value query string behind it, like this:

view plain print about
1http://www.mysite.com/index.cfm?variable1=pagename&location=england&value=7

Cosmetic reasons

So for two reasons URL rewriting seems like a good idea.

Firstly to mask those ugly URLS with a url rewriter. On a basic level this will re write specified request to the URL you tell it to, taking your ugly list of name value pairs and changing it into a user friend URL. If you are pitching this to a client this looks a lot more professional.

Security reasons

Secondly there is an added security benefit here. The URL gives a lot away about a website, like what the code base is, and is potentially a window on the internal workings of a website. Take a normal FuseBox application for example. The normal URL might be:

view plain print about
1www.mysite.com/index.cfm?fuseaction=controller.action&othervalues=values

From here it is very easy to start messing around with the controller names, trying to dig out an 'admin' controller, or other common function controller. Similarly adding values to pages where it is obvious a Query has been fired is an easy way of testing of the developer is using 'cfQueryParam', with potentially disastrous results.

Along the same lines it is quite simple to inject form values into the URL (like this http://www.mccran.co.uk/index.cfm/2009/7/30/Cross-site-Script-hacking-using-the-GET-method). By masking the URL and the values you make it considerably more difficult to do this, after all if you can see or get to the URL, how can you fool around with it?

So far I am implementing a rewrite script that will rewrite URLs into friendly strings, here is a modified version of the .htaccess file I'm using.

view plain print about
1# Helicon ISAPI_Rewrite configuration file
2# Version 3.1.0.68
3
4RewriteEngine on
5RewriteBase /wwwroot/
6
7#generic
8RewriteRule requestID/(.*)/(.*)/ index.cfm?decryptURL=$1&params=$2
9
10# site pages
11RewriteRule home(/)? index.cfm?go=controller.home
12RewriteRule contact(/)? index.cfm?go=controller.contact
13RewriteRule login(/)? index.cfm?go=controller.login
14RewriteRule privacy(/)? index.cfm?go=controller.privacy
15RewriteRule about(/)? index.cfm?go=controller.about
16RewriteRule faqs(/)? index.cfm?go=controller.faqs
17RewriteRule search(/)? index.cfm?go=controller.search

This code starts off by turning the rewriteEngine on, then setting the rewriteBase, this is typically your webroot, or the root of the site the file is for. Then it rewrites any URL params to the URL string.

The main part of the code is where we set individual rewriteRule's for each URL. The first example (home) looks for any URL requests to the 'home' string, and re writes this to the URL in the regular expression (index.cfm?go=controller.home). Pretty straight forward really.

There is a lot more you can do with this, and hopefully I'll get to explore rewriting in more depth in the future.

 
16
D
E
C
2009

Using Isapi rewrite to serve up non existing templates

I was discussing some ideas for an application framework this morning with the team, and one of the issues we hit upon was having a common directory for templates, but serving them up as if they were from a different directory.

The idea is to have one instance of a reusable skinnable template, that appears to live on several sites.

IE all the content lives in "webroot/content/templateName.cfm", but is actually served up by many sites, IE "127.0.0.1/site1/template1.cfm", "127.0.0.1/site2/template1.cfm" ... etc

In this way they can be re skinned or adapted as needed, and they aren't database driven. The main stumbling block for the discussion was the need to actually create blank versions of each of the named templates, in each of the sites, as ColdFusion server would error on the request.

I spent twenty minutes trying to work it so that my Application.cfc's onRequest or onRequestStart method would intercept the request before it was actually made, but that just wasn't working. My other idea was to use the onMissingTemplate method, but the server is only running ColdFusion 7, so that was a no go (I figured I could catch the missing template request and just re path it, although I'd have to assess if that was really inefficient due to almost every page request logging as failed).

My eventual solution was Isapi rewrite. I am re writing all the requests to the same template, and just passing in the template variable. In that way I can request pages that don't actually exist, but they appear in the url.

Create an index.cfm template like this:

view plain print about
1<h1>I am the index page</h1>
2<ul>
3    <li><a href="page1">Page 1</a></li>
4    <li><a href="page2">Page 2</a></li>
5    <li><a href="page3">Page 3</a></li>
6    <li><a href="page4">Page 4</a></li>
7</ul>
8
9<cfdump var="#url#">
10<!--- write a handler to go get the url var passed in --->

For this example I am using the free version of Helicon's Isapi rewrite, you can get it here: Link to Helicons Isapi re write

In the example below I have altered the first page link to look like it is actually a .cfm template request, just in case you want the url string to have a .fileextension look to it.

view plain print about
1# Helicon ISAPI_Rewrite configuration file
2# Version 3.1.0.68
3
4RewriteEngine on
5RewriteBase /mywebroot
6
7#no physical page testing
8RewriteRule page1.cfm(/)? isapitest/index.cfm?p=page1
9RewriteRule page2(/)? /index.cfm?p=page2
10RewriteRule page3(/)? /index.cfm?p=page3
11RewriteRule page4(/)? /index.cfm?p=page4

So when you fire it up and test it you just see /page1, /page2 etc, and the pages don't actually exist.

I'm not experienced enough with Isapi rewrite to know if there is a downside to this, but bookmarking in a browser still works correctly, so I can't see an issues at present.

 
20
N
O
V
2009

Exploring the variations in email UN subscription methods

If you are anything like me, everyday you are smothered in a stack of emails from various companies all delivering html formatted, image heavy flyers persuading you to buy whatever dead horse they are flogging. I know it is my own fault, after all I signed up to them in the first place, I've only got myself to blame. As I find myself checking (and deleting) these email on an Android mobile device now it has become hassle-some. So I set out to unsubscribe from the majority of them, which is where the inspiration for this article came from.

In a short period of time I have unsubscribed from around a dozen different email newsletters, and because of this the differences in the methods used to accomplish this have become glaringly obvious. I was very surprised at the variations in the methods used, some are very user friendly, and others are very much not. I won't name the companies involved.

Case one:

By far the easiest user interaction, this is a simple link from an email that provides you with a screen confirming your UN subscription. No prompt is required from the user, you are simply unsubscribed. All the data is passed seamlessly behind the scenes.

Case two:

Almost the same as above except that you are taken to a screen where you have to commit an action. You are presented with a screen displaying your email address, and prompted to click a button to confirm the UN subscribe action. This may be a handy safety net to step errors from the casual clicker.

Case three:

Clicking on the link from an email takes you to a generic page with a form on it. They have not transferred any form of token from the email so you are prompted to enter the email address you want to UN subscribe. Entering your email address takes you to a screen confirming your action. This additional step is unnecessary, and doesn't add any value at all.

Case four:

In this scenario we are passed to a page where we have to login. The subscription details are attached to an account application, and as such your credentials need to be verified. Based on passing an encrypted token from the email a user could easily be logged in automatically. Actually requiring a username and password adds an additional level of complexity. Once I logged in I then had to navigate to the subscription settings and choose to unsubscribe with a form similar to the ones mentioned above.

Case five:

In the most convoluted example I have come across so far I actually had to create an account. I arrived at the UN subscribe page and found that to subscribe did not require an account, but to change my subscription options did! This was a very strange scenario, requiring a user to create an account to stop emails. Once you have created an account the subscription options were managed through a form like the ones mention above.

Conclusions

I think the thing to keep in mind with functionality like this is the balance between usability and the business objectives. An obvious point to note is that businesses do not want their users to UN subscribe to their emails. This is their user base and they do not want to lose it. Still it is worth considering just how you interact with your customers, even when providing functionality you do not want them to use.

After all you can always just 'Mark as Spam'.

 
07
N
O
V
2009

Testing methodologies - Regression testing

One of the more overlooked forms of testing (you do test don't you?) is regression testing. I'm a big fan of scripted testing using both scripted tests to actually run against your code base (think cfUnit or Junit) and scripted testing as in a basic word doc of testing instructions.

This word doc can be as simple as 'click button N' - what displayed on screen? You can literally just list the actions, expected consequences and actual conqequences.

Regression testing is the practice of going back after a release and testing the functionality that was already present. IE did you break anything by releasing your new functionality. Often the business and IT focus is on the shiny new development, not the integrity of the existing application.

Developers in particular are guilty of zoning in on the specifc area that they are directly involved with. This can sometimes lead to other areas suffering, especially if you have an OO application layer. In just how many places is each individual object referenced? A change to it may work in one area, but have devastating consequences in another.

I've seen cases of this where its been months later before an error has reared its head, and without an accurate change log it can be difficult to track the root cause down. Needless error tracking and bug fixes take developers away from actually developing, and essentially cost the business money due to bad practice.

I mentioned scripted testing above as it has had unforseen beneficial consequences. If you have done anything like this in the past, your regression testing will be very easy. You will have a handy library of repeatable scripted tests, so it is very easy for you to measure the previous results against any new tests you might perform. Thus making it instantly obvious wether your functionality is still behaving as it was before the release.

 
01
O
C
T
2009

Introducing third party applications into your frameworks, good practice?

A recent development involved some changes to a large script that was using a product called ImageMagick (link). It is an image manipulation tool that allows you to perform transformations and other actions on image files. The product seems stable enough, and can be executed from a web interface using cfexecute, in a kind of command line prompt method.

It got me thinking as to why the application wasn't using cfimage, and then lead me to examine the wider topic of whether to use ColdFusion's in built functionality, or opt for other third party products.

I can think of a few obvious deciding factors for both pro and con, the first that springs to mind is performance.

Is there a marked performance difference between a ColdFusion function, and the third party application? Is it better to pass the load of to the operating system, rather than have ColdFusion perform whatever processing function it is supposed to do? In this case it would be a race between cfexecute, and cfimage, so there may be very little difference in it.

The second major point that springs to mind is the knowledge base of the developer, and the structure of whatever framework you are using. What I really mean by this is 'if your chosen technology can perform a function, why not utilise it to its full potential?' . It seems a bizarre choice indeed to deliberately not harness a function that your platform can already provide, and instead introduce another code base or application into the framework.

It also introduces another hurdle for the development staff, they may well be familiar with how an existing Tag works, but be totally unaware of the third party application, as was my case here.

A long winded intro, but here is the code I used:

view plain print about
1<!--- setup vars --->
2<cfset variables.destination = "C:\dev\images\testimage.jpg">
3<cfset variables.source = "C:\dev\images\testimage.jpg">
4<cfset variables.width = "100">
5<cfset variables.height = "100">
6<cfset variables.exec = "C:\dev\apps\imageMagick\convert.exe">
7
8<!--- executing an external application version --->
9<cfexecute name="#variables.exec#" arguments="-size #variables.width# #variables.source# -geometry #variables.height# -strip #variables.destination#" variable="imageinfo" timeout="3" />
10
11<!--- CFimage version --->
12<cfimage source="#variables.source#" action="resize" width="#variables.width#" height="#variables.height#" destination="#variables.destination#">

 
30
S
E
P
2009

A simple Fusebox reset function

A simple Fusebox reset function

I am always forgetting the application URL for resetting fusebox frameworks, so instead of having to type out the entire fuseaction url, and appending the load variables, and the parsing variables you can create a fuse action for it.

view plain print about
1<cffunction name="rebuild">
2        <cfargument name="myFusebox" />
3        <cfargument name="event" />
4
5        <cfset xfa.reinit = "index.cfm?" & FUSEBOX_PARAMETERS.fuseactionVariable & "=" & "&fusebox.loadclean=true&fusebox.parseall=false&fusebox.execute=true&fusebox.password=" & FUSEBOX_PARAMETERS.password>
6        <cflocation url="#xfa.reinit#" addtoken="false">
7    </cffunction>

The code above will build the URL using the fuse action variable (IE 'action=' or whatever you have specified). It also uses the fusebox password set in your Application.cfc.

There may be a small security risk involved with this, so don't use an obvious name for the function. Also they would need your fusebox password.

Even then thought the only potential issue I can see with this is that someone may empty your framework cache and rebuild your application. Which isn't all that bad?

 
26
A
U
G
2009

Example of inserting a Struct() into a database using keys

A while ago a colleague and I were working on a timesheet application in Flex. The idea was that you could commit a custom timebar object, generated in flex, and it would update the dataset in the back end using the ColdFusion flex gateway.

I came across the code recently, and decided to tidy it up a bit, and make the query dynamic, based on the Struct contents. The obvious limitation to this is that your Struct and your database schema have to match exactly.

I won't go into the Flex application here, but I've emulated its input arguments here with a pre-populated structure.

view plain print about
1<cfscript>
2 timesheetTask = StructNew();
3 StructInsert(timesheetTask, "employeeid", '36');
4 StructInsert(timesheetTask, "timesheetDT", '0');
5 StructInsert(timesheetTask, "projectid", '6');
6 StructInsert(timesheetTask, "weekid", '25');
7 StructInsert(timesheetTask, "taskid", '39');
8 StructInsert(timesheetTask, "hours", '8');
9 StructInsert(timesheetTask, "comment", 'Comments for this task live here');
10 StructInsert(timesheetTask, "szStatus", '1');
11 StructInsert(timesheetTask, "iFirstLineApproval", '23');
12 StructInsert(timesheetTask, "iSecondLineApproval", '34');
13 StructInsert(timesheetTask, "iCurrentApprover", '');
14 StructInsert(timesheetTask, "szRejectReason", '');
15 StructInsert(timesheetTask, "szDescription", '');
16
17 updateTimesheet = createObject("component", "timesheet");
18 updateTimesheet.updateTask(timesheetTask);
19
</cfscript>

Notice that this code also calls the CFC object at the end. The data itself isn't massively important, it's a time object for recording tasks.

Next we have the function, which accepts a Struct() argument called 'taskStruct'. I then loop through the structure, and populate a SQL query using the keys from a collection. The only logic is a check to see if it is the last structure element, as this controls the ',' placement.

view plain print about
1<cffunction name="updateTask" access="remote" returntype="string" hint="Creates a record for timesheet tasks">
2 <cfargument name="taskStruct" type="struct" required="yes">
3 <cfset var count = 0>
4
5 <cfdump var="#arguments.taskStruct#">
6 <cfset variables.structSize = structCount(arguments.taskStruct)>
7
8 <cfquery datasource="#application.dsn#">
9 INSERT INTO [dbo].[timesheet]
10 (<cfloop collection="#arguments.taskStruct#" item="key">
11 [#key#]
12 <cfset count = count + 1>
13 <cfif count LT variables.structSize>,</cfif>
14 </cfloop>)
15
16 <cfset count = 0>
17
18 VALUES(<cfloop collection="#arguments.taskStruct#" item="key">
19 '#arguments.taskStruct[key]#'
20 <cfset count = count + 1>
21 <cfif count LT variables.structSize>,</cfif>
22 </cfloop>)
23 </cfquery>
24
25 <cfreturn true>
26 </cffunction>

That will insert your Struct into a database, in small and tidy manner. It was somewhere around here that we started using cfproperty tags, and creating strongly typed objects for Flex.

More Entries


This content is purely my opinon, any offence or errors are unintentional, please comment your views appropriately
Site Credits
Aggregated by ColdfusionBloggers.org Powered by Coldfusion

Technology & Science Blogs - BlogCatalog Blog Directory Blog Directory & Search engine