Slides from My cf.Objective Session on Highly Available CF Apps

The organizers of this year's cf.Objective() had the brilliant idea of setting up a shared Dropbox folder for the slides, code, and supporting materials from all sessions at the conference. I've posted a PDF of my slides from my session, "Making Your ColdFusion Apps Highly Available," to this Dropbox folder. The PDF includes links to a lot of the tools, services, and articles that I referenced in my talk.

Thanks again to everyone who attended, and for the excellent questions and feedback I've received after the session.

Based on some of the questions I've received, I think I'm going to put in a conference proposal next year to talk about Amazon S3 and CloudFront, and how amazingly simple they are to use in ColdFusion!

My cf.Objective() 2013 Schedule

As a number of other folks in the CF community have been posting their cf.Objective() 2013 schedule, I thought I'd do the same — and promote my session in the process.

Thursday, May 16

10:10am: Learn You a What for a Great Good? Polyglot Lessons to Improve Your CFML!

Sean is an excellent speaker, and all-around smart guy. I know I need to learn more languages (my attempt at picking up Groovy went OK, and my attempts at learning Ruby stopped at Rails 101), so it feels like a good opportunity for motivation.

11:20am: The Art of JavaScript: Level Up Your Skills in 60 Minutes

I can always write better JavaScript. Always!

2:35pm: Nothing.

Why is that? Because I'll be preparing for my two hour deep-dive session which begins at 3:45pm.

3:45pm: Making Your ColdFusion Apps Highly Available

This is my session, and one I'm both excited and terrified to present. The topic is so deep and the complexities so great (especially when talking about building for the cloud) that, in the two hours allotted, I'm hoping to give a solid foundation for building a highly available CF application in a cluster and giving an overview of options for the rest. There won't be a lot of code, but there will be a lot of architecture!

Friday, May 17

9am: Building a Single Page App with AngularJS, Bootstrap, and CFML

I want to learn more about AngularJS. I love Bootstrap (it saves you so. Much. Time.) I prefer to use CFML on the backend in most cases, and Kurt is another super-smart guy and a personal friend.

11:20am: Nginx and CFML Apps

I've only ever used Apache and IIS as a front-end to my CFML apps. Nginx gets a ton of play in the Node.js world, and as I develop more there, expanding my knowledge about the server is a good thing.

2:35pm: Who let a bum into the kitchen? Using Vagrant and Chef to create development environments

Chef is becoming an almost required tool in cloud environments, particularly AWS. (Want to know why? Come to the second half of my deep dive on Thursday!) I'd love to see how to leverage it on the desktop and for testing.

3:45pm: Humongous MongoDB

MongoDB is probably the leading persistence engine for Node.js apps, and, thanks to Marc Escher, is easily accessible through CF. I look forward to hearing Sean's experience about deploying and running MongoDB in real production environments.

Saturday, May 18

9am: Grow a Backbone.js and drag your apps out of the past with JavaScript Templating

More JS, though I may head on over to Luis Majano's session on AOP, as I find ColdBox to be pretty impressive.

10:10am: It's either going to be "IIS 8 Troubleshooting Features for CF Admins" or "Railo 4.0 - Developing with Railo." We use IIS for deployment at my place of work, but haven't made the upgrade to IIS 8 yet, and Railo is a superior option for autoscaling deployments on AWS. (Want to know why? Come to the second half of my deep dive on Thursday!)

11:20am: Architecting ColdFusion Applications with AWS

In case you haven't noticed, this is a topic near and dear to my heart. Aaron has been working long and hard to deal with some of the issues with deploying CF10 on AWS.

1:45pm: REST APIs: Easier Than You Imagined

We need to build more REST-based APIs for our projects at work, and I've not been pleased with the REST implementation in CF10 (particularly with the administrative burdens it creates). I know Adam has a lot of experience in the area, and we're definitely considering a framework like Taffy or Relaxation for our work.

3pm: Metrics Driven Development

I'm bad on metrics and measurement. Well, not terrible bad, but not particularly good. I hope this session is the good, swift kick that I need.

I'm really looking forward to this year's conference. The content is always excellent, and I'm very proud that I've been asked to speak for a second year!

Utility for Creating Signed URLs for Amazon CloudFront Up on GitHub

