Tuesday 30 July 2013

Installing Coldspring 1.2

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).

Whilst on the train this morning, I read this Twitter update from Rob:

Amazing. NOWHERE can I find INSTALLATION INSTRUCTIONS for #coldspring. Just lots on how it works. #coldfusion
That is quite amazing, but not in the way Rob means. Because a quick google of "coldspring install" returns a bunch of results, and just browsing through the first few:

  1. ColdSpring - Home
    Well... yeah, OK: this is a fail. I've done superficial clicking around, and didn't see any installation instructions within the first ten clicks of hitting the home page.
  2. [PDF] Reference Guide - ColdSpring
    The third item is the installation instructions.
  3. How to install the ColdSpring framework - Hosting Forum - Hostek ...
    The raison d'être of the document is that its instructions of how to install Coldspring.
  4. Mach II and Coldspring for n00bs | Ollie Jones, software hints and tips
    Includes instructions for installing Coldspring
  5. ColdSpring - Railo
    Is not actually about installing Coldspring.
  6. A Beginner's Guide to the ColdSpring Framework for ColdFusion ...
    Unfortunately - given the title - doesn't actually include how to install it.
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.

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.
  1. Download Coldspring from the Coldspring website. At time of writing, the current stable version proclaims to be 1.2, and there's an alpha of 2.0 available too. There's a download link for 1.2 (zip) on the homepage.
  2. 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:

    /[parent directory]/
        /[coldspring directory]/ (can be called anything, but "coldspring" makes sense)
    There will be a lot of other files in there, but that gives you an idea of what the directory structure is like.
  3. 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]/
  4. 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.

// Application.cfc
component {

    this.name = "coldspringTest12";
    this.mappings = {
        "/coldspring" = expandPath("../coldspring"),
        "/api" = expandPath("../api")

    public void function onApplicationStart(){
        var timestamp = now();

        writeOutput("application initialised @ #timeFormat(timestamp, "HH:MM:SS.LLL")#<br>");

        application.beanFactory = createObject("coldspring.beans.DefaultXmlBeanFactory").init(defaultProperties = {timestamp=timestamp});
        application.beanFactory.loadBeansFromXmlFile("../conf/beans.xml", true);


Here we have our /coldpsring mapping, and the bootstrap code to get Coldspring loaded, and my beans loaded too.

I'm passing a bean config parameter too.

Here's my bean definition XML file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    <bean id="C" class="api.C">
        <constructor-arg name="timestamp">

Note that the /config directory is also not in the web root. It's adjacent to the /coldspring and /webroot and (see below) /api directories.

And I obviously have this C.cfc file too:

// C.cfc
component {

    public C function init(required date timestamp){
        this.timestamp = arguments.timestamp;

        writeOutput("C initialised @ #timeFormat(timestamp, "HH:MM:SS.LLL")#<br>");

        return this;


Finally, I have a file which uses Coldspring to fetch my bean:

// test.cfm
writeOutput("test.cfm initialised @ #timeFormat(now(), "HH:MM:SS.LLL")#<br>");
o1 = application.beanFactory.getBean("C");
writeOutput("o1.timestamp = #timeFormat(o1.timestamp, "HH:MM:SS.LLL")#<br>");

writeOutput("current time #timeFormat(now(), "HH:MM:SS.LLL")#<br>");
o2 = application.beanFactory.getBean("C");
writeOutput("o2.timestamp = #timeFormat(o2.timestamp, "HH:MM:SS.LLL")#<br>");

And the output from this is as follows:

application initialised @ 08:38:21.029
test.cfm initialised @ 08:38:21.053
o1.timestamp = 08:38:21.029
current time 08:38:26.066
o2.timestamp = 08:38:21.029

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.