Tuesday, 30 July 2013

Is there a way to make #Coldspring reload the CFCs on each requestion, for dev purposes? #coldfusion

I've had the same question myself, but never had to act on it so never bothered to check.

At the time I responded that I was pretty sure there was no "mode" in Coldspring to get it to change its load behaviour, and indeed one would usually only load beans when the application starts anyhow, so by the time a subsequent request comes around, everything's loaded.

Some people have code in their onRequestStart() which looks for a "reload" (or similar) URL param, and does an app-restart if it's found. This is an OK approach, but for some reason it's never sat that well with me. My feeling is that one's environment doesn't change from request to request, so it shouldn't be a request-centric process. It also leaves functionality intended for the dev environment accessible in the live environment, which isn't ideal IMO. It's not a major concern and is easily-enough worked around, but it got me thinking about alternative approaches. Not necessarily better ones, just an alternative.

Here's an approach which is based on the environment the code is running in, with the environment settings being dictated by an environment-specific config file.

In source control there's a bunch of environment config files, eg:

/config/
environment-config-DEV.json
environment-config-LIVE.json

Update:
As per a couple of the comments, I had been slightly too abstract for my own good in the code example, so I have modified it a bit. The intent was not to suggest one would always want to run Coldspring in a dev environment, just that if one wanted to whilst one was working on something that needed reloading every request, then it can be achieved using an environment-specific configuration. Hopefully my tweaking of the code has made this more clear. Or less unclear.

And when deploying, the deployment script takes the file appropriate for the deployment environment and deploys it as environment-config.json. In this case, a very pared down config file might be:

{
"coldspringLoadMode" : "REQUEST"
}

From there, the Application.cfc file reads environment-config.json (which is now environment-specific), and acts accordingly. EG:

So Application.cfc doesn't need to have logic to decide whether it's in LIVE or DEV mode, it just loads the config file, and then uses the environment-specific settings.

From a Coldspring perspective, we then have conditional logic as to where we do its initialisation. To facilitate this we factor out the Coldspring initialisation into its own method, and then conditionally call that method onApplicationStart() (when "live"),or onRequestStart() (if "dev").

That's it, really. I'm not saying this is a better approach to having URL-based stuff, but it's a case of different horses for different courses. Each approach has its pros and cons. And, indeed, both can be used in conjunction with each other.

G'day:
This article is partly a piss-take, and partly actual guidance. Mostly the latter. Thanks to Rob Glover (again!) for the inspiration for the article (both the piss-take and the actual meat of the article).

From here, the docs are referring to Coldspring installation / config issues, or tangential issues people have had, so not really relevant. Still: in the first six Google results, five are about Coldspring installation, and three of them have instructions.

So what's amazing about this is that Rob couldn't find any of this stuff.

But just for the sake of completeness, here are some instructions for installing Coldspring.