I've taken the code I wrote for my previous two posts on creating signed URLs for protected content in Amazon CloudFront in ColdFusion and dynamically changing the file names of the files you serve from CloudFront and put it all in a little CFC which you may find useful if you're doing either of these two tasks.

In order for you to be able to do anything with this CFC, you're going to need an AWS account that uses CloudFront and have everything set up so you can serve protected content. You're also going to need a copy of the AWS SDK .jar file in your ColdFusion /lib directory. The two blog posts go into extensive detail about what needs to be done and the little gotchas you need to watch out for along the way.

CTL CloudFront Utility CFC on GitHub

Dynamic File Names Using Amazon CloudFront and ColdFusion

There are a lot of use cases which require you to store customer-uploaded files with a system-generated file name instead of the original file name that the file had when the customer uploaded the file. You may want to ensure that every customer-uploaded file has a unique file name. You may want to provide a random file name so that someone poking through a server directory or Amazon S3 bucket doesn't see file names like "income_taxes_jill_smith.pdf" You may have a specific file-naming convention that's used for storing files in multiple hierarchies in your application. Whatever the reason, you also often need to change the name of the file when it's requested by the customer after the initial upload. Jill Smith will want her file with the original name, and not "ks8pqz0hs7.pdf"

This is simple enough to achieve by using the content-disposition HTTP response header. You can set this really easily in ColdFusion:

<cfheader name="Content-Disposition" value="filename=someFileName.pdf">

We recently started a major project wherein we will be delivering tons of lecture content in MP4/WebM format through Amazon CloudFront. This will help speed delivery of the video content to our truly global audience and reduce bandwidth consumption on our network. However, one of the major hurdles we ran into when setting up our CloudFront distribution was figuring out how to dynamically rename files when our learners requested them. We store the video files with very generic names in our S3 buckets (or, previously, on our server file systems). This lets us avoid having to rename the video files every time the course instructors rename their lectures, or change lecture numbers, or reorder content in their course or even within a specific lecture. Having to manually update thousands of files every quarter is a tedious, time-consuming, and error-prone process. We have all the metadata about a lecture stored in a database, so we can use that to dynamically rename the video files when they are requested.

