Kim Blyth
Kim Blyth

Reputation: 65

Coldfusion 8 respond to particular error

I am writing an API which exposes parts of our database to a client. Part of this API requires certain HTML response codes to be sent for particular conditions. This is generally easy with simple checks, but I can not see how to catch (for example) 'InvalidDateTimeException' errors where an invalid date is submitted to SQL.

I have tried dumping the ERROR and cfcatch variables, but while they generate huge stack traces I cannot see any field that is easily parsable to check the specific type of error (short of doing a text search on the error message or stack trace).

I could also do a pre-check with regex such as

(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})

but this could still generate invalid dates. Coldfusion also provides some date validation, but I have read that it is particularly bad. This also wouldn't help other scenarios that don't deal with dates.

So in brief: What is the best way to react to a particular error such as 'InvalidDateTimeException' in coldfusion?

[Edit] Some clarifications from the comments - We are using MYSQL 5 and cfqueryparams. We use the 'euro' date format here in Australia but it would be much prefered if the api user presented ISO format dates (yyyy-mm-dd) to avoid confusion.

Upvotes: 0

Views: 125

Answers (1)

Aaron Terry
Aaron Terry

Reputation: 328

Well .... my advice to use is to catch the error before it gets to SQL. You didn't specify your DBMS (SQL Server, MySQL, etc), so I'll focus on ColdFusion solutions. I hope one of these suggestions point you in the right path.

Options:

  • The article that you linked to concerning Coldfusion date validation mentions the isValid function as the recommended solution. Consider using that with the USDATE validation type, as suggested.
  • If you are using CFCs or at least cffunctions for your API methods, then you have cfargument type="date" at your disposal to assist with ensuring the dates are valid (although my feeling is that would have the same lenient behavior as isDate)
  • Inside of your cfquery tag, you should be using cfqueryparam for all of the parameters you pass, especially those passed directly from the user (whether a form post or a API call). You should use cfqueryparam cfsqltype=CF_SQL_DATE

Using any of the methods above (or all of them) you should wrap your coldfusion code in a try/catch construct and have a much easier error to deal with.

Depending on your DBMS, you might have access to Try/catch constructs there too.

**** UPDATED:

After reading your comment about the international conversion issues, I have two approaches that I'd choose between:

Keep in mind that I haven't tested any code or anything ....

First, maybe the international functions can help you.

http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_in-k_37.html

Use Setlocale to set the location to English (Australian) and then use LSParseDateTime to read in the yyyy-mm-dd format and then use dateformat to write it to mySQL using mm/dd/yyyy or whatever dateformat it expects. I don't have much experience dealing with those LS functions though.

Second option, use the regex you provided to make sure that the input has the right structure, then use createDate to create a date in US format using the parsed mm dd and yyyy elements. Validate the usdate using isValid.

Here's a blindly coded attempt at the second option. Remember, I haven't tested this code. I'm heavily using the list function listGetAt to split the inputted datetime into separate date and time strings and then using listGetAt to parse out the individual date parts.

<cfscript>
    isosampledate = "2013-06-05 14:07:33";
    passesValidation = false;
    expectedDatePattern = "\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}";
    try {
        if (refind(expectedDatePattern,isosampledate)) {
            datePortion = listGetAt(isosampledate,1," ");
            timePortion = listGetAt(isosampledate,2," ");

            yearPart = listGetAt(datePortion,1,"-");
            monthPart = listGetAt(datePortion,2,"-");
            dayPart = listGetAt(datePortion,3,"-");

            hoursPart = listGetAt(timePortion,1,":");
            minutesPart = listGetAt(timePortion,2,":");
            secondsPart = listGetAt(timePortion,3,":");

            thisUSDate = createDateTime(yearPart,monthPart,dayPart,hoursPart,minutesPart,secondsPart)

            if (isValid("usdate",thisUSDate) {
                passesValidation = true;
                sqlDate = CreateODBCDateTime(thisUSDate);
            }
        }
    } catch (e:any) {
        passesValidation = false;
    }
</cfscript>

I'm pretty sure that if the inputted value was not a valid date then at least one of those date functions would throw an exception which would get picked up by the catch block.

Hope this helps. I'm off to bed.

Upvotes: 2

Related Questions