Update:
As Mark Mandel has pointed out to me, I only cover 1.2 here, and there is also 2.0 in the works (the status of it is TBC... I don't actually know). I'll find out if 2.0 works differently, and write a companion article if required.

Unzip the file into a non web browsable directory. Do not put it in your web root (this conflicts with most of the instructions you will see). After unzipping, you should have this sort of directory structure:

There will be a lot of other files in there, but that gives you an idea of what the directory structure is like.

In you application's Application.cfc, create a ColdFusion mapping to the [coldspring directory], eg:this.mappings = { "/coldspring" = expandPath("../coldspring")};In this case, my web root is adjacent to the coldspring dir, eg:

/[parent directory]/
/coldspring/
/webroot/
Application.cfc

as an alternative to creating the mapping in Application.cfc, one could instead create it in CFAdmin, but I think doing it in the application is preferable.

That is it as far as installation goes.

Note that a lot Coldspring installation instructions will by default suggest just dumping the Coldspring directory in the web root, because this is "easier" because it doesn't require the mapping. This is really poor advice for a few reasons:

It's not exactly difficult to create the mapping.

The Coldspring files are not intended to be web browsable, so why would the instructions suggest putting them in the web root? That's just wrong.

Having files not intended to be web browsed in a web-browsable directory is a potential vector for site hacking.

In fact most framework installation instructions prefer the lazy / wrong / insecure installation approach to the equally-easy / good / secure approach. So when you read framework installation instructions which advocate putting the framework in the web root as a default practice, screw your nose up in disgust, and don't do that. Generally a framework will be happy to be installed anywhere, and all it needs is a CF mapping with a known name (eg: /coldspring in this case).

So the install for Coldspring is easy. Here's a sample bare-bones application building on that, showing some of the config.

What the timestamps show is that the C bean is created once, during application start-up, and then calls to getBean() simply return that bean. Note that I pause for 5sec in test.cfm, but the timestamp o2 has is the original timestamp from app start-up, not the current timestamp from when o2 was created.

There's obviously a bunch more config options for Coldspring, but this is not an attempt to replicate the docs, it's just a top level summary of how to install it, and a bare bones example app showing the minimum config.

Hopefully this will help people trying to find Coldspring installation docs online.

I've got another article to come on Coldspring: also based on a question Rob asked the other day. Stay-tuned.

Monday, 29 July 2013

G'day:
Just to go off on a tangent... I'm doing Javascript this week, so the puzzling stuff I encounter will probably be JS rather than CFML.

Whilst I know a decent amount about CFML, my JS is... limited. I know enough to get into trouble... I know enough to know when I'm in trouble... but not necessarily enough to get me back out of trouble again.

G'day:
I've decided I want to know more about any CFML code incompatibilities / issues that arise from migrating the underlying JVM from Java 6 to Java 7. I've created a quick - single question, written answer - survey to gather info from people. Here's the intro text from it:

I executed the example you have showed above for customised sorting using arraysort function, but i didn't get the same result. The output i got was the array that i defined in the code. I can't understand why its not happening for me.

On SEO... if I search for "railo docs cfassociate" the first link is the page above. If I try "coldfusion docs cfassociate" I get the CF8 version of the docs as the first link, and the docs for ColdFusion 7 are third. ColdFusion 9 and 10 don't actually show up on that search, but Google displays them as results for "similar" searches: "coldfusion docs cfassociate", then the CF9 docs are listed. Oddly, if I actually do a search for "coldfusion cfassociate", I get the CF8 match first, the CFMX7 match on the second page (who the hell every looks at the second page of Google's search results? ;-), and by the time I gave up... page 5... I'd still not seen a link to the docs for any currently-supported version of ColdFusion. Blimey on page 3 there was a link to this blog of me talking about the tag, but nothing from Adobe on CF10 or even CF9. Slack. How can a web company be so poor at making sure their own docs are googlable?

G'day:
So I started to write an article on the performance of evaluate() (and whether it's still a problem), but I got sidetracked by other CFML stuff I was catching up on, and now I'm on to article two of three articles to today that I'm writing instead. Mostly cos they're easier than the evaluate() one.

Whilst researching the earlier article, I looked to see what other bugs there already were with toScript(), to see if I was treading already-trod ground (no, as it happens). Ad I came across this bug, raised by Ray Camden a while back: 3041310. The gist of it is demonstrated by this code:

G'day:
I'm in Portumna visiting my boy... well not right now, I'm in the pub starting my second pint of Guinness, but the point is I'm away from home and am on my baby netbook rather than my usual rig, so blogging / coding / internet access / my-ability-to-do-useful-things are all severely curtailed today.

Friday, 26 July 2013

G'day:Adam Tuttle (that's twice today) was quipping last that I'd mentioned him twice on the blog on Weds, and I should try for three times y/day (which failed: just the one mention, sorry). Anyway, as a joke back I said I should tag my articles with the people who I mention - these are usually people who have helped me, or caused me to write the article - and whoever is at the top of the list is automatically on my "give them beer next time I see them" list.

And then I thought... well why not? People do help me out and inspire me to write, and I appreciate it. So I did go through all my back articles last night, and tagged them up with the people I have mentioned in them, and I will continue to do so. So there are people's names listed at the bottom of the article on the "tags" bit, and the tag cloud thing on the right hand side also lists a bunch of people amongst the other tags I've got. Now there's been a whole swag of people tagged up, and the tag listing became unhelpful with every tag displayed, so you don't get a mention on the right unless you've got 3 mentions (or are Chris who only had two mentions until now, but as he wrote my most popular article, I decided to list his anyhow. And now he's got his third mention anyway).

