Tuesday, 31 July 2012

CFCHART phones home

G'day
Sorry about the lack of post today (or yesterday, depending on your TZ)... I had some family dramas to deal with that needed to take precedence over my waffling.

This is just going to be a quick post too.

Stephen Walker put me onto this via Twitter, and all credit for noticing this goes to him.

Sunday, 29 July 2012

Are CFINSERT and CFUPDATE as bad as everyone makes them out to be?

G'day
This is a bit of a lazy-Sunday sort of posting.  I was on the Adobe forums last week, and CFINSERT and CFUPDATE came up in conversation.  The person asking the question was asking about <cfqueryparam> and I responded to that (and cross referenced to my post on that topic, should you want to read it), but I mostly left the <cfinsert> and <cfupdate> side of things alone, sniffing with distain and moving on to something else.

I decided I didn't like leaving the question unanswered, so revisited it today.

I could recall a discussion a while back about these two tags not parameterising their values, which kinda invalidates them in my view.  But I decided to find out where they're at now.

I found this bug that was raised on the old bug tracker which covers this topic, and the ticket is still open so it seemed like the problem still existed.  However I never trust the Adobe bug tracker because... well... err... it's just not very good and not very accurate, so I decided to re-investigate for myself.  I knocked together some quick code, thus:

Saturday, 28 July 2012

Investigation into applicationStop()

G'day
This is a bit of a funny ("odd" as opposed to "amusing") one today, as I set out to investigate a hypothesis with preconceived expectations, but it turns out the expectations were wrong. But in a good way as it turns out.

A wee while ago - in the weeks leading up to ColdFusion 10's release - I was involved in a discussion about how applicationStop() works, and that it apparently had a moderately serious glitch in it that rendered it not production-ready.

What seemed to be happening was that as soon as applicationStop() was called, it did what it said on the tin: stopped the application. However it did this without any consideration of any requests which might still be running, and they'd possibly error if suddenly the application scope vanished.  This could be a risk because applicationStop() only stops the application: it doesn't start it again... It relies on the next incoming request to trigger this. However an already-running request will - in the meantime - not have an application!

I'm an fairly certain I tested this on CF9.0.1 and the beta of CF10, and these concerns were borne-out.

This morning I wrote some test code to demonstrate this to you, and go "oh dear... that's not good, is it?".

Friday, 27 July 2012

How do I know if this variable is a file handle?

G'day
I'm not going to make a habit of making two posts in one day, but this quandary has just presented itself, so I'm gonna ask about it on StackOverflow, the Adobe forums, and Twitter (via this post).

I have this code:

This is a version of the code from my earlier post, having been fixed slightly as per Simon Baynes's observation that I had a spurious catch() block in the original.

Anyway, there's another bug in it: if there was an error during the fileOpen(), then the file variable won't be a file handle, so the fileClose() in the finally block will error.  Oops.

So I need to identify whether the file variable is actually a file handle, and iff it is, then close it.

Why do CFML arrays start at 1 instead of 0?

G'day
A few weeks ago whilst investigating something completely unrelated, I came across an interesting thread on StackOverflow, in which someone had asked why ColdFusion arrays start at index 1 rather than index 0 like other languages do.

This was an old thread, but my thoughts on it were a bit different from the others thusfar offered, so I wrote up my own point of view. Whilst writing it I started to think "I wish I had a blog for this sort of thing, rather than posting it on an old thread on StackOverflow"... and it was that thought that culminated in me finally starting this blog.

Anyway, I realise it's a bit of a duplication, but I'm "reclaiming" the post for myself. Here it is.

Thursday, 26 July 2012

Finally

G'day... This is another one of those "Adam admits he's a bit thick, and doesn't RTFM" kind of posts.

Yesterday I was writing a function which loaded and read from a file, and extracted some info from it. It's entirely legit for the thing being sought to not be in the file, and the correct response in this case is to return an empty string. I wanted to deal with the chance of the file ops failing, so I wrapped the whole thing in a try/catch/finally as one is wont to do. I'll stop describing the code and just list it:


Can you see the stupid thing I've done here?

It seems straight fwd: I look for the value I'm after, return it if I find it, or if I get to the end of the file I return an empty string. If I encounter any problems, I just error, but make sure I close the file.

Except it doesn't work... I always got an empty string. The matching & extraction logic is fine (I checked): it just wasn't working.

Wednesday, 25 July 2012

The holy grail

No, this ain't about Grails, sorry. I dunno anything about Grails, so anything I write about it would be rubbish, anyhow.

What it is is a follow-up to a conversation (if that's the right word) on Twitter last night regarding ColdFusion and backwards compat between releases.

Adobe treats the notion of backwards compatibility in ColdFusion as a "Holy Grail": it's often cited as one of the most important considerations when undertaking changes/enhancements to the language.

Whilst I respect "maintaining backwards compat" as a goal, I do not respect the lengths Adobe go to sometimes to preserve backwards compat at the expense of... well...  doing work. I think this has lead to some inertia in the language, and has contributed to ColdFusion lagging behind both in comparison to its competitors (Grails etc), and even now its imitators (Railo & OpenBD). ColdFusion might be a RAD language from a development perspective, but it's a creaky old behemoth when looking at its release cycle and recent language innovations. Take note I am specifically referring to language innovations here, not the various plug-ins and wrappers for third-party efforts such as Hibernate and Ehcache integration.

When I say "language innovations", I mean stuff at a level I cannot integrate myself. Closures in CF10 would be an example here. Or Application.cfc from CFMX7, or CFCs in general from CFMX6.0. Continuing to improve CFScript coverage would be an example if this, too.

Tuesday, 24 July 2012

What are the most common CFML tags?

G'day. There was a bit of a break there: no post yesterday. I'm not on the wane yet, it's just it was such if a cracker day in London yesterday that I went to stand outside the pub in the sunshine after work, and by the time I got home I was... err... well a bit pissed, actually.

Note to Americans: that means "drunk" in our vernacular, not "angry".

Anyway, I decided not to write anything. I think we can all be grateful for that.

Yesterday's pre-work research was to write some code to tally up what CF tags we use in our codebase, to compare this with the codebases of one of our older and less-well-maintained apps, as well as our brand-spanking-new app's codebase. Just to see if it turned up anything interesting.

Before I go on (and on... and on... and on... ;-), do me a favour? Jot down what you think would be the ten most-commonly-used CFML tags, and once you're done reading, post 'em as a comment. There's no right or wrong here, I just wanna gauge people's impressions. This would be my list:

Sunday, 22 July 2012

Joe Rinehart's thought-provoking video

Joe Rinehart released a very forthright and thought-provoking video about what he perceives to be some significant issues with ColdFusion as it stands today.  If you've not watched it already, here it is:


And the URL is: http://www.youtube.com/watch?v=I1KjX5NOD7c.

I've taken the liberty of transcribing the "script" of the video here (well: I couldn't be bothered doing a 100% transcription, so it's a bullet-pointed transliteration/paraphrase), as a basis for a discussion.  I hope you don't mind Joe, and if you do: let me know and I can work out an alternative approach.  But just to be clear, the text in the grey box below is Joe's good work, not mine.  I was just the typist.

Saturday, 21 July 2012

Which is better: having your methods inline in a CFC, or included from a separate file? (cont'ed)

This is just a reply to Henry, Shawn and Dave regarding my earlier posting on this topic, but as it's longer than 4kB, I cannot post it as a comment to the original post, so I'm creating a new one.

Hi guys. I didn't reply to the bulk of this last night cos I was watching a movie(*) and could multi-task enough to keep an eye on the #ColdFusion channel on Twitter, but not enough to give my reply to you the attention it warrants.

@Henry. Yeah, I too am let down by the lack of static methods in ColdFusion, and for the same reason. I have hit Adobe up about this a coupla times (for CF9 and for CF10), but I'm always swamped by colleagues saying it's to complicated to implement (this was not from Adobe, but a CF community member, so dunno if that has merit); most CF developers are too "junior" to understand what they are so it'd be wasted on them; you can work around it easy enough; ColdFusion is all about simplicity, and this concept is to complicated; and that old specious chestnut "if you want to use Java, use Java". Which is all a mix of faulty logic or is just plain facile. Still: the idea always garners this negative criticism, so I guess it didn't seem compelling to Adobe. Anyway: we are where we are... no static methods.

Friday, 20 July 2012

Which is better: having your methods inline in a CFC, or included from a separate file?

A question came up on StackOverflow about whether it's "better" to compose a CFC vis a single CFC file, out to include the methods via <cfinclude>. Thus is an interesting topic (after a fashion), so I decided to look into it some more, beyond the answer to the specific question on StackOverflow.

Just to set a baseline, what Henry was asking is whether there are performance considerations when contrasting these two approaches to composing a component:

<!--- MethodsInline.cfc --->
<cfcomponent>
    
    <cffunction name="publicMethod" access="public" returntype="struct" hint="This is my public method">
        <cfreturn arguments>
    </cffunction>
    
    <cffunction name="privateMethod" access="private" returntype="struct" hint="This is my private method">
        <cfreturn arguments>
    </cffunction>
    
    <cffunction name="packageMethod" access="package" returntype="struct" hint="This is my package method">
        <cfreturn arguments>
    </cffunction>
    
    <cffunction name="remoteMethod" access="remote" returntype="string" hint="This is my remote method">
        <cfargument name="who" type="string" required="true">
        <cfreturn "hello, #arguments.who#">
    </cffunction>
    
</cfcomponent>

Thursday, 19 July 2012

According to ColdFusion "0,6" == "6,0". And both are integers to boot

G'day
If you participate on StackOverflow or the Adobe ColdFusion Forums, you might be aware of this already.  But I thought I'd write it up again, and also solicit people's opinions on the topic.

Consider this code:

<cfset list1 = "0,6"> 
<cfset list2 = "6,0">
<cfoutput>

<cfif list1 eq list2>
    #list1# equals #list2#<br />
<cfelse>
    #list1# does not equal #list2#<br />
</cfif>

What would you expect this to output?  Would you be surprised to here it outputs this:

0,6 equals 6,0

I was, initially.  My reaction was something along the lines of "WTF?"

Wednesday, 18 July 2012

The IMP Operator

G'day
Everyone knows about boolean operators such as AND, OR and NOT.  I was surprised one day - about a year ago - when I tried to create a variable"imp" (or "iMP" or whatever... I forget what the situation was now) that I got an error, replicated here:

The following information is meant for the website developer for debugging purposes.
Error Occurred While Processing Request

Invalid CFML construct found on line 1 at column 8.

ColdFusion was looking at the following text:imp
The CFML compiler was processing:

  • A cfset tag beginning on line 1, column 2.
The error occurred in D:\websites\www.scribble.local\junk\junk.cfm: line 1
1 : <cfset imp = "foo">

That didn't give me much to go on, but eventually I just started changing random things (not an approach to problem-solving I recommend, btw ;-), including the variable name, and the problem went away.  I changed the variable name back to "imp" and the error came back.  At which point I consulted Google, and it pointed me to the docs for  Operator types: Boolean operators.

Tuesday, 17 July 2012

Quick follow-up to CFPARAM posting

G'day.
A coupla days ago I posted about how the default attribute of the <cfparam> tag worked.

Surprisingly - given it was a pretty bland topic - I did get some feedback from a colleague of mine (if nothing else, at least I know someone read it!).

Depsite being a better CF developer than I am, it hadn't occurred to him how the default thing worked, so it goes to show that even documented stuff escapes people who have had a lot of experience; they just haven't encountered everything in the language.

But he came up with another point for me to investigate: if <cfparam> behaves like that... is there a risk <cfargument> does too?  This would actually be something of a concern for us if it did.

This has given me another topic to investigate and report back on (thus staving off for another day the fear I have of running out of stuff to say... ;-)

Monday, 16 July 2012

RTFM, Cameron: CFCASE

Here's another one to file under a "stating the bleeding obvious" category (like the <cfparam> one from y/day).

Possibly like everyone else who isn't 100% au fait with the docs and the way all CFML tags work, and thinking I know better, I have been caught out in the past trying to do this:

<cfswitch expression="#someVariable#">
    <cfcase value="#SomeDynamicValue#">
        <!--- do some stuff --->        
    </cfcase>
</cfswitch>

Sunday, 15 July 2012

<cfparam>: the expression in the default attribute value is always evaluated

G'day:
Yeah, OK, I'm writing a blog entry about <cfparam>, which I think ought probably be considered perhaps the most boring topic ever.  Sorry about that, but: it's a) Sunday; b) before I've had any coffee.

