Blog

Entries for month: April 2007

Adobe Made me Obsolete

April 25, 2007 · 5 Comment s

It looks like with the Scorpio tour in full swing, the NDA is up on certain aspects of ColdFusion 8. (I'm still going to tread lightly though.) But according to this article from the downloadsquad, Adobe finally revealed that they went and added Exchange Integration to ColdFusion.

Up until now, the only game in town was using Webdav to communicate with Exchange. I've been pushing the little bit I know about it for the last year.

I've never been happier to be out of a line of work ever. This stuff is tough to write and fickle to maintain. Microsoft doesn't make it any easier by breaking stuff when they push out updates.

I've been working with it in the Beta tests and I can categorically say: Adobe has made it truly easy to interact with Exchange. Short of working in .Net, there is no easier way to programmatically interact with Exchange than with what the ColdFusion team achieved here. This is to say, having worked with .Net, there is no easier way to programmatically interact with Exchange than with ColdFusion 8.

I have some ideas for best practices of working with Exchange from ColdFusion when we can all talk more freely about it. In the meantime if you get a chance to get on the Beta trial give it a chance; it will knock your socks off.

5 Comment s Tags: Web Development · ColdFusion

Twitter's System Maintenance Page

April 19, 2007 · 2 Comment s

I would like this image to be Wharton's new maintenance page. I wonder if Bob would go for that.

2 Comment s Tags: Web Development · ColdFusion

Top Code Review Issues

April 19, 2007 · 3 Comment s

I figured I would blog about what I've been seeing during code reviews lately. Maybe someone else has been seeing too, or seeing other issues. I've omitted problems that deal with our shop's internal best practices, and tried to stick with things that would apply more globally. If I over applied something let me know. It's a long one, so more after the jump.

5. Improper implementation of Application.cfc inheritance

Application Inheritnace is very useful for application and sub applications development. However there is a gotcha to remember here. If you are going to override application variables that you set in onApplicationStart, they you need to give the application.cfc its own this.name. Why?

  • Imagine this:
  • Application.cfc
    • This.name=parent
    • OnApplicationStart
      • <cfset application.title = "Parent" />
  • Child/application.cfc extends="../application"
    • OnApplicationStart
      • <cfset application.title = "Child" />

In this case, assuming the application is not started, going to a page under the child will trigger onApplicationStart. But since they have the same application name through inheritance, going to any parent page will not trigger OnApplicationStart, and they will be stuck with the application title of "child."

The easy fix here is to always give children a different application name, only omitting it when you have a specific reason not to.

4. Improper Access on CFC methods

The four access types of CFC methods tend to cause people some confusion especially when they are learning the whole CFC thing. They each have different implication for application security.

I've pasted a more in depth guide below, but for the most part you probably shouldn't set access=remote. Even if you are writing a webservice, only the exact method you are calling needs to be set to remote, so don't set all of the methods called from your webservice to remote.

  • Private
    • Only accessible by other functions in CFC
    • Used for sub functions only relevant to CFC
  • Package
    • Only accessible by code in same folder
    • Any sort of organization makes this almost useless
  • Public
    • Accessible by any code on the server
    • Sounds scary, but relatively safe on a dedicate server
    • Use with caution on a hosted box.
  • Remote
    • Used for webservices.
    • If building webservices these should be accompanied by some security or logging.

3. Inappropriate use of a Query of Queries

Query of Queries have many legitimate uses. They include but are not limited to:

  • Performing SQL syntax queries on query objects returned from non-SQL operations. (Ex. <CFLDAP> <CFDIRECTORY>)
  • Joining the results of two queries made from two different sources (Ex. Joining MS SQL and Oracle data, or SQL and LDAP data.)
  • Providing multiple views to the same data on the same page request. (Ex. Showing a chart of data sorted multiple ways on the same page.)

However, where they get deservedly shunned is when they are reproducing functionality that can be completely handled in native SQL. In my experience, this is often (but not always) done by developers who know Cold Fusion very well, but not advanced SQL, therefore when they can't get the problem solved in SQL they fall back on Cold Fusion to do what they need to get done. (At least that's what I was doing when I got yelled at for it.)

In many cases, it takes less time to post the SQL request to the database server and get the response back then it does for Cold Fusion to process the request on an in-memory query. It's counter-intuitive, but such is the power of indexing and SQL-based set operations. Case in point, when I was designing a dictionary check for a password change page, it made sense to load the entire dictionary into an application variable, and then do a query of queries on it. The process took 3000ms, or 3 seconds, which is slower than a request really should take. The same request against the database server took half that. Ultimately through indexing and query tuning, I got the process down to 100ms.