Out of the box, CloudFront doesn't allow you to pass along response headers like content-disposition. If you try to append HTTP headers to your URL string that points at CloudFront, they'll simply be ignored. Amazon requires that you pass along specifically-named query parameters as the HTTP headers you want sent back from CloudFront/S3. The supported HTTP headers you can use are listed in the documentation for GET requests to S3. (Remember, we're using S3 as our origin for all CloudFront requests. If you are hosting your own origin server, you have to handle query strings with HTTP parameters on your own.) All supported HTTP headers that can be sent back in the response are prefixed with response-

However, you'll get a S3 access error message if you try to simply append ?response-content-disposition=attachment;filename=somefile.pdf to a CloudFront URL. (This assumes you are using S3 as your origin server. If you're using a custom origin, it's up to you to determine how you handle query strings and response headers.) As the docs say, you must sign the request, either using an Authorization header or a pre-signed URL, when using these parameters. They can not be used with an unsigned (anonymous) request. So what does this mean? What do you need to do in order to pass along response headers to a CloudFront request?

In order to dynamically name files on a per-request basis in CloudFront, you have to do the following:

  • Sign your CloudFront request URLs using a valid CloudFront key pair
  • Set up your CloudFront distribution with an origin access identity

If you don't have URL signing for CloudFront requests working, please see my post on creating signed CloudFront URLs with ColdFusion. You must have everything working with basic/"canned" signed URLs before moving forward.

You also need to add an "Origin Access Identity" to the CloudFront distribution so that S3 sees a named user making a request when CloudFront passes the request to S3. Only named, authorized users can pass query strings which include response-disposition headers to S3. More information on Origin Access Identities can be found in Amazon's CloudFront documentation.

To add an origin access identity to an existing CloudFront distribution in the CloudFront Management Console, do the following:

  • Next to the distribution where you need to add an origin access identity, click the [i] button
  • Click the "Origins" tab
  • Click the checkbox next to your S3 origin bucket, and select "Edit"
  • For "Restrict Bucket Access" select "Yes"
  • For the "Origin Access Identity", select "Create a New Identity" if you have none. Otherwise, use an existing origin access identity.
  • For "Grant Read Permissions on Bucket," you have to decide the following:
    • If you want people — including developers on your own team — to be able to directly access your objects in S3 for any reason, you cannot let CloudFront update the bucket policy. You must also have correct permissions set up in your S3 bucket to allow anyone to read your objects in that bucket.
    • If you don't want people to be able to directly access your objects in S3 and only want them to go through CloudFront, then you want CloudFront to update the bucket policy.
  • Save your changes.

As with all CloudFront distribution updates, it takes about 10 minutes for your distribution to be properly updated.

Now you can add response- HTTP headers to the URLs that you pass into your CloudFront URL signing method. If you use the code from my post on creating signed CloudFront URLs with ColdFusion, here's what you would need to add:

<cfset cloudFrontObjURL = "https://" & distributionDomain & "/" & s3ObjectKey & "?response-content-disposition=attachment%3Bfilename%3DsomeReadableFileName.pdf" />

Amazon AWS is very, very picky about proper URL encoding, so make sure you have properly escaped non-alphanumeric characters in your response-content-disposition header (or any custom header you may use as allowed in the Amazon S3 docs). Note, though, that the = sign after response-content-disposition is not escaped, because S3 won't recognize it as a valid response header parameter if it is.

Creating Signed URLs for Amazon CloudFront in ColdFusion

My team is in the process of shifting all of our online course content from being delivered in a Flash-based format to delivery in a video-based format. At the same time, we're trying to figure out ways of improving delivery of this content to our global audience. We've got students all over the world, and in some fairly low-resource areas (where they have Internet access from 3-5pm on Tuesdays and Fridays, for example). One of the strategies we're going to employ is distribution of our online course content via a CDN. Although we've used Akamai as a CDN in the past, we're going with Amazon S3 and CloudFront because of cost and integration benefits.

Some of the content we're going to distribute needs to be protected, however. Although we can claim "fair use" for some copyright-protected content, we have to make sure that only individuals in our online courses have access to this content. We want to take advantage of the global distribution network that Amazon CloudFront provides, but we also need to make sure we limit who can access that content. Enter signed URLs in CloudFront.

As the CloudFront docs explain, signing URLs allows you to specify that the current request really should have permission to access a resource in CloudFront (or, more specifically, a S3 bucket or on some kind of other origin server) even though general requests to that object in CloudFront are blocked. This is how companies like O'Reilly let you download an ebook that you've bought but prevent those that have not bought the book from downloading the book using the same URL.

There are a number of SDKs available from Amazon for CloudFront integration. As you might expect, however, there are no SDKs specifically for ColdFusion. There are some libraries available from the ColdFusion community — Simon Free's AWS Wrapper on GitHub is perhaps the most complete — but none included CloudFront functionality.

One of the great things about ColdFusion is that it's built on top of the JVM. As a result, we can use a huge number of Java-based SDKs in our ColdFusion apps. It's not always obvious what you need to do, but nearly all Java-based SDKs include auto-generated API documentation that make it pretty darn easy to figure out. So that's what we did.

I've split this post into two major parts: Setting up the CloudFront distribution for protected content, and the ColdFusion code. You have to do everything in the first part before proceeding to the code, or the code won't work.

Setting Up the CloudFront Distribution for Protected Content

I'm going to assume you've done the following:

  • Created an AWS account
  • Have at least one accessKey and secretKey created in Amazon IAM (Identity and Access Management)
  • Set up a S3 bucket which will contain the content you want to protect
  • Set up a CloudFront download distribution which points to the S3 bucket with your content

If not, Amazon has a ton of getting started materials to do any of the above tasks.

(I'm also only looking at download distributions here. Streaming CloudFront distributions are slightly different, but the code shown below should still work.)

To generate a signed URL for CloudFront, you're going to need both AWS IAM security credentials (the accessKey and secretKey) and a CloudFront keypair. Generating a signed URL will work with any IAM security credentials on the account for which you create a CloudFront keypair. You should have at least one accessKey and secretKey to work with — if you don't, you should go do that now.

In the CloudFront docs on creating signed URLs, it says that you need to specify one or more trusted signers for your CloudFront distribution. Trusted signers are the AWS accounts that you want to have permission to create signed URLs. Each trusted signer has to have a CloudFront key pair. This is different from an EC2 key pair (if you use Amazon EC2). Amazon explains how the CloudFront key pair works when you sign URLs as follows:

When you create a signed URL, you use the private key from the trusted signer's key pair to sign a portion of the URL. When someone uses the signed URL to access an object, CloudFront compares the signed portion of the URL with the unsigned portion to verify that the URL hasn't been tampered with.

A trusted signer is linked to a cache behavior in the setup of your CloudFront distribution. Again, from Amazon:

Download distributions: You add trusted signers to cache behaviors. If your distribution has only one cache behavior, users must use signed URLs to access any object associated with the distribution. If you create multiple cache behaviors and add trusted signers to some cache behaviors and not to others, you can require that users use signed URLs to access some objects and not others.

So if you want to have a mixed CloudFront distribution where some URLs need to be signed (to set a new timeout expiration on a cached object in CloudFront, for example) but some URLs don't need to be signed, you would need to have multiple cache behaviors. If you want all content in a CloudFront distribution to be protected and require signed URLs, then you only need one cache behavior with a trusted signer.

Also, IAM users are currently not allowed to create CloudFront key pairs, so you cannot use IAM users as trusted signers. IAM users are all the accounts you set up in Amazon AWS that use the accessKey and secretKey to access Amazon AWS. So...the account that's going to create the CloudFront key pair is the account that you use to sign in to AWS. Fun!

To create a CloudFront key pair:

  • Sign into the AWS portal
  • Go to Account -> Security Credentials
  • Click the "Key Pairs" tab
  • Click "Amazon Cloud Front Key Pairs" and then "Create New Key Pair"

This will create a new key pair and automatically downloads the private key to your machine.

It's up to you to secure this file. Don't put it in a web-accessible directory when you deploy your CloudFront-signing code to production. Hide it away somewhere on your network and make it accessible only by a special account on the machine(s) running your code.

Once you create the key pair, you now have to alter your CloudFront distribution to authorize the account for the key pair you just created to sign URLs. To add a trusted signer to your CloudFront distribution, do the following:

  • Sign into the AWS portal
  • Go to the CloudFront console
  • Next to the distribution where you want to have trusted signers, click the [i] button
  • Click on the "Behaviors" tab
  • Click "Create Behavior"
  • Set up the cache behavior as needed, including the path pattern to match for this behavior. The default is to match everything (*)
  • For "Forward Query Strings" select "Yes" if you are using query strings to do object versioning in CloudFront.
  • For "Restrict Viewer Access (Use Signed URLs)" select "Yes"
  • The default trusted signer is "self" - the account which manages your AWS distribution and for which you created the CloudFront key pair. (If you want another account to be able to sign URLs for this CloudFront distribution, you need to look up and use the canonical AWS account number.)
  • Save the changes to the CloudFront distribution.

As with any CloudFront distribution, making changes will take about 5-10 minutes to process.

Whew! Now that the AWS setup is done, we can get to some code.

The ColdFusion Code

First up, you're going to need to get the core AWS SDK for Java. This vastly simplifies the kinds of calls you have to make. The AWS SDK has a ton of files in it, but you only need one: aws-java-sdk-1.3.30.jar

Like any .jar file you want to make available to ColdFusion at server startup, this .jar needs to be added to your cfusion/lib/ directory and you'll need to restart ColdFusion after you add the .jar. Note that I did not use Mark Mandel's excellent JavaLoader project or the built in .jar loading functionality in Adobe ColdFusion 10. I have access to my servers in both development and production, and felt this was the simplest way of handling the issue.

Next, we're going to use the JetSet libraries for dealing with CloudFront. The AWS docs pretty much say "use these" and don't provide any other options for abstracting away CloudFront AWS calls. Fortunately for us, the jets3t-0.8.1.jar that comes bundled with ColdFusion 10 works just fine.

If you are using ColdFusion 9, you can download the latest version of the JetSet library and add it to your cfusion/lib/ directory. However, in our testing, we found that the latest JetS3t library breaks S3 functionality in the <cffile> tag in Adobe ColdFusion 9. Apparently, the method signatures for some functions changed between the jets3t-0.7.3.jar that comes with CF9 and the jets3t-0.8.1.jar that comes with CF10. Signing CloudFront URLs described in this post will work using the jets3t-0.8.1.jar in Adobe ColdFusion 9, but the Amazon S3 integration in the <cffile> tag will break. You will have to use third-party code to interact with Amazon S3 if you go this route. Additionally, you must remove jets3t-0.x.0.jar that comes bundled with Adobe ColdFusion 9 that's already in the cfusion/lib/ directory. If you don't do this, ColdFusion won't be able to find all the methods that are in the jets3t-0.9.0.jar because there are versions of some methods in both .jars and ColdFusion can get confused about which version of which method should be used and gives you a "method cannot be found" error even though the method is in the source Java objects.

Once you've got those two .jars in your cfusion/lib/ directory and you've restarted ColdFusion, let's test to make sure that the AWS and JetSet .jars loaded properly. Create a new file with the following:

<cfset accessKey = "YOUR ACCESS KEY" />
<cfset secretKey = "YOUR SECRET KEY" />

The accessKey and secretKey can be any IAM accessKey/secretKey combination in the AWS account that is your trusted signer for CloudFront URLs.

<cfset awsCredentials = createobject("java", "org.jets3t.service.security.AWSCredentials").init(accessKey, secretKey) />
<cfdump var="#awsCredentials#" />
<cfset cloudFrontService = createobject("java", "org.jets3t.service.CloudFrontService").init(awsCredentials) />
<cfdump var="#cloudFrontService#" />

If this runs successfully, you will see the simple dump of the JetSet AWSCredentials object followed by the various methods available to the JetSet CloudFront service object.

Add to the current file the following:

<cfset distributions = cloudFrontService.listDistributions() />
<cfloop array="#distributions#" index="thisDistrib">
   <cfoutput><p>#thisDistrib.toString()#</p></cfoutput>
</cfloop>

This will return a list of all your current CloudFront distributions. If you didn't set any up, none will be listed!

If you want to play with other methods of the CloudFront service, you can see what's offered in the dump of the CloudFrontService object, or, better yet, view the JavaDocs that come with the JetSet download.

In full disclosure, I have to mention that JetSet provided a long list of code samples that I used as the basis for my code work. Those samples can be found here:

http://jets3t.s3.amazonaws.com/toolkit/code-samples.html#cloudfront-manage

Moving on, you're also going to need an instance of JetS3t's serviceUtils object for date conversions when signing, so add this:

<cfset jets3tServiceUtils = createObject("java", "org.jets3t.service.utils.ServiceUtils").init() />

And, finally, let's not forget the JetS3t EncryptionUtil object for handling the conversion of Amazon's .pem files into the Java-readable .der file format:

<cfset jets3tEncryptionUtils = createObject("java", "org.jets3t.service.security.EncryptionUtil").init("dkhcoaj3fh2sk0oay") />

Note that you have to pass some initial password to the EncryptionUtil object. It's not important what the initial password is as we are not persisting data using this EncryptionUtil object. You just need to pass in something.

We're now at the point where we can create a signed URL! There are two methods in the cloudFrontService object that let us do this: signURL and signURLCanned. signURL lets you sign a URL with a custom policy JSON document stating what the access restrictions on the file in S3 are. signURLCanned lets you sign a URL with a simple statement of when the URL will expire. For this example, we're going to use signURLCanned because we want our customers to only have access to a file in CloudFront for a limited period of time.

If you look at the docs for JetSet's CloudFront service, the method signature for signURLCanned is as follows:

public static java.lang.String signUrlCanned(java.lang.String resourceUrlOrPath, java.lang.String keyPairId, byte[] derPrivateKey, java.util.Date epochDateLessThan) throws CloudFrontServiceException

So we're going to need the following:

  • A string that is the URL of the object we want
  • The keyPair ID of the CloudFront keypair from Amazon that you made earlier
  • The der-encrypted version of your CloudFront private key
  • An ISO8601-formatted date that indicates the date and time when the signed URL will expire

Let's look at each item in order:

resourceUrlOrPath - this will be the full URL of the object you want to access on CloudFront. For example: https://gobb7edyg00k.cloudfront.net/somefile.mov

keyPairID - this is the ID of the CloudFront key pair that you made earlier. If you didn't write this down, you have to log in to the AWS portal, select Account -> Security Credentials and click the "Key Pairs" tab. Your CloudFront key pair ID will be listed there.

derPrivateKey - When AWS creates key pairs, they are created with .pem encoding. However, Java can't natively read .pem encoded key files. Java works with .der encoded key files. So you've got to convert the .pem encoded files to .der encoding so that Java can properly work with them. This is where the jets3tEncryptionUtils object that we created earlier comes in. It has a method called convertRsaPemToDer() that converts .pem encoded files into .der encoding so that we can create a valid CloudFront signature.

The docs for convertRsaPemToDer() state that it takes a Java FileInputStream. This is simple enough to do:

<cfset privateKeyFilePath = "/path/to/you/keyfile/pk-YOURKEYFILENAME.pem" />
<cfset keyFileInputStream = createObject("java", "java.io.FileInputStream").init(privateKeyFilePath) />
<cfset derPrivateKey = jets3tEncryptionUtils.convertRsaPemToDer(keyFileInputStream) />

epochDateLessThan - This needs to be an ISO8601-formatted date that tells CloudFront the date and time on which the signed URL will expire. How do we get the date into the right format? That's where the JetSet ServiceUtils object we created earlier comes in:

<cfset expiresOnDate = jets3tServiceUtils.parseIso8601Date("2013-02-14T22:30:00.000Z") />

Note that the date string has to be in the supplied format has to be in UTC time format. You can use time offsets if you need.

Here is the complete code we need to create the signed URL:

<cfset accessKey = "YOUR ACCESS KEY" />
<cfset secretKey = "YOUR SECRET KEY" />

<cfset awsCredentials = createobject("java", "org.jets3t.service.security.AWSCredentials").init(accessKey, secretKey) />
<cfset cloudFrontService = createobject("java", "org.jets3t.service.CloudFrontService").init(awsCredentials) />
<cfset jets3tServiceUtils = createObject("java", "org.jets3t.service.utils.ServiceUtils").init() />
<cfset jets3tEncryptionUtils = createObject("java", "org.jets3t.service.security.EncryptionUtil").init("dkhcoaj3fh2sk0oay") />
<cfset cloudFrontObjURL = "https://gobb7edyg00k.cloudfront.net/somefile.mov" />
<cfset privateKeyFilePath = "/path/to/you/keyfile/pk-YOURKEYFILENAME.pem" />
<cfset keyFileInputStream = createObject("java", "java.io.FileInputStream").init(privateKeyFilePath) />
<cfset derPrivateKey = jets3tEncryptionUtils.convertRsaPemToDer(keyFileInputStream) />
<cfset expiresOnDate = jets3tServiceUtils.parseIso8601Date("2013-02-14T22:30:00.000Z") />
<cfset signedUrl = cloudFrontService.signUrlCanned(cloudFrontObjURL,keyPairId,derPrivateKey,expiresOnDate)

You can then use the signed URL value in an <a href> or anywhere you can supply a valid URL.

Hella-long blog post? Yes. Hopefully those of you who need to create signed URLs for CloudFront using ColdFusion will find it a big time-saver!

Diving Deep at cf.Objective()!

I'm honored to have been selected to speak at this year's cf.Objective() conference. I got the opportunity to speak for the first time at cf.Objective() last year, and this year, the good people on the content selection committee asked if I'd do a deep dive on my proposed topic: Making Your ColdFusion Apps Highly Available.

The full sessions description and outline is at the link above. However, that description and outline were written before the topic was selected as a deep dive session (which runs for two hours instead of one). I do plan on adding a bit more, including information on:

  • monitoring options for the local cluster
  • using a message queue (ie; RabbitMQ/ActiveMQ) in your architecture
  • separation of services to ensure availability when one service (ie; PDF generation, custom reporting, email) fails. This is particularly important for AWS/cloud deployment.
  • moving existing apps to the cloud vs. building cloud-native apps

Once I get the outline finalized, I'll try to get it updated on the cf.Objective() site.

Anyway, thanks again to the cf.Objective() conference team. I can't wait!

cf.Objective() 2013 Call for Speakers is Now Open

cf.Objective() is my favorite ColdFusion-related conference. No offense to the great teams who put together NCDevCon (also pretty damn awesome) and MAX, but I've always been the most challenged and gotten the most out of my time at cf.Objective(). Last year, I was privileged to be asked to speak at the conference, and I hope to do so again this year.

The cf.Objective() team has just opened the call for speakers for the 2013 conference. They really want to see proposals around the following topic areas:

  • Software Architecture & Design
  • Integration & Tools of the trade
  • Security
  • Mobile Development
  • Front End Development & Design
  • Javascript aka js.Objective()

If you think that you're not smart enough or a good enough public speaker to speak at a conference like cf.Objective, do not sell yourself short!. If you have strong knowledge on a subject area that is of interest to developers, they will want to hear you talk. We've all had interesting or difficult challenges to overcome in our daily work, and those make for really good conference presentations (conflict is a great hook for structuring a presentation, plus you get to show how you overcame the problems).

You have about a month to get your proposals in, so get to it!

Learn ColdFusion in a Week is Now Available

Some of the smartest people in the ColdFusion community have put together a great getting started guide for learning ColdFusion: Learn CF In a Week. This is a great, free resource to anyone who wants to pick up ColdFusion quickly. Instead of buying a book or purchasing training videos about getting started with ColdFusion, there's this free, in-depth resource (that's not to say that the CF Web Application Construction Kit series of books shouldn't be on every CF developer's bookshelf, because they should be!).

Learn CF In a Week gets you up and running quickly, and covers modern application development features like building business logic with objects, CF's implementation of Hibernate for Object-Relational Mapping (ORM), and — my favorite &madash; caching. It's all written in a very approachable style, with quite a few examples.

Even better, there are hands-on exercises for each and every part of the training. This way, you get to put into practice what you read about, which is a much better way of actually learning how to program in any language. Learning by doing is always much more effective than simply learning by reading. (That's not just an aphorism - there's lots of research to back that up.)

If you're looking to move up from client-side coding with JavaScript, learning ColdFusion with Learn CF In a Week is super easy!

Slides from "Making Your ColdFusion Apps Highly Available"

Attached to this post are my slides from my presentation at NCDevCon 2012: Making Your ColdFusion Apps Highly Available. While I do talk a bit about ColdFusion code changes that are necessitated by moving from a single server to a cluster, all of the content applies to making any web application highly available, no matter if it's written in ColdFusion, PHP, or Ruby. In future iterations, I suppose I should rename the talk to "Making Your Web Apps Highly Available."

The presentation also wound up covering a lot more about Amazon Web Services than I had originally planned, but there's so many powerful tools in AWS to make applications highly available that I felt I needed to give a solid architectural foundation for attendees to work from.

In any case, enjoy the slides. The last few slides are reference slides that have links to the services and tools mentioned in the presentation. If you have any feedback about the presentation, I'd love to hear it!

I'm Speaking at NCDevCon 2012!

I'm really excited that the team behind NCDevCon 2012 has selected me to speak at this year's conference. I was really impressed by last year's conference (my first) and I really wanted to speak again this year.

Here's the session description for my session:


Making Your ColdFusion Apps Highly Available

Level: 200 - Intermediate

Thousands of Web applications run on a single server, and that works great. But what happens when you need 99.999% uptime and you have to move your Web application from that single server into a cluster of servers in your datacenter, or the cloud? This session focuses on the challenges you'll face moving your ColdFusion-based app from a single server setup to many ColdFusion servers running in parallel. Specifically, we'll look at changes you'll need to make to your:

  • application code
  • database setup
  • ColdFusion application server setup
  • server configuration
  • network setup
We'll also cover special considerations that need to be made for cloud services like Amazon's Web Services platform. If you've never built a ColdFusion app that runs across multiple servers with shared resources, this session is definitely for you.


At $200 per ticket, NCDevCon is a great bargain. The quality of presentations is on par with other major ColdFusion and Web development conferences, and the conference is small enough that it makes it really easy to talk to speakers and meet new people. You're also only 30 minutes away from the best damn Carolina BBQ on the planet.

More Entries

BlogCFC was created by Raymond Camden.

Creative Commons License
The content on http://www.iterateme.com/ is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.