Sean's currently at the top of the leaderboard, and there's a fair gap back to the rest of the pack.

G'day:
Whilst messing around with how scopes in functions in ColdFusion work, I came across something I didn't know: like Javascript, ColdFusion hoists its VAR declarations. This could be common knowledge, but I certainly didn't know.

Here's some code that shows how an unscoped variable within a function interacts with a samed-named variable in the arguments scope, and to what unscoped references refer.

Update:
Ray pointed out the way I had originally done the code was very hard to read (harder than usual ;-). I'd tried to take a sort of two-column approach so all the writeOutput() statements were off to the right next to the statement they were outputting stuff for, not underneath. This made it much easier to follow the code in a text editor, but it looked whack when it was in the blog. I didn't notice when I was proofreading. Anyhow, I've sorted it out now. Cheers for the nudge, Ray. And note to any other readers: do let me know if I screw anything up like this!

Thursday, 25 July 2013

G'day:
I've knocked out a quick arrayReduce() UDF, which I'll post on CFLib once I get some code review feedback (if any) on it. I'd appreciate sets of eyes on it, if you had time.

Update:
Adam Tuttle (only one mention today mate, sorry) offered some advice on Code Review, which I have taken onboard. This is the second iteration of the function. I have also updated the entry on Code Review too.

For the sake of completeness, here's the code, but pls feed-back on the Code Review page, as per link above:

Tuesday, 23 July 2013

G'day:
This is something that I've been mulling over / worrying about / contemplating for a coupla months now. I find myself poised over the keyboard frequently about to write this increasingly often. And Rob Glover is to thank for making the comment on Twitter that made me think "actually, yeah..."

This is my conclusion. I now believe Adobe is doing more harm to ColdFusion and CFML in general than they are good. And I think it's time - for the benefit of CFML as a language - for them to pull out. There's a few reasons for this.

Firstly, whilst they are "mothership", the language is just not going to go anywhere. As far as I can tell, no-one involved in the Adobe ColdFusion Team actually uses CFML as a matter of course, and I think the entire business unit is completely detached from the community. Worse, what they are doing on a day-to-day basis is Java. Whilst Java is a great language, it's not even remotely the same in intent as CFML is, and - worse - Java is a behemothemic (I made that word up) old juggernaut which works in a completely different way than the spritely languages that compete in the space CFML is struggling to be relevant in. Adobe don't (seem to ~) know how CFML is used, what the target market is, and what they should do with it to keep it relevant.

Secondly... $$$. I guess this makes sense. Adobe are not in the business of making a great language, they're in the business of making money for their shareholders. To do this, they need revenue, and to have revenue, they need to sell licences. Because they're in the software selling business. Unfortunately the people they market CF / CFML to are the people who pay for the licences, and all they need to do is to generate enough smoke, and angle the mirrors in the right way, and the licence-purchasing decision makers will re-up their licences. Especially if - and I think this is where the bulk of Adobe's ColdFusion revenue comes from - the person signing the cheques (dear god, I actually typed in "checks" then, initally) is doing so on behalf of some US government agency, and there's very little oversight on the sort of money they're paying; and what's more important to them is continuity, not innovation.

Thirdly. And this is how I came to this conclusion, remember, so this is the third reason that influenced me to think the way I do: Railo. I've been using Railo since it came on the scene, but only in the capacity of reading the mailing list and testing stuff out. I have never had any of my apps running in production on Railo. This is not slight on Railo, it's just that I have always worked for ColdFusion shops; licences already purchased. But over that time I've seen Railo arrive as the third possibly-viable CFML solution (after ColdFusion and BlueDragon... the New Atlanta one, not the Alan Williamson one, which came along around about the same time as Railo?), and then surpass BD (closed or open) becoming the second player in the CFML market, to now pretty much being the leader in the CFML community. I don't mean in revenue, or in "stature", but in importance. Basically I've gone from not giving a shit what Railo might have to say about CFML, to not giving a shit what Adobe might have to say about it (I never gave a shit about BD, for varying reasons). This is partly because Adobe hardly ever say or do anything sensible / useful about CFML other than when there's a release cycle on, and more recently because what Railo is saying about CFML and the CFML community just makes sense. Whereas everything out of the Adobe stable these days is going more and more heavily on the marketing smoke and mirrors, and is almost entirely without substance.