Your mileage may vary, especially depending on the size of the dataset, but the point remains that you should let SQL be SQL and Cold Fusion be Cold Fusion.

And by the way, I'm not being original here, other people have said this:

ColdFusion is Not a DBMS

2. Fake Email addresses in error or reporting pages

If your application sends email, those emails should be sent from a legitimate, addressable email address. (Whether or not the email goes to a list, a mailbox, or some other place is not a factor.) There are a couple of reasons for doing this:

  • It is not inconceivable in the future that your organization, hosting provider, or your user's email host will start rejecting messages from invalid addresses due to spam considerations.
  • Any bounces generated from these messages will never get back to you.
  • Users responding to these messages will get ungraceful bounce responses.

Of these reasons, 1 is probably the most important as spam or virus concerns have forced mailing hosts to make quick decisions like this without consulting others, due to the severity of the issue. But this is one of those easy to fix low hanging fruit issue.

1. Lack of Var scoping in CFC methods

This is a pretty familiar issue to everyone. I don't want to belabor it. As a matter of fact I'll just link to a bunch of posts about it:

Additionally there is a tool you can use to help programmatically attack this problem:

VarScoper

3 Comment s Tags: Web Development · ColdFusion · Running a ColdFusion Shop

Running a ColdFusion Shop Part 4

April 17, 2007 · 4 Comment s

I received an email today, that reminded me of a topic I wanted to throw up on my Running A ColdFusion Shop series.

The email:

Subject: Mail Queues Need Attention

Body: Hoth Spool could be backed up.

query - Top 1 of 1 Rows
DATELASTMODIFIED DIRECTORY NAME SIZE
04/17/2007 05:43:54 PM C:\CFusionMX\Mail\Spool Mail22186.cfmail 719


To unblock spool:
Drain stop node(wlbs drainstop)
Restart Cold Fusion Service.
Restore node (wlbs start)

Make sure before doing this that the node is actually backed up.
One or two messages in the queue does not a blockage make.
But depending on the number of items and length of their stay, you can make the determination.

What this email reminded me to say was: DRY isn't just for code.

We had this problem a while back. Every once in awhile, the mail queues on a random one of our ColdFusion servers would back up. The mail would remain stuck until the server was restarted. Developers and users started getting pissed about their application email being delayed.

The short term solution was to check the queues every once in awhile. Once the problem stopped occurring, we stopped checking... until it happened again. We looked for a hotfix, to no avail. We did this a couple times, and each time we got burned when we stopped being vigilant.

Finally I said "Screw it; I'm scripting a solution to it." I started checking to see if files were in the spool directory of all of our servers. Then I had to make sure that the files had sat there for a little bit instead of just having been written there. Finally I had to send an alert with the needed fix.

No big deal, it's not advanced programming, it's not even particularly good code.

The point here is that it was running in a scheduled task... since I wrote it in 2005 (and restarted it earlier this year.) We had this problem again today, and nobody outside of my team noticed.

So what's the point of this besides a little bragging? Don't do things by hand that you can automate and forget about, or DRY isn't just for code.

4 Comment s Tags: Web Development · ColdFusion · Running a ColdFusion Shop

Running a ColdFusion Shop 3

April 12, 2007 · 6 Comment s

For Reference: Part 1 and Part2.

It's been awhile, but I've finally got more to say about all this.

Backup

In the last one of these, I told you to back up your system. Maybe not directly, but it was there. Okay, so I didn't say it. I'm saying it now. Backup your machines. Do a tape backup, export to an external drive, do anything. Just backup your machines.

Backup Configuration Files Separately

Independent of a backup solution that takes care of your whole system, I would also recommend backing up configurations to separate location, in their current format. Meaning, don't put them on a tape, don't ship them off site. Just keep them somewhere you can access them. Why? Coldfusion is pretty light. CFML sites are comprised of pretty small files. Odds are, if you have a systems failure, it very well may be faster to rebuild a system from scratch then it will be to get a system backup restored and working. Rebuild your server, reinstall your webserver, and reinstall ColdFusion, all while getting the CFML files from backup. Then use configuration files you've stored elsewhere to restore both your webserver and Coldfusion to its old state. By this point, the CFML files should be out from a restore.

There are other uses for these files. You can use this method to clone your boxes, for clustering for example. Additionally, the ways they are broken up make it easy to share certain areas of configuration between machines. The most useful of these is neo-query.xml, which has all of your datasources on it.

Anyway, you probably want to know where all of these are:

  • ColdFusion configuration information is stored in xml files, in [CfusionRoot]\lib.
  • IIS XML configurations can be exported from the IIS Manager
    • Right Click website
    • Choose "All Tasks"
    • Choose "Save Configuration to file."