Word of warning: make sure you've had your coffee before wading through this ;-)

This is another thing that cropped up in a conversation I was having the other day: even if the variable being paramed is already set, the expression in the default attribute value is always still evaluated.  Before anyone panics, I don't mean "evaluated" in the sense of the oft-maligned evaluate() function, I just mean the expression is processed / executed / whatever.

A bunch of people probably already know this, but a bunch of people probably don't.  The target audience here is the latter.  For my part: I am certainly one of those that this didn't occur to me until it bit me on the bum one day, and then I slapped my forehead and went "well: duh!", but I had to have the bum-biting happening first.  So I'm trying to avoid derrière dentition for other people here.

Right: so what am I blathering about?

Saturday, 14 July 2012

CFML: onApplicationStart is not intrinsically single-threaded (part 2)

G'day:
I'm very new to the blog carry-on, and was quite pleased to get some good feedback from my first post, and that it was sufficiently interesting for me to create a follow-up post to take a look at the question.

David McGuigan made a comment, and had this to say (extract):
[If] you call onApplicationStart programmatically, [...] say with a check in onRequestStart for a URL scope flag that triggers it from within Application.cfc itself, it still *is* single-threaded.
I gotta say my initial thought was "um... I'm pretty sure it's not single-threaded", but I wasn't completely sure, so decided to look into it.