Fourthly I've been looking at other languages recently. I'm a slack-arse when it comes to forwarding my career prospects: I'm good at CFML and that finds me work. Well has done so far. I'm lucky in that regard (although I will never become a rich person with my work ethic, I at least have a place to hang-out and write code every day ;-). So I've pretty much focused on CFML and enough JS to get by over the last decade. However now that I'm looking, what I do see out there is every other relevant language just does stuff better than CFML does these days. It's a complete frickin' myth that CFML is still this quickest-to-market / rapid-development language. It might be so in the context of "my simple website", like what CFML used to excel at ten years ago, but in the context of doing more than "making it easy to generate HTML", even my superficial knowledge of competing languages reveals that CFML is basically irrelevant in that space now. Now I'm not saying some stuff on a line-of-code-by-line-of-code basis is simply easier to do in CFML, but I really think ColdFusion is lacking the bigger picture here. Plus it just moves too damned slowly to keep up. THat and when they do decide to do new stuff, it's crap like <cflclient> (ColdFusion 11's apparent marquee feature) which seems to be a wizard for writing JavaScript for mobile apps. In CFML. What? Are you lunatics, Adobe?

Update: <cfclient>? Wah?
Someone asked what I'm on about with this mention of <cfclient>. It was mentioned on a slide in a presentation I saw at cf.Objective() of new features coming to ColdFusion 11. There was also discussion of the CF -> Mobile functionality in the same presentation, and again at Scotch on the Rocks. I do not claim any specific knowledge about the functionality other than what's in the public domain via those sources.

The shining light here for CFML though, is Railo. They listen to their developers / their community. They do Railo (and accordingly CFML ~) consultancy, so they know what people on the ground are actually doing, and they enhance then language in ways that will benefit professional CFML developers. They seem to look at what other languages are doing, and consider those features for Railo / Railo's CFML. They keep the language alive and moving. They seem to give a shit about CFML (the Adobe ColdFusion Team seem to be interested in CFML because it pays their salary, and not really beyond that. Well that's my impression).

So here's what I think. Adobe? Give up on ColdFusion and CFML. You're not helping.

And Railo? Screw what Adobe might have done / might be doing with CFML. Take the language as your own (that sounds more melodramatic than I intend it to, but you get the idea).

G'day:
And to think someone said on Twitter the other day that I'm one of those people who are never wrong (the subtext being "actually you are, but just will never admit it"). Well here's an example of me being wrong, happily admitting it, and admitting to being a bit stupid to boot.

Saturday, 20 July 2013

G'day:
This isn't some attempt at a controversial reaction to something someone else in the community has said, it's just that the 2DDU podcast blog is a bit exclusive in that it requires a Facebook login to comment. And I do not have a Facebook account.

In January this year (so after the first six months), I was averaging 94 unique visitors per day; Over the most recent six months, it's about 150 per day. So not a huge amount of traffic still, but at least it's something. And it's generally building week by week, so that's a positive sign.