I'm sure that Apache has something to handle this too. But I don't have any experience with it.

Backup Certificates

If you are using SSL certificates, back them up. They are a pain in the ass to manage. If you lose one without a backup you have to depend on the Certificate Authority to get your SSL service back up. Better to just have them ready to go in case of a problem.

Again I can only speak authoritatively about IIS, but:

  • Go to IIS Manager
  • Right click your SSL secured site
  • Choose "Properties"
  • Go to "Directory Security"
  • Under "Secure Communication" hit the "View Certificate" button
  • Choose "Details" tab
  • At the bottom "Copy To File"

That will bring up the "Certificate Export Wizard." I usually choose the default options, with one exception. I choose "Yes export the private key." It's less secure, so you want to make sure you store them somewhere safe, but you'll be able to do this again with a certification created from a backup with the private key.

That's all I got this time around. Sorry it's all backup related. Nothing happened; I was just collating tips for building a new Coldfusion box in our environment, and realized that these were all pretty important to doing that

6 Comment s Tags: Web Development · ColdFusion · Running a ColdFusion Shop

I'm coming to cf.Objective 2007

April 11, 2007 · 1 Comment

I just found out I get to go to cf.Objective this year. Woohoo.

Airline tickets, hotel room and conference reservation are already booked.

1 Comment Tags: Web Development · ColdFusion

CFUse CFTry CFCatch

April 04, 2007 · 5 Comment s

I was in a code review earlier last week, and someone said that they didn't like using <cftry> and <cfcatch>. When we as a group investigated further it was revealed that they had used it "incorrectly," experienced problems for doing so, and labeled the try catch model as bad, instead of the implementation. So I figured I would quickly go over my opinions of what you should be using them for.

To start with, the incorrect usage of <CFTry> was wrapping it around a troublesome page, so instead of visibly erroring, the page would just silently fail. To add insult to injury, there was an error in the cfcatch block which caused the whole thing to throw an application level error anyway. This was, to put it mildly, a flawed use of <cftry> and <cfcatch>.

In a nutshell, the <cftry> and <cfcatch> model in ColdFusion is for handling expected errors, as opposed to handling unexpected errors. ColdFusion has a pretty good system for handling unexpected errors - a combination of <cferror> tags, and use of onError in the application.cfc. So wrapping an entire page in <cftry> to catch any error that may come up is not only the wrong thing to do, it's also pretty redundant.

In my opinion <cftry> and <cfcatch> should be used to handle errors around small pieces of code that have the potential to error in predictable ways. For example here is a line of code from one of my applications:

cfset Wsdl = "<webservice URL>" />

<cfset displayBrainstorm = FALSE />

<cftry>

    <cfinvoke timeout="1" webservice="#Wsdl#" method="AuthorInfo" returnvariable="BrainstormStruct">
       
<cfinvokeargument name="username" value="#url.username#" />
   
</cfinvoke>

    <cfset displayBrainstorm = BrainstormStruct.IsAuthor />
    <cfcatch type="any">
        <cfif FindNoCase("stub objects", cfcatch.Message)>
           
<cfset createObject("java","coldfusion.server.ServiceFactory") .XmlRpcService.refreshWebService(Wsdl) />

            <cftry>
                <cfinvoke timeout="1" webservice="#Wsdl#" method="AuthorInfo" returnvariable="BrainstormStruct">
       
            <cfinvokeargument name="username" value="#url.username#" />
   
            </cfinvoke>

                <cfset displayBrainstorm = BrainstormStruct.IsAuthor />

                <cfcatch type="any">
                    <cfrethrow />
                </cfcatch>

            </cftry>

        <cfelse>
            <cfrethrow />
        </cfif>

    </cfcatch>

</cftry>



In it you'll notice I'm doing a webservice call. In my experience webservices can have issues with the skeleton ColdFusion creates to consume them, especially if details about the webservice change. However, my application has little control over this webservice. So I wrap the call to the webservice in a <cftry> block, and if my expected error condition occurs, (something with to do the skeleton, or "stub objects") I reset the webservice and try again.

You'll notice that if it isn't a "stub objects" problem, it assumes that it is some other issue, and rethrows the error so the application error handlers can tackle the problem. Why, because it is an unexpected problem, not an expected one.

In conclusion, I'm not speaking for all programming languages, but at least in ColdFusion <cftry> and <cfcatch> should be used to handle error that you can predict. The shouldn't be your default error handling technique, and like a <Cflock> or a <cftransaction> they should surround as little code as possible.

5 Comment s Tags: Web Development · ColdFusion