I knocked-together some slightly different code from last time, thus:

<!--- Application.cfc --->
<cfcomponent>

    <cfset this.name                = "singleThreadedAppStart3">
    <cfset this.applicationTimeout  = createTimeSpan(0,0,0,30)>

    <cffunction name="onApplicationStart">
        <cfset application.startTick = getTickCount()>
        <cflog file="#this.name#" text="[#getTickCount()-application.startTick#] Top of onApplicationStart() called via #CGI.script_name#">
        <cfset application.startedBy = CGI.script_name>
        <cfset sleep(10000)>
        <cflog file="#this.name#" text="[#getTickCount()-application.startTick#] Bottom of onApplicationStart() called via #CGI.script_name#">
    </cffunction>

    <cffunction name="onRequestStart">
        <cflog file="#this.name#" text="[#getTickCount()-application.startTick#] Top of onRequestStart() called via #CGI.script_name#">
        <cfif structKeyExists(URL,  "restart")>
            <cfset onApplicationStart()>
        </cfif>
        <cflog file="#this.name#" text="[#getTickCount()-application.startTick#] Bottom of onRequestStart() called via #CGI.script_name#">
    </cffunction>

</cfcomponent>

I've added a coupla bits in here that stand quick clarification:
  • I'm setting a small application timeout, so between tests I get a new application starting.  I only mention this because I've been a bit of a drongo (look it up) in the past, and when I want to scrub my test application I change the name in the this.name setting (as you can see I've still actually done this three times in my code as it is, eg: "singleThreadedAppStart3").  There's no need to do that... a 30sec time out is enough for me to run the test and then whilst analysing it, the app times out of its own accord, ready for the next test.  This is not earthshattering, but I was marginally pleased with myself for this finally occurring to me to do.  I now feel I'm slightly less stupid than I was yesterday.
  • I've added to the log entries how long it's been since the app was started (well: in this case, "since onApplicationStart() was called"). This info is already in the log entries, but this just makes it a bit more clear in the extract I'm going to include below.
  • I've added in one of these "restart the app" conditions into onRequestStart(), so I can specify on the URL to restart the app.  I'll repeat that this is not something I would usually do nor do I recommend it as a practice, but it's relevant to this discussion.
Other than that, it's all the same gig as last time:  basically log what's going on when the app starts,  so I can see what order (and when) events occur.  And in the app start code I have a contrived 10sec delay to make it easier to to time my "simultaneous" requests.

The calling code for this is much the same as before:

<!--- requestOne.cfm --->
<cfdump var="#application#" label="#CGI.script_name#">

<!--- requestTwo.cfm --->
<cfdump var="#application#" label="#CGI.script_name#">

The test I run is to do this:
  1. Hit requestOne.cfm (without the restart switch set).  This is just to warm up the app.
  2. Count off my guess at 5sec (so halfway through the 10sec delay in onApplicationStart())
  3. Hit requestTwo.cfm (again, with no restart switch set).  This is just to "prove" that app restart - if not calls to onApplicationStart() - are single-threaded.
  4. Wait for them both to finish, but being mindful that my new 30sec app timeout is perhaps working against me here (I screwed it up the first time, forgetting about it, I have to admit.  Back to being as dumb as I was y/day.  Sigh ;-)
  5. Hit requestOne.cfm?restart=true
  6. Count to five again.
  7. Hit requestTwo.cfm?restart=true
So what I'm testing here is twofold:
  1. that my baseline is sensible... the actual application start-up process is single-threaded.
  2. However the actual test hypothesis is that the second two calls to onApplicationStart() actually are not single threaded.
Right.  What's in the log?

[0] Top of onApplicationStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[10002] Bottom of onApplicationStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[10005] Top of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[10005] Top of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestTwo.cfm
[10017] Bottom of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[10022] Bottom of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestTwo.cfm

[12291] Top of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[4] Top of onApplicationStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[4097] Top of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestTwo.cfm
[0] Top of onApplicationStart() called via /shared/CF/other/appcfc/singlethreaded/requestTwo.cfm
[5908] Bottom of onApplicationStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[5909] Bottom of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestOne.cfm
[10001] Bottom of onApplicationStart() called via /shared/CF/other/appcfc/singlethreaded/requestTwo.cfm
[10002] Bottom of onRequestStart() called via /shared/CF/other/appcfc/singlethreaded/requestTwo.cfm


And what does this tell us?

I've put a break between the two sets of requests (steps 1-3, then steps 5-7).

The first block shows us that requestOne.cfm takes the mantle of starting the application up, and requestTwo.cfm patiently waits until requestOne.cfm is done, then it continues its request (and it doesn't call onApplicationStart() at all).  Good.  This is what we want.

The second block is our actual test.  What we see here is that requestOne.cfm starts, and correctly calls onApplicationStart().  However requestTwo.cfm comes in right behind it (note the "4097ms": I can't actually count off 5sec very well... ;-), and it also merrily calls onApplicationStart() too.  Bleah.  We really didn't want that to happen.

This is especially true if we look at the dumps afterwards:

/shared/CF/other/appcfc/singlethreaded/requestOne.cfm - struct
applicationnamesingleThreadedAppStart3
startedby/shared/CF/other/appcfc/singlethreaded/requestTwo.cfm
starttick1342293921379

(wow: am quite impressed I could just copy the CFDUMP output from my browser into here and it renders perfectly.  Nice one blogger.com).

/shared/CF/other/appcfc/singlethreaded/requestTwo.cfm - struct
applicationnamesingleThreadedAppStart3
startedby/shared/CF/other/appcfc/singlethreaded/requestTwo.cfm
starttick1342293921379

 So unfortunately as requestTwo.cfm started to execute onApplicationStart()'s code before requestOne.cfm had finished, we get the wrong value for application.startedBy.

This is a foolishly contrived example, I know, but it shows the point: onApplicationStart() in and of itself is just not single-threaded no matter how you spin it.  It's just a method in a CFC.  The single-threadedness of application start-up is because app-start-up is single-threaded, not that onApplicationStart() itself is single-threaded.

One last thing I better check... Dave, is that what you were kinda talking about?  It'd be... "funny" if I'd blathered on about all this, and you were actually meaning something else.  Heh... :-/

Righto... cheers all and enjoy your Saturday.  What's left of it, if any.

--
Adam

Friday, 13 July 2012

CFML: The difference between events and event handlers

G'day:
Here's another quick about Application.cfc.

In a conversation a few weeks back I was talking with a colleague about the applicationStop() function that was added to ColdFusion in CF9. Docs here.

I can't recall the exact gist of the conversation, but we got to the point where my colleague suggested that rather than stopping the application, it could simply be restarted by calling onApplicationStart() (or a combination of onApplicationEnd() and onApplicationStart() or something). This is the same conversation that resulted in my earlier post about the single-threadedness of onApplicationStart().

One thing to bear in mind here is that calling onApplicationStart() does not start your application. It's just something that gets called when ColdFusion starts the application. Obviously a lot of what constitutes your application being in a "started" state is the code that gets executed when onApplicationStart() runs, but onApplicationStart() is not in and of itself what causes an application to start.


Similarly, onApplicationEnd() doesn't end your application. ColdFusion handles the application ending... it just has the courtesy of allowing use to specify some of our own code that runs when it takes the application down. Same with sessions: running onSessionStart() doesn't start a session, and running onSessionEnd() doesn't stop the session. And, yeah, samesame with onRequestStart() and onRequestEnd(): they don't start and stop a request (those two are a bit more obvious).

This might seem obvious to people, but it does trip a lot of people up, and I include myself in that group until I sat back and reflected one day.

The thing is that there's two different notions here; an event, and an event handler. In the process of going about its business, ColdFusion will cause events to happen, such as starting an application, session or request, and at some later point in time it ends them too. But those are the events, and it's ColdFusion that performs them. What Application.cfc gives us is the ability to specify event handlers which ColdFusion calls as part of it performing the actual event. So ColdFusion performs/executes/whatever-you-want-to-call-it an event (I dunno what the best technical term is? Anyone?), and then it calls our event handler from Application.cfc. What this doesn't mean is that the opposite is true: running the event handler doesn't cause the event to occur.

A way to easily see the distinction here is to forget about ColdFusion and think about JavaScript for a moment. If one clicks a mouse button, a click event occurs, and in turn an onClick event handler could run. However the reverse is obviously not true: running the onClick handler obviously doesn't cause the mouse button to depress. That's probably a good way of thinking about it. It's certainly helped me keep it straight in my head.

And now it's time for the pub.

--
Adam

What one can and cannot do with <cfqueryparam>

G'day:
Looking at how other languages handle DB interaction, <cfquery> is one of the best things about CFML.  It's just so easy.  We all know how it works, but here's a pointless reminder of what you already know:

<cfquery name="q" datasource="dsn" result="stResult">
    any old string you like
</cfquery>

In its most basic usage, ColdFusion takes the string and sends it to the DB driver.  The DB driver passes this to the DB, the DB does something with it and sends back a response to the DB driver and then to ColdFusion, and ColdFusion exposes via the variable named in the NAME and/or RESULT attributes (I'm not going to repeat the docs, which are here: go read 'em).

Another thing that ColdFusion does really nicely is play with strings, inline in the body of your CFM file.  We might have this SQL to pass to the DB:

Thursday, 12 July 2012

CFML: onApplicationStart is not intrinsically single-threaded

G'day:
I read somewhere today someone say onApplicationStart is single-threaded, as a justification for removing a <cflock> from some code that was causing another person some problems.

In the explicit context under discussion the person was offering good advice, but the blanket statement that onApplicationStart is single-threaded is not entirely accurate.

In ColdFusion, application-start-up is single-threaded. And during application start-up onApplicationStart is called. So that call to onApplicationStart is also single-threaded.

However the single-threadedness here is not intrinsically related to onApplicationStart.