I said in one of my earlier articles that I've learned more about ColdFusion since I started this blog than I had in the preceding few years. This continues to be the case, and I've learned a bunch of good stuff about Application.cfc, ColdFusion regexes, JSON (grumble), REST, interfaces (in general, as well as ColdFusion's inplementation of them), and various other odds 'n' sods. Even some web sockets stuff, whilst troubleshooting that security issue from a coupla weeks back. I've also used Railo a lot more, and had a look at Coldbox. Beyond ColdFusion I've also started dabbling with PHP and Ruby. It's been cool! I hope some of it was useful to you, or at least slightly interesting. Or killed some time whilst you tried to decipher what I was wittering on about.

To close, I'd like to say special thanks to a few people whose participation in this blog has been helpful, interesting or thought-provoking. In no particular order, and it's certainly not an exhaustive list:

Chris Kobrzak

Sean Corfield

Andrew Myers

Bruce Kirkpatrick

Brad Wood

Andrew Scott

Adam Tuttle

Ray Camden

Gavin Pickin

Jay Cunnington

Simon Baynes

Duncan Cumming

Brian Sadler

There's been a bunch of great input / correction / sanity-checking / bullshit-detection done by a heap of other people too. Cheers to everyone who's participated here.

G'day:
I was looking up the docs for Javascript's String replace() function the other day (because, no, I could not remember the vagaries of its syntax!). And whilst being relieved I had remembered it correctly for my immediate requirements, I also noticed it can take a callback instead of a string for its replacement argument. How cool is that?

G'day:
A week or so ago there was some derision expressed that when approving UDFs submitted to CFLib we might change the code (for whatever reason). There was also derision expressed at how long it had thusfar taken to approve that person's UDF (it's still in the queue, and as far as I'm concerned: there it will stay for the foreseeable future... pretty much until everything else in the queue is cleared).

But due to this conversation I figured I might explain what it is I do when I approve a UDF. I cannot vouch for the process that Ray undertakes when he approves a UDF... this is simply the process I undertake. And I might perform some, all or none of these steps, as I see fit when doing the approving.

G'day:
This is a strange article, this one. It started off just being a feature request which I was typing into the Adobe bug tracker, but decided to write my thoughts up here, by way of soliciting other people's thoughts too. On re-read just before pressing "publish", I realise the framing for the point is about five times longer than the point itself. Oops. Oh well. It's a slow news day here. It's Monday after all.

ColdFusion has a function getMetadata(), which can be called on a variety of objects: an CFC instance, a user-defined function, a property, a query. I'm just focusing on on its usage with "objects".

I just found this one when testing Mockbox 2.1. Testing it to see if we could upgrade to it (no, not until this is fixed). We already could not upgrade to 2.0 due to another issue (MOCKBOX-6), so on 1.3 we stay for the time being.

Both of these issues have been ColdFusion problems that Mockbox has been victim of though. Which sucks a bit for Luis & co.

G'day:
As I said in my previous article, it's a bit of a slow day in the office today, so I'm just sitting here hitting ColdFusion interfaces with a sledgehammer to see what happens. I was trying to be clever, and have failed miserably. Oh well.

When I was fiddling around trying to work out "WTF" in that previous article, I ended up with this code.

I have no factored-out Mockbox as a factor in this issue. The tangentially-related issues in Mockbox still stand, but I wanted to have a repro case that did not have any third party code in it. And now I have one.

Thursday, 11 July 2013

G'day:
A coupla days back I wrote a vague article "Weird issue with Mockbox and interfaces", which detailed some weirdness I was seeing with using Mockbox to mock methods in CFCs which implement an interface. The short version is that on the first use of a method mocked this way, I was getting this error:

However if one just re-ran the test, the problem went away. In fact it was only the first usage of the mocked method after ColdFusion was started that caused the problem. Subsequent runs: all good. Restart CF: problem. This is on ColdFusion 9 & 10, but not Railo.

Monday, 8 July 2013

G'day:
This should possibly have happened a while back, but I suspect no-one's mentioned it until recently, so nothing was done about it.

When one submits a UDF to CFLib, one needs to specify which ColdFusion version it is for. It was possibly a bit of an oversight that until now "ColdFusion 10" was not on the selection list. It is now, and CFLib has had it's first submission (and approval) of a ColdFusion-10-specific UDF, from James Moberg: isImageCMYK().

There's a bunch of interesting stuff ColdFusion 10 can do with function-expressions, callbacks and closures, so perhaps you have a treasure trove of ColdFusion 10 stuff sitting on your hard drive that the community could benefit from? If so, please consider submitting it to CFLib. Cheers.

I'll have a poke around and see if I do. Although I've not done anything "production ready" on ColdFusion 10 yet.

Saturday, 6 July 2013

God knows what this article will read like. I headed to the pub to catch the last quarter of the Aussie v Lions match, and I've been sitting here since. I'm over in Portumna visiting my son, and other than my 4h appointment doing that, I've kinda got nothing better to do here, so I'm still in the pub (which has wireless), amusing myself and drinking Guinness. Am just finishing my third pint. And will order a fourth. It's 3pm ;-)

This is a fairly vanilla Application.cfc. The onApplicationStart() stuff is just to work around some lazy programming on the part of Adobe, in that when one changes a REST-aware CFC, it will error until one restarts the REST engine. The onError() is just there in case REST calls call thisonError() instead of the one in the directory the REST CFCs are in (I came into this not knowing how this stuff was handled at all, so just making sure).

The first method is just me testing that stuff was actually working properly with a vanilla method. The second method is one that forces an error, specifically so I can see what happens when an exception occurs.

And I have this Application.cfc in this directory as well, to log everything which goes on during REST requests:

The only non-obvious method in this is the onCfcRequest() one. The code here is reflective of the unexpected "security issue" onCfcRequest() could effect in an application that I blogged about a while ago. Any onCfcRequest() method should do this lot as a minimum. That consideration aside, basically every event handler call is logged. That's the crux of things.

Friday, 5 July 2013

G'day:
I'm half-way across the Irish Sea at the moment (oh, now that I look out the window, I've actually just making landfall over Ireland), and sitting in a very cramped seat trying to write code on my netbook without elbowing the bloke next to me too much. So this will be short and to the point. And hopefully the last chapter in all this JSON nonsense.

