The Blog Is Dead. Long Live The Blog.

I've become increasingly frustrated with blogging software. I use MangoBlog here. I used BlogCFC before that. I used WordPress before that (a long time ago - but I've worked with it for a few friends more recently). I just don't enjoy using any of it. Back in January, I toyed with the idea of using my Google+ account for blogging but that hasn't really worked out - because I don't much like Google+, even with all its improvements since I last tried using it. So I'm starting a new blog that doesn't need software to publish anything!

I'll keep this site running since there's a lot of legacy material here that is heavily linked but I won't be posting here any more. I'll probably add redirects to the new blog (with a link back here for Google-friendliness). The new blog probably won't have any CFML stuff on it since, well, I don't really do that any more. I'm still committed to maintaining and enhancing FW/1 - Framework One so don't worry about that but my blog is not really the best place for announcements about that: I'll continue to post to the mailing list and Twitter, and I'll probably set up a I have also set up framework-one.github.io as a blog and documentation site now that I've seen how seancorfield.github.io is going to work.

Where did they go? A look at (former) CFML bloggers

Update June 9th, 2014: Ray Camden used my list of "dead" CFML blogs to prune the feed on coldfusionbloggers.org down to just 146 active blogs. I'm going to leave the old list (of 680 blogs) up for a while then I'll update it and rewrite this blog post to reflect the changes. This will give folks on the "dead" list a chance to look at their blog and decide whether to add it back or not.

Back in March 2013, Adam Cameron posted a list of CFML blogs that he follows, asking the community to comment with additional blogs they followed. The comment thread kinda went off in a different direction but it is an interesting discussion nonetheless that would be grist for several blog posts on other topics. A month later, he posted about a new CFML blog and it made me wonder what had happened to a lot of the "old guard" of CFML bloggers. I thought it might make an interesting blog post to take a look at the blogs of a number of formerly very active members of the CFML community and see what they are up to these days.

I started doing the process manually, based on the list of feeds on coldfusionbloggers.org and after a while I just ran out of steam so I put the project aside. Back in January 2014, a conversation with Mark Mandel on IRC spurred me to at least put that ages-old draft into Mango Blog so that I'd see it every time I logged in, thinking it might spur me to go through some more blogs and categorize them. For a while it did, but it was a tedious process, visiting each blog (if it still existed), and figuring out whether they mostly blogged about CFML or something else these days and writing up some notes. There are nearly 700 blogs listed on coldfusionbloggers.org and about half of them had ceased to exist in their original form (some were still blogs, some were even still about CFML, but the old RSS feed had gone away so they weren't contributing to the aggregator). I got tired again.