Basically we use a caching system which has a method "contains" which checks to see if there's an item with a given key already in the cache, before trying to fetch it. We've actually since revised this approach, but we have some legacy code still using methods called "contains". So we need to unit test them, and indeed their responses play a part in other methods we test. When testing these other methods which use the caching system, we mock-out the cache, and the methods within it, and we use Mockbox to do this. Mockbox is cool, btw. You should be using it if yer not already.

We're still using Mockbox 1.3 (more about why further down), and it is impossible to directly mock a method called contains using Mockbox. We've worked around this, but it took a bloody long time to work out what the hell was going on, and that there was working-around to do.

G'day:
What a busy CFML day today (ed: it's now the following day... I didn't get this finished last night) has been. And it seems it just keeps on giving. Here's a quirky one that has bitten me on the butt before, and has now bitten the butt of someone on Stack Overflow too.

However I'm pretty impressed with their turn-around time on this one. Henry raised the issue on June 27, and it's only a week later and they're got a patch in the works (I presume it's well under way, not that they were simply starting it when Rakshith announced it).

I look forward to testing it, and I will feedback with my findings having done so.

Tuesday, 2 July 2013

G'day:
Ever have one of those days in which you spend most of your time fighting with ColdFusion, rather than getting your work done? Well if so, you're familiar with the last week of my life. And it continues...

G'day:
Whilst playing with objectSave() and objectLoad() yesterday, I came across yet another bug in ColdFusion. It really does seem sometimes that if one attempts to do anything other than the "obvious" in CF, there are bugs. Or illogical quirks. Or omissions in the implementation.

What were were trying to do is to reliably serialise a query, and have ColdFusion not mess up either the null values, nor the dates (actually the latter is a side-effect of the JSON processing, and more an issue with query of query).

I was trying to use JSON because it was faster and lighter than WDDX, and it's kinda become the de facto way of doing quick serialisation, I think.

G'day:
(Warning: this is just a frustrated grumble, and has little merit beyond allowing me to stomp my foot like a petulant school child).

As mentioned in my previous article, "I've raised four bugs, but unfortunately I cannot share the details with you because I raised them as "security issue", so I don't get given the bug number."... all I get is a note "Thank you for submitting a bug. Due to security concerns, this bug will not be externally viewable."

This plumbs new depths of "Adobe really just don't think shit through".

Search This Blog

About

I've been a web developer since 2001. I have spent 13yrs as a CFML developer, and until Sept 2014, that was the main subject matter here. I've now been re-tasked as a PHP developer, so learning PHP will become the focus of this blog. But I also mess around with other languages too.

I tend to be a bit "forthright" in my opinions, I am indelicate, and I tend to swear too much. This will come out occasionally here: I make no apology for it.

Everything said here is my own opinion. Feel free to disagree with me :-)