Then this week I decided to write a little code to automate the review process. Due to vagaries in the format of various RSS and Atom feeds, it took me a while to get a viable "parser" working that could segregate blogs into missing, present but no longer parsable, and valid feeds. In deciding to automate the process, I'd decided to give up on the manual review and annotation: I figured that whatever I write will become outdated and having a blog post full of links to outdated material wouldn't be much value. So instead I created a separate HTML page, auto-generated by code, listing the most recent blog post I could determine on every (former) CFML blog that still exists. Of the 250 or so that weren't directly parsable, some have genuinely gone away, replaced by an HTML placeholder for the domain, some have updated their sites and still have an RSS feed but never updated coldfusionbloggers.org (if you're on that list, head over and let Ray Camden know your updated RSS feed!). And then there's nearly 90 that my code couldn't get a response from. I decided to leave links present to all 680 entries so folks can take a look for themselves, and add comments here about changes (but see my note about letting Ray know about updated RSS URLs!). Note that some of the RSS feeds that were unreachable belong to blogs that clearly do still exist! (e.g., Open BlueDragon's blog still exists, but the RSS feed on coldfusionbloggers.org is for openbd.blog-city.com which is offline).

I can run the code and update that page whenever there are significant changes.

Getting Started

I've been involved with World Singles for about five years now, about three and a half years as a full-time engineer. The project was a green field rewrite of a dating system the company had evolved over about a decade that, back in 2009, was running on ColdFusion 8 on Windows, and using SQL Server. The new platform soft-launched in late 2011 as we migrated a few small sites across and our full launch - migrating millions of members in the process - was May 2012. At that point we switched from "build" mode to "operations" mode, and today we maintain a large codebase that is a combination of CFML and Clojure, running on Railo 4.2 on Linux, and using MySQL and MongoDB, running partly in our East Coast data center and partly on Amazon.

Like all projects, it's had some ups and downs, but overall it's been great: I love my team, we love working with Clojure, and we have a steady stream of interesting problems to solve, working with a large user base, on a multi-tenant, multi-lingual platform that generates millions of records of data every day. It's a lot of fun. And we all get to work from home.

Sometimes it's very enlightening to look back at the beginning of a project to see how things got set up and how we started down the path that led to where we are today. In this post, I'm going to talk about the first ten tickets we created as we kicked the project off. Eleven if you include ticket "zero".

#0 - Choose a bug tracking / ticketing system. We chose Unfuddle. It's clean and simple. It's easy to use. It provides Git (and SVN) hosting. It provides notebooks (wikis), ticketing, time management, customizable "agile" task boards, collaboration with external users, and it's pleasing to the eye. I've never regreted our choice of Unfuddle (even when they did a massive overhaul of the UI and it took us a week or so to get used to the radically new ticket editing workflow!). #1 - Version control. Yes, really, this was our first ticket in Unfuddle. The resolution to this ticket says: Selected vcs system (git), created repository in Unfuddle, and provided detailed documentation on why git, how to set it up, how to connect to the repo and how to work with git. And the documentation was all there in an Unfuddle notebook for the whole team. A good first step. #2 - Developer image. Once we had version control setup and documented, we needed an easy way for every developer to have a full, self-contained local development environment. We had some developers on Windows, some on OS X, some on Linux, so we created a VMWare image with all the basic development tools, a database, a standardized ColdFusion installation, with Apache properly configured etc. This established a basic working practice for everyone on the team: develop and test everything locally, commit to Git, push to Unfuddle. We could then pull the latest code down to a showcase / QA server for the business team to review, whenever we or they wanted. #3 - Project management system. Although we had bug tracking and wikis, we wanted to nail down how communication would work in practice. We created a project management mailing list for discussion threads. We created a notebook section in Unfuddle for documenting decisions and requirements. We decided to use Basecamp for more free-form evolution of business ideas. We agreed to use tickets in Unfuddle for all actionable work, and we settled on a Scrum-like process for day-to-day development, with short, regular sprints so we could get fast feedback from the business team, and they could easily see what progress we were making. #4 - General project management. Since we had agreed to use Unfuddle for time tracking, we created a ticket against which to track project management hours that didn't fit into any actual work tickets. We used this for the first six months of the project (and logged about 300 hours against it). #5 - Performance planning/tuning. This was mostly a placeholder (and initially focused on how to make a Reactor-based application perform better!). It was superceded by several more specific tickets, six months into the project. But it's one of those things we wanted on the radar early for tracking purposes. #6 - Architectural planning. Like ticket #4, this was a time tracking bucket that we used for the first six months of the project. #7 - Set up Continuous Integration. Yup, even before we got to our first actual coding ticket, as part of the early project setup, we wanted a Continuous Integration server. Whilst we were using ColdFusion for local development (prerelease builds of ACF9, at the time), we chose to use Railo 3.2 for the CI server so that we could ensure our code was cross-platform - we were still evaluating which engine to ultimately go to production with. The resolution of this ticket says: Apache / Tomcat / Railo / MySQL / Transparensee / Hudson in place. Automated test run restarts Railo, reloads the DB, reloads Transparensee, cleans the Reactor project, runs all test suites and generates test results. We developed an Ant script that stopped and started Railo, tore down and rebuilt the test database, using a canned dataset we created (with 1,000 random users), repopulated the search engine we use and cleaned up generated files, then ran our fledgling MXUnit test suite (and later our fledgling Selenium test suite). #8 - Display About us/trust. This was our first actual code ticket. The company had selected ColdBox, ColdSpring, and Reactor as our basic frameworks (yeah, no ticket for that, it was a choice that essentially predated the project "getting started"). This ticket was to produce a first working skeleton of the application that could actually display dynamically generated pages of content from the database. We created the skeleton of the site navigation and handlers for each section as part of this ticket. The "trust" in the ticket title was about showing that we really could produce basic multilingual content dynamically and show an application architecture that worked for the business. #9 - Implement resource bundles for templates. And this was also an early key requirement: so that we could support Internationalization from day one and perform Localization of each site's content easily. #10 - Display appropriate template for each site. This was our other key requirement: the ability to easily skin each site differently. Like #9, this was an important proof of concept to show we could support multiple sites, in multiple languages, on a single codebase, with easy customization of page layouts, content, and even forms / questions we asked.

So that's how we got started. Bug tracking, version control, local development environment, continuous integration and the key concepts tackled first!

A reasonable question is to ask what has changed in our approach over the five years since. We're still using Unfuddle (in case you're wondering, we're up to ticket 6537 as I write this!), we're still using Git (and still loving it). Our development stack has changed, as has some of our technology.

Over time we all migrated to Macs for development so maintaining the VM image stopped being important: everyone could have the entire development stack locally. We eventually settled on Railo instead of ColdFusion (we're on Railo 4.2 now), and we added MongoDB to MySQL a couple of years ago. We added some Scala code in 2010 to tackle a problematic long-running process (that did a lot of XML transformation and publishing). We added Clojure code in 2011 for a few key processes and then replaced Scala with Clojure and today Clojure is our primary language for all new development, often running inside Railo. We stopped using Reactor (we wrote a data mapper in Clojure that is very close to the "metal" of JDBC). Recently we stopped using MXUnit and replaced it with TestBox. We're slowing changing over from Selenium RC tests to WebDriver (powered by Clojure). We have about 20,000 lines of Clojure now and our CFML code base is holding steady at around 39,000 lines of Model and Controller CFCs and 45,000 lines of View cfm files.

BlogCFC is a TeamCFAdvance project

I don't think I've actually blogged about TeamCFAdvance yet. That's very lax of me. TeamCFAdvance is an initiative started by Denard Springle last year to help foster the development of Free Open Source Software (FOSS) in the CFML community. Yes, there's been several attempts at this in the past. I've been involved with a few of them myself. The Open CFML Foundation is one example, focused on promoting awareness of open source solutions that are written in CFML - reaching out beyond our community. But TeamCFAdvance is very pragmatic: it's aimed directly at our developers, to educate and encourage, to ensure that great projects continue to be maintained, even when their maintainers move on.

If you look at the TeamCFAdvance Github repo you'll see a bunch of projects and there is one you will definitely recognize: BlogCFC! Originally created by Ray Camden, and later stewarded by Scott Stroz, BlogCFC is now a TeamCFAdvance project. One of the things you'll note on that page is the (hopefully!) green "build: passing" icon as we now have BlogCFC hooked into Travis-CI - a Continuous Integration system that automatically runs your test suite after every change, testing the project against Railo (4.0, 4.1, 4.2 beta - soon to be "gold") and Adobe ColdFusion (9.0.2 and 10 on Linux - soon to add 11), using TestBox. There's only a placeholder there right now but expect tests to blossom soon...

To see what's possible once we have everything wired up, take a look at what happens with FW/1's Travis-CI setup with automated tests - 115 of them - that are run on five platform combinations. Almost 120 builds have been tested. FW/1, DI/1, and AOP/1 are all automatically tested.

If you're not already involved with TeamCFAdvance but you're interested in FOSS, sign up! Everyone is welcome!

FW/1 2.5 is released!

This is a migration release to pave the way for breaking changes in Release 3.0. All examples have been updated to latest best practices and now use cfcscript exclusively. Examples use DI/1 0.5.0 to manage all beans and services (as framework.ioc), and no longer rely on start/end actions or the service() method.

As always, FW/1 can be downloaded from the FW/1 page on RIAForge. Release 2.5 is now the latest stable release of this framework, as it approaches its fifth birthday!

For a full list of all tickets closed in Release 2.5: https://github.com/framework-one/fw1/issues?milestone=14&page=1&state=closed

Migration from 2.2.1

The service() call has been deprecated, as have start/end action items. Global access to rc in Application.cfc has also been deprecated. If you just drop 2.5 into your setup and you rely on these features, you'll get exceptions explaining how to enable these features for backward compatibility, namely add the following to your framework configuration:

enableGlobalRC = true,
suppressServiceQueue = false

The ability to enable the implicit service calls is still present via:

suppressImplicitService = false

but, like the other two options, defaults to disallowing the deprecated feature.

If you enable these deprecated features, you will no longer get exceptions using them, but you will see deprecation warnings in your application server's console log. This is to remind you to update your code in preparation for 3.0 later this year!

Please note that Release 3.0 will completely remove these backward compatibility options - and the associated deprecated features. In addition, org.corfield.framework will move to framework.one in Release 3.0, alongside framework.ioc.

Conferences & Me

cf.Objective() is over for another year and the reactions I've seen were all very positive. As a long-time member of the Steering Committee, that makes me very happy. This is the first time I've ever missed cf.Objective(). Yes, I've attended eight of the nine, and I've been a speaker at six of them (I think?). I've also attended as a sponsor (2012, as Railo's "booth babe").

This year also saw Into The Box the day before - a one day conference dedicated to all things *Box, not just ColdBox. That conference also seemed to go well, from what I saw on Twitter, and I'm very interested to learn more about CommandBox, the CLI and package manager they previewed!

Eagle-eyed readers may have noticed posts from me back in November and December indicating that I'd submitted talks to cf.Objective() and Scotch on the Rocks, which had been accepted... and then those posts disappeared. I took the posts down to reduce linkage to them and, to some extent, to head off any questions. I try really hard not to back out of commitments: I had to cancel Scotch on the Rocks back in 2009 because my wife broke her ankle just before the conference and she was laid up in bed for a couple of months and then in a wheelchair for another couple of months.

Over the last few years, I've attended a lot of conferences and most of them have been out of my own pocket and out of my vacation allowance. Over the last few years, my technology focus has shifted. When I joined World Singles full-time in 2010, I came in primarily as a CFML developer, with experience in a number of other languages. At BroadChoice we'd gone to production with Groovy and Flex alongside CFML. At World Singles, we went to production with Scala alongside CFML and then we introduced Clojure. Now we're primarily a Clojure shop: it's our go-to language for all new work and we're slowly replacing CFML code with Clojure code as we touch that CFML code to make enhancements. The benefits of immutable data, pure functions, and composable data transformations - and the ease with which we can operate concurrently - are huge.

That shift has meant that CFML conferences, once core to my work, are now a personal luxury. The once bleeding edge, new technology events that I could justify as an investment in my personal growth have instead become core to my work: MongoDB Days, Clojure/West, The Strange Loop, Lambda Jam, Clojure/conj. Even with an employer as generous as World Singles, I can't get to all of those on the company dime and company time.

I've been very lucky to be able to attend and speak at so many conferences over the last decade, and I've loved attending all those CFML conferences: MXDU, Fusebox, Frameworks, CFUnited, CFinNC, cf.Objective(), Scotch on the Rocks. I have a huge number of friends in the CFML community and that's a big part of what I love about the conferences. The desire to see my friends is a large part of why I've continued to submit talks to CFML conferences.

Unfortunately, as Jay & I reviewed our commitments back in January, both financial and timewise, as we started to prepare our 2013 tax return, it became clear that there was no way I was going to be able to attend Into The Box, cf.Objective(), and Scotch on the Rocks. It led to some very uncomfortable discussions with those conference organizers. I'd already overreached in 2013 and, realistically, I shouldn't have even submitted talks.

In the end, of course, Into The Box and cf.Objective() were both great successes - they are so much more than the sum of their speakers - and Scotch on the Rocks looks absolutely amazing. I wish I could attend! I miss my friends in the CFML community and without the conferences I don't get to hang out with them.

I'm sorry that I caused the conference organizers hassle by submitting talks and then pulling out. As a long-time member of the cf.Objective() Steering Committee I know that flaky speakers are a pain in the ass!

Realistically, all this means that unless you attend The Strange Loop (or a Clojure conference), I'm probably not going to get to hang out with you in the future. That makes me sad for the friends I won't get to see but I hope we all grow...

FW/1 2.5 Release Candidate 2

Later than planned, FW/1 2.5 RC2 is finally available for testing! You can download FW/1 2.5 RC2 from Github and it is also the default download from FW/1's page on RIAForge.

You can read the complete list of closed tickets for Release 2.5 for more details on features added (or removed) in this release.

Changes since RC1: trace now has delta column showing time taken (thank Ryan Guill); environment control is now able to affect many more basic configuration items, including tracing; ColdFusion 11 / Railo 4.2 compatibility (string member function workaround); bean factories are fully cleared on a reload (Brian Fitzgerald); all examples updated to remove deprecated features.

DI/1 0.5.0 is included (as framework.ioc), along with the WireBoxAdapter.cfc (also in the framework/ folder), and all the examples that used any sort of bean factory have been updated to use DI/1 instead.

All the examples have been updated to use script-only CFCs, with the exception of userManagerAccessControl which I just couldn't summon up the energy to tackle this morning. It will get converted before 2.5 goes "Gold" since it will dramatically simplify the code (especially the beans!).

Migration from 2.2.1

The service() call has been deprecated, as have start/end action items. Global access to rc in Application.cfc has also been deprecated. If you just drop 2.5 into your setup and you rely on these features, you'll get exceptions explaining how to enable these features for backward compatibility, namely add the following to your framework configuration: enableGlobalRC = true, suppressServiceQueue = false

The ability to enable the implicit service calls is still present via:

suppressImplicitService = false

but, like the other two options, defaults to disallowing the deprecated feature.

If you enable these deprecated features, you will no longer get exceptions using them, but you will see deprecation warnings in your application server's console log. This is to remind you to update your code in preparation for 3.0 later this year!

Please note that Release 3.0 will completely remove these backward compatibility options - and the associated deprecated features. In addition, org.corfield.framework will move to framework.one in Release 3.0, alongside framework.ioc.

Packt Publishing Buy One, Get One Free Offer Ends March 26th!

Those wonderful folks over at Packt Publishing are celebrating their 2000th title release and they are offering all their customers a "Buy One, Get One Free" offer on all e-books right now. The offer runs until March 26th and will be applied automatically at check out - and it is unlimited! Great time to stock up on their titles!

Check out Packt Publishing's Buy One, Get One Free e-book offer!

Insanely Useful Leiningen Plugins

A very short post, partly as a reminder for my future self. Check out the following Leiningen plugins:

lein-ancient - analyzes your project.clj and lets you know which dependencies are out of date. lein-exec - directly execute Clojure code snippets, or write shell scripts in Clojure! lein-try - start a REPL with various dependencies without needing a project. Great for exploring new libraries! Eastwood - a lint tool for Clojure.