7 Random Facts About Me

This showed up on Facebook and I thought I'd make it into a blog post for no particular reason.

OK, I'm doing the random fact game. Here are 7 random facts about me you might not know.

  1. Early names suggestions for my last 'major' band, Far Cry Fly, were Ampersand, Kermit's Children, and Fozzie's Malaise.
  2. I have taken saxophone lessons, piano lessons, and voice lessons. I have taught myself guitar, bass, and drums. Other musicians say I have a great sense of timing and I accredit that to Steve Chetcuti, my saxophone teacher.
  3. My house is full of Cabbage Patch Kids, Webkins, and other random stuffed animals. We call them our "Imaginary perfect children." Someday I want to write a book about them and it will be a "Rugrats meet Winnie the Pooh" sort of thing.
  4. I have written 3 books that were published by Osborne McGrawhill. I am currently working on the fourth. These are technical books.
  5. I have participated in February Album Writing Month for four years straight; writing and recording 14 songs during the month of February. If you Google my name, some may come up on the Internet. But I'm not sure. I posted some songs on some music sites; but I forget the names.
  6. I make my own Dairy Free ice cream. Since it is Dairy Free perhaps it shouldn't be called ice cream? But, it is the same concept made with an ice cream maker.
  7. My band, Far Cry Fly, once got kicked off stage a few songs into our set. The owner walked up and said "play one more song and get off." because people were not dancing to us.

Calling a ColdFusion CFC from AngularJS

I have been working on my HTML5/AngularJS book and ran into a problem integrating AngularJS with ColdFusion. I wanted to be able to reuse the same ColdFusion services in my Angular project as they did with my Flex project. This didn't work quite as elegantly as I thought, so I thought I'd blog about the problems, and my solution.

Setting up the CFC

ColdFusion allows you to easily create a web service inside a CFC. Each method can be set with an access of remote and that makes the method available to AMF, SOAP, and REST calls. The AngularJS code will use REST. I put together a simple CFC for demonstration purposes:

<cfcomponent displayName="TestService" hints="I am a Test Service for an AngularJS Article">
 <cffunction name="sum" returnformat="plain" access="remote" output="true" hint="I am a Sample CFC" >    
  <cfargument name="num1" type="numeric" required="true"  />         
  <cfargument name="num2" type="numeric" required="true"  />         
  <cfreturn arguments.num1 + arguments.num2 />
 </cffunction>
</cfcomponent>

The CFC starts with a cfcomponent tag.  It has a single method inside of it, named sum.  The sum method accepts two numeric arguments, adds them together, and returns the result.  This is pretty simple. 

A ColdFusion Sample for creating a Post Call

There are two ways to call a CFC method as a REST service, either through an HTTP get call or an HTTP post call.  This is well documented in the ColdFusion docs. The problem with get approach is that all the values are put in the URL; and URLs have a character limit depending upon the browser. As such, I prefer to make calls using an HTTP post.  The name of the method and the arguments must be specified as form parameter in order for ColdFusion to determine how to process the call.

Here is a sample ColdFusion template to test the call:

<cfhttp url="http://#cgi.SERVER_NAME#/com/dotComIt/samples/callingCFC/TestService.cfc" method="post" result="results" >
                <cfhttpparam name="method" value="sum" type="formfield">
                <cfhttpparam name="num1" value="1" type="formfield">
                <cfhttpparam name="num2" value="2" type="formfield">
</cfhttp>
<Cfdump var="#results.filecontent#" />

This uses the CFHTTP tag to make the remote call.  It specifies three separate form fields:

  • method: This is the name of the method to call on the URL, named sum.
  • num1: This is the first argument value of the CFC’s method, and it is hard coded to the value 1.
  • num2: This is the second argument value into the CFC method, and it is hard coded to the value 2.

If you run this template, you'll see that you get a result of 3.0 displayed to the screen.  So, we have created a CFC and proved the method can be executed using an HTTP Post call.  The next step is to make this call from AngularJS.

Setting up the AngularJS App

To make a post call from AngularJS, you can use $http.post(), which is a helper function to make post calls easier.  Before we jump into that we’ll need to set up our Angular app.  Start with a simple HTML page:

<html>
<head>
    <script src="/AngularApp/js/libraries/angular.js"></script>
</head>
<body ng-app="testCalls">
</body>
</html>

This page imports the Angular framework and creates a single app; named testCalls.  Start another script block in the header and use it to define the application.  We'll be putting more JavaScript in this block later:

<script>
 testCalls = angular.module('testCalls', []);
</script>

Next, we'll need a div for our content:

<div ng-controller="testCallsCtrl">
</div>

The content is just going to be buttons that trigger calls to the remote service and display the results.  The content will be filled in shortly.  Create the controller in your JavaScript block:

function testCallsCtrl($scope, $http){
}

For now the controller is empty.  If you load your app in a browser, and check the console you should see no errors yet, but you also have no functionality.

Calling the Service with a Parameter object, and why it didn’t work

Most of the documentation I read about AngularJS has people making post calls and sending an object as the parameter, so that was my first approach.  First, add the button to the HTML Div:

<input type="button" value="Sum Via Post Object" ng-click="onPostObject()" />
<b>Post No Header Result</b>: {{postResultObject}}<br/>

This HTML Snippet will call the function onPostObject(), and through the use of binding display the results from the postResultObject variable. 

In your controller code, create the result variable:

$scope.postResultObject = 0;

Next, create a function to make the call:

$scope.onPostObject = function onPostObject(){<br />
}

Create an object to contain the three parameters:

var parameters = {
 num1 : 1,
 num2 : 2,
 method   : "sum"
}

This parameter object contains the method, sum, and values for the two input parameters to the method: num1, and num2.  As with our ColdFusion sample, both num1 and num2 are hardcoded values.  This is done for simplicity purposes of this sample.

Finally, use the $http.post() method to call the remote service:

$http.post('/com/dotComIt/samples/callingCFC/TestService.cfc', parameters).success(onPostObjectSuccess).error(onError);

The first argument of the post method is the endpoint of the service to call. In this case, it calls our TestService.cfc.  Then the parameter object is added.  On a success response from the server, an onPostObjectSuccess() method will be executed.  If the server has an error; then the onError() method is called.

The onError method is re-used for all our subsequent examples, so this is it:

var onError = function onError(data, status, headers, config){
 console.log('failure');
 console.log(data);
}

It simple logs the data to the console.  In a real app you would want to display information to the user, but that Is not needed here.  This is the onPostObjectSuccess() method:

var onPostObjectSuccess = function onPostObjectSuccess(data, status, headers, config){
 console.log('success');
 console.log(data);
 $scope.postResultObject = data;
}

This logs the returned data to the console, and uses it to set the controller’s postResultObject variable, which will in turn update the display.

If you set this up and try to execute, you will get unexpected results returned from the server. 

Instead of the number 3, you’ll see a bunch of HTML.  The ColdFusion server does not the parameter object as individual form variables, instead they are sent as a single object.  Since there is no method variable, ColdFusion does not try to execute the service method, but instead tries to load the CFC, which redirects to an Administrator login page.  The HTML of the login page is what is returned.

For comparison’s sake, this is what is shown in ServiceCapture for the call:

The ‘text’ is sent as one big JSON object.  That is not what we want.

Calling the Service with a Query String, and why it didn't work

The next approach I tried was to send the parameters along as if they were a query string.  First, let’s add the UI elements, the button and the place for the header:

<input type="button" value="Sum Via Post String" ng-click="onPostString()" />
<b>Post No Header Result</b>: {{postResultString}}<br/>

Back to the JavaScript block, and add the variable to hold the results from this:

$scope.postResultString = 0;

Next create the onPostString() method:

$scope.onPostString = function onPostString(){
 console.log('onPostStringNoHeader');
 parameters =    "num1" + '=' + 1 + '&'
 parameters +=   "num2" + '=' + 2 + "&"
 parameters +=   "method" + "=" + "sum" ;
 $http.post('/com/dotComIt/samples/callingCFC/TestService.cfc', parameters).success(onPostStringSuccess).error(onError);
}

The code uses string concatenation to create a parameter string, which will look like 'num1=1&num2=2&method=sum'. This is very similar to using a Query string.

The onPostStringSuccess() method just outputs the results to the console and updates the postResultString variable:

var onPostStringSuccess = function onPostStringSuccess(data, status, headers, config){
 console.log('success');
 console.log(data);
 $scope.postResultString = data;
}

If set this up and try it, the same thing will happen:

This is the same problem we previously saw.  ColdFusion doesn’t see the method name in the request and tries to launch the CFC in the CFC Explorer.  The page returned is asking for an administrator login.  This is the ServiceCapture information:

Although, we can see our parameter string as part of the call, there are no formal parameters attached to it; so ColdFusion can’t determine how to handle the call.

Calling the Service with a Query String, and getting expected results

The problem with the two previous calls is that the parameters are not being added to the call with the correct content type to create, what is essentially, a form post.  To solve this, we’ll need to specify the appropriate header.  First, add this to your HTML:

<input type="button" value="sum Via Post String w/ Header" ng-click="onPostStringWithHeader()" />
<b>Post Result With Header</b>: {{postResultStringWithHeader}}<br/>

This code snippet will call a method on the controller, and then display the results.  It works just like our previous two samples.

Create the postResultStringWithHeader variable in the Angular Controller:

$scope.postResultStringWithHeader = 0;

Next, create the method for making the remote call:

$scope.onPostStringWithHeader = function onPostStringWithHeader(){
 parameters =    "num1" + '=' + 1 + '&'
 parameters +=   "num2" + '=' + 2 + "&"
 parameters +=   "method" + "=" + "sum" ;
 $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
 $http.post('/com/dotComIt/samples/callingCFC/TestService.cfc', parameters).success(onPostStringWithHeaderSuccess).error(onError);
}

This code is almost, identical to the previous approach.  The most important change is that it sets the header for the HTTP calls to ‘application/x-www-form-urlencoded’.  This is the secret sauce that made the remote calls magically work.  This is the result method:

var onPostStringWithHeaderSuccess = function onPostStringWithHeaderSuccess(data, status, headers, config){
 console.log('success');
 console.log(data);
 $scope.postResultStringWithHeader = data;
}

The result method displays the returned data to the console and stores it for display in the HTML template.

These are the successful results, displayed in the browser:

This is the request from service capture:

You can see that this request has a formal parameter tab as part of the call.  When this request gets to the server, ColdFusion is able to correctly discern the request and determine which method should be called and how to handle the parameters.  We have achieved success.

Final Thoughts

A more in depth solution to what is going on under the hood is written up here. It also provides additional details on handling arrays and objects, which are important to many aspects of development.  I have spent a couple days researching the different methods to communicate between Angular and ColdFusion without rewriting code, or adding JQuery Dependencies, and this has been the most elegant.

How to Fail Fantastically: My 360|Stack Session Results + Video

At 360|Stack I gave a presentation entitled "How to Fail Fantastically" session results. I recently got the results from my survey. Only three people provided results this time; and there was only one comment.

I got two 5 ratings and one 4. I assume the ratings are out of 5; so that is pretty good. There was one comment left:

A very good presentation of things to watch out for if you want to run your own company, or for almost any venture you want to be a part of.

The comment is pretty complimentary. I do notice that since the went digital in their session survey's the ratings are fewer, as are the comments. I think people are less likely to type long comments into a smartphone.

And I promised a video, so you can view the presentation here.

Why You Didn't Hire Me

I started writing this post a few years ago; after I failed to come to terms with a new client. I finished it for September's Flextras/DotComIt newsletter. I realized that I seem to pass on more opportunities than I take on. Part of the problem is me, of course, because I can be picky about the type of work I take on. But, there does seem to be a common thread running through these rejections. This newsletter collects my thoughts on why I wasn't a fit for the project you wanted to hire me for.

How I Work

Before going into why we didn't come to an agreement, I thought I'd explain how I usually work. There are usually two different approaches I can take to a project contract: either by the hour, or by the project. I'll explain a bit about each approach.

By the Hour

Working by the hour means that the client pays me for each hour I work for them. This includes everything from meetings, email management, documentation, system maintenance, and writing code. Some important aspects of an hourly contract:
  • They are great if a client wants to get me in the door to have me start working as quickly as possible.
  • They are very flexible and allow for a constant change in requirements, priorities, and focus. This is good for the client because it allows for a fluid approach to development.
  • The deliverables are delivered when they are ready, and functionality usually comes in small, quick chunks.
  • If the client wants to manage me as one of their resources, then this is the way to go. Usually we have weekly planning session to discuss the progress made and the plan for the week. I expect that the client is involved every step of the way; and will direct where my efforts should go. This gets a very tight feedback loop and the client and problems can be addressed quickly.
  • The client can terminate at any time, usually with minimal commitment.
  • The client is responsible for managing the budget and schedule; and none of the responsibility is passed onto us. I will provide a client with weekly breakdowns known as time sheets that they must approve.

Some of these items are considered 'double edged' swords. The fluid nature of development means we often code for speed and not architecture elegance. It is tough for the developer to budget our time and finances without said commitments. Some clients are more comfortable by limiting their own commitment.

By the Project

Working by the project contracts usually means with a fixed fee. The client hires the developer for a specific period of time for a specific amount of money to complete a specific scope of work. Some aspects of a project contract are:

  • They are great for a client working within a fixed budget or under a deadline. This is also good for both the developer, who gets guaranteed work and the client who gets a guarantee on the project being complete in their limitations.
  • The budget is all inclusive, which means every aspect of our time is included in the budget.
  • A project plan is created, which will include fixed milestones with detailed descriptions of functionality. The down side of this is that this requires a lot of paperwork up front in order to define the scope. Sometimes it is hard for a client to create the documentation in enough detail needed to code something.
  • Changes to the focus or priorities can be very costly; and require additional paperwork. When changing a fixed fee bid; we have clients sign a change request that includes a description of the changes, the additional cost, and the new timeline.
  • We act as the project manager and balance our own time, budget, and development tasks against project milestones. This relieves the client of some responsibility, but the client usually gets more functionality in a single deliverable than they would in an hourly contract. Milestones are often 2-8 weeks apart.

A lot of developers don't like working on fixed fee bids; and I can understand why. The requirements are very rarely carved in stone and often change. It is tough to manage those changes in the context of a project bid. I, personally, love fixed fee projects because, like many small business owners, I like to look out at least three months ahead to see that we have a plan.

Reasons we Couldn't Come to Terms

Understanding the two approaches that I can take to project development, here are some of the reasons why I often don't come to terms:
  • No Contract: Some clients have insisted that we work without having a contract in place. A contract will define the terms of the full relationship including payment terms, code ownership, lawsuit liability, termination terms, and what one party can do if the other party is in default. I like to have the contract in place to avoid any ambiguity. In my early days it was to make sure I could get paid. These days, it also makes sure they can't claim ownership on work I do not do for them.
  • Intellectual Property Rights: Ownership of the project's output is a big deal for many companies. They want to make sure they own the project and source code, and are able to maintain it without coming back to us. They also want to make sure that the source code I provide them is not violating the IP rights of any other organizations or developers. This is all fine. However, I have seen IP clauses are too over-reaching for my tastes. I am very careful not to transfer ownership to the client of anything I do not build for them. I maybe building something for other clients; or I may be writing newsletters like this one, or I may be creating podcasts, or creating for my own projects, such as Flextras. I am very careful not to transfer ownership of everything I create.
  • Work with Jeffry Houser, not DotComIt: I've lost projects because I only work through DotComIt. Some people insist I must personally sign contracts as an individual instead of as a representative of DotComIt. I never do that. Issues such as insurance, liability, and accounting all go through DotComIt. As a compromise; I may suggest a 'key person' clause to the contract which says I will be the primary contact, or developer, on a client's project.
  • Mixing Project types: I don't like it when a client tries to mix our two approaches to development; and I'm undecided if that is me being inflexible or not. I have had clients request explicit deliverables in an hourly contract. Sometimes hourly contracts includes a limit on the amount of hours worked; so a list of deliverables could put me in a position where I am contractually obligated to complete said deliverables without pay. I do not want to be in that situation. Likewise, I have had clients request an hourly breakdown in a fixed fee project. I understand the client doesn't want to pay me for time I am not working, but in such cases, they should focus on the bottom line, functionality, and delivery dates. The micromanagement gives me a pause.
  • Non-Compete: I understand that a client doesn't want to hire me and then have me steal their client list, or source code, and use it to help, or become, a competitor. However, some non-competes are more far reaching than that. In one contract, with a web development firm that wanted to subcontract work out to me; a clause said I couldn't work in a similar industry. I feel every client I had before and after them would have violated that clause. Another contract had a guarantee I had not worked for any of their clients two years prior to signing. Without their client list; how could I make that promise? I'm fine with a company protecting their proprietary information, but I'm very careful not to sign away my right to continue to do what I do.
  • No-Advance: I always like to ask clients for an advance at the start of the project. Some clients insist on not paying anything until they have the final results, and that is a red flag for me. I do not want to spend weeks, or months, building something only to find out the client can't, or won't, pay. For fixed fee projects; I am usually able to successfully negotiate some type of an advance. For hourly projects, I am not always so lucky.

Any contract with a client will have a dozen different little things that will cover the working arrangement with the client. Usually many of these things are no-issue or easily dealt with, but the items above are the main reasons why I often walk away from a contract.

Final Thoughts

I'm curious to hear about experiences of others. What are some of the problems you've had when working with clients? At what point do you decide it is time to pass on this client and move on?

Deconstructing the Consulting Contract

At the recent 360|Stack conference, I presented some lessons learned about various business ventures I've been in. The presentation was called How to Fail Fantastically and spoke about many of the things I've done that didn't work out perfectly.

Molly mentioned to me that most of the questions people asked about were about the legal portion of the talk and about contracts. That inspired me to dig out this article I had written back in 2007 for Fusion Authority Quarterly Update.

The article is entitled Deconstructing the Consulting Contract. At the time; this was one of the easiest articles I ever wrote; despite it being non-technical in nature. I approved the final on January 13th, 2007 if that matters.

My Hamburger Recipe

And now for something non-technical. A friend asked for my hamburger recipe. I've made this with both ground beef and ground turkey and we really like the taste. It works great for meatballs too:

Ingredients:

  • 1-1.5 Pounds of Ground Meat (Beef or Turkey). I buy the biggest package I can at BJs and split it in half.
  • 1/3 cup of Olive Oil
  • 2 Eggs
  • 1 Cup of Breadcrumbs (I use Panko Bread Crumbs which I run through a Food Processor and make very fine. The measurement of 1 cup is after they are food processed)
  • Seasonings (This is what we use)
    • 2 teaspoons of Parsley
    • 2 teaspoons of Onion Powder (or Diced Onions)
    • 1 teaspoon of Garlic Powder

Instructions:

  1. Mix all Ingredients Together. I use a KitchenAid Stand mixer; but you could also do it with your hands.
  2. Form into patties [or Meatballs]
  3. Bake in Oven at about 400 degrees for 10 minutes. This only partially cooks them; so if you want to eat right away you can bake for a bit longer.
  4. Store in freezer or fridge until ready for your meal. Often before cooking I will stab them through the center with a knife.

I've toyed around with different seasonings to mixed results. But, everything has been edible. Add Red Pepper if you want something spicy. Add oregano and/or Italian Seasonings if you want something with an Italian flair.

Creating a ViewStack with AngularJS

I've spent the past two months diving into as many JavaScript frameworks as I could find time for. I am trying to determine what I can use in a book I'm writing entitled "Life After Flex". The book will be about converting a Flex application to JavaScript. I decided that I like a lot of things about AngularJS.

This is a tutorial on how to get ViewStack like functionality within an AngularJS HTML project.  My one caveat is that I am not yet an expert in AngularJS; so my understanding of what goes on under the hood may be wrong.

What is a ViewStack?

One of the common navigator components in a Flex Application is known as a ViewStack. It allows multiple views to occupy the same the same space in an application at the same time.  Only one view is displayed at the same time.  The Flex ViewStack does not inherently include any way to navigate between views because that is usually done through user interaction, either through something in the view or through a TabBar.  In the MX Component set; the TabNavigator combines a ViewStack with a ButtonBar for us.

One use case for a ViewStack might be to show a login screen in one view; and the main application screen as another view.  When the user successfully authenticates the application will tell the ViewStack to change from the login view to main application screen.  There are a multitude of uses for this component.  

I wanted to see if I could use a similar approach in an HTML5 based apps.  I was successful and you can view the simple app.

The Index.htm page

The index.htm or index.html is often the main page of an HTML site.  That is where this tutorial starts.  The page must import the angular.js framework and our custom JavaScript Code, in viewstack.js.  It also needs to set up some special AngularJS directives so that Angular will know where to display the custom views.

First, the HTML page imports the JavaScript files:

<html>
<head>
<script src="angular.js"></script>
<script src="viewstack.js"></script>
</head>

The body tag will define the AngularJS application:

<body ng-app="viewStackSample">

The ng-app is a special directive for AngularJS that ties code in our custom JavaScript file to the elements of the HTML document.  Next, a div will contain the view:

<div ng-view></div>

The div includes a special AngularJS directive named ng-view.  Finally the HTML is closed; finishing off the page:

</body>
</html>

The viewstack.js File

The index.htm page referred to a viewstack.js file’ and this file will include our custom JavaScript code.  This code will define two custom controllers; one for each view. It will also set up a config element called a routeProvider.  A route is, basically, a URL.  Based on the URL, the ng-view in the index.htm will decide which HTML page to display.  The approach reminds me of the early years of ColdFusion’s Fusebox framework.  Based on the URL; it determines which page will be displayed.

This is the routeProvider setup:

angular.module('viewStackSample', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/view1', {templateUrl: 'view1.html', controller: View1Ctrl}).
when('/view2', {templateUrl: 'view2.html', controller: View2Ctrl}).
otherwise({redirectTo: '/view1'});
}]);

The first line is creating an AngularJS module.  The module is named; viewStackSample which refers back to the value of the ng-app directive defined on the body tag in the index.htm. 

On the newly created module, the config method is called, and the ‘$routeProvider’ value is configured.  The $routeProvider is defined with a function.  The function has two “when” clauses and one “otherwise” clause.  This code, basically says:

  • If the URL has “/view1” in it then display the view1.html in the ng-view of the index.htm file.  Send it an instance of the View1Ctrl.
  • If the URL has “/view2” in it; then display the view2.html in the ng-view of the index.htm file.  Send it an instance of View2Ctrl.
  • If the URL has neither of those in it; then redirect the URL to ‘/view1’ and try again.

The two values View1Ctrl and View2Ctrl are defined the same viewstack.js file:

function View1Ctrl($scope) {
$scope.title = 'View 1 From Controller';
}

function View2Ctrl($scope) {
$scope.title = 'View 2 From Controller';
}

These two functions are, in essence, data stores, like a model class.  They each define a variable instance named title and put that on the $scope variable.  $scope is just a fancy way to send data into the view template.  These functions can do a lot more than just define data; they can also have functions which can call remote services or communicate with other aspects of the application. 

The view1.html and view2.html files

The view1.html and view2.html files are simple files.  This is view1.html:

<h1>{{title}}</h1>
<a href="#/view2">Go to View 2</a>

The h1 tag refers to the title variable defined in the viewstack.js file.  It uses double curly brackets, with the variable name inside it.  This is framework magic which tells the template to display the value of the title variable instead of the actual text.  It also includes a link which will change the URL to “#/view2”. 

The view2.html is almost identical to view1.html:

<h1>{{title}}</h1>
<a href="#/view1">Go to View 1</a>

The view2.html file has the same H1 tag; although a different value will be displayed.  The link goes back to “#/view1”.    

Final Thoughts

Loading this page will allow you to switch between the two views easily by clicking the link.  The code is not quite as encapsulated as the Flex ViewStack; however it is not too difficult and an approach like this can provide a lot of flexibility to an application.

360|Stack is the rebranded 360|Flex.

I am buried in my man-cave lately, focusing on writing a book about converting a Flex app to other technologies. I wanted to pop my head out for a second to let you all know that I'll be speaking at the 360|Stack conference coming up in the beginning of August.

360|Stack is the old 360|Flex conference, but it has a slightly different name.

I'll be giving an inspirational presentation entitled "How to Fail Fantastically." I'll be talking about my various business ventures, such sa The Flex Show and Flextras and DotComIt and probably some you had never heard of.

Even if that doesn't excite you there is plenty of real technical content covering everything from Google Glass to more JavaScript frameworks than you can shake a stick at.

I have an extra ticket that I'm undecided what to do with. I'm thinking maybe some type of contest?

Manually configuring ColdFusion with IIS7

I sent this email out yesterday as part of the Flextras/DotComIt newsletter. I thought I'd repost it here.

I recently had the opportunity to move some of my hosted sites to Amazon web services. The Flextras site, The Flex Show, and my personal blog, are now all hosted on EC2. It has been a few years since I've had to deal with my own production server maintenance; and I came across a weird issue with IIS7 and ColdFusion 9. I thought I'd describe the issue and explain my solution.

IIS6 Compatibility is turned on

Normally, when you create a new instance of an IIS web server, you'll need to associate ColdFusion with it. ColdFusion provides a tool named the Web Server Configuration Tool that can attach an instance of ColdFusion with an instance of IIS. If you happen to be using ColdFusion 9.02--or later--and IIS7; you may receive this error:

The Web Server Configuration Tool will not work with IIS7 if IIS6 Management Compatibility is enabled. On this particular server, the management compatibility was enabled for the FTP plugin could be managed on the server. I did not want to uninstall the IIS management compatibility if I could avoid it. How could I tell IIS7 that it should send .cfm requests to ColdFusion for processing without using the Web Server Configuration Tool?

Editing the applicationHost.config file

Under the hood the mappings that tell IIS7 how to communicate with ColdFusion are in a file named applicationHost.config. You can find this file in the 'C:\Windows\System32\inetsrv\config\' directory. This file contains a lot of configuration for IIS7.

If IIS7 was already installed when ColdFusion was initially installed, then you can find a section that references an existing IIS7 instance with your existing ColdFusion instance. Look for something like this:


<location path="iisInstanceName">
<system.webServer>
<handlers>
<clear />
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="CGI-exe" path="*.exe" verb="*" modules="CgiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="AboMapperCustom-130401" path="*" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\1\jrun_iis6_wildcard.dll" requireAccess="None" responseBufferLimit="0" />
<add name="AboMapperCustom-130411" path="*.jsp" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130412" path="*.jws" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130413" path="*.cfm" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130414" path="*.cfml" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130415" path="*.cfc" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130416" path="*.cfr" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130417" path="*.cfswf" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130418" path="*.hbmxml" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="AboMapperCustom-130419" path="*.hbmxml" verb="*" modules="IsapiModule" scriptProcessor="C:\ColdFusion9\runtime\lib\wsconfig\jrun_iis6.dll" requireAccess="Script" responseBufferLimit="0" />
<add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>
</system.webServer>
</location>

If you're using CF Standard, you can just copy and paste this section; then change the path name on the location to be the name of your new IIS7 server instance. Restart your IIS instance and that should be all you need. Otherwise, you'll have to create the above section manually; by copying and pasting from above and changing your paths to relate to your own CF Install.

Although I didn't have the experience of setting this up using CF Enterprise, I expect the procedure will be similar; you'll just need to point to the jrun_iis6.dll for your specific instance of ColdFusion.

How to Create a System for Caching Data

I wrote this article for the monthly Flextras newsletter, and thought I'd share it here.

I was working with a client recently and we had some performance problems while accessing remote data from within our application. The user interface, built with Flex, was accessing our ColdFusion server, and ColdFusion would relay requests onto another remote system using SOAP web services. The web service data didn't need constant updates, so we decided to create a caching system for the data to improve performance. I thought the concepts behind that would make an interesting topic for this month's newsletter.

What Type of Data to Store?

We decided it was best to create a generic system to cache any type of data. The system should handle any type of data we wanted to throw at it. To accomplish this, I created two classes a CacheManager class and CacheData class. The CacheData class is intended to be a generic object used by the CacheManager. Here is a diagram of the class:

The CacheData class is used by CacheManager to store the cached data. It has three properties: the data to store and two dates. The first date is, dateCached, which keeps track of the date and time that the data was first cached. The second element is dateLastAccessed, which keeps track of the date that the data was last accessed. The data property should be protected, or private, or something similar depending upon your language of choice. The two date properties should be publicly accessible.

The class has two methods: get() and set(). The get method returns the data and should also update the last accessed date value to the current date and time. The set method will update the internal data property, as well reset the two dates. In an attempt to keep this as platform agnostic as possible; this would be pseudo code for the class:


package{ class CacheData{
// this value stores the data
protected var data : *;
// this value stores the date that the data was initially stored
public var dateCached:Date
// this value stores the date that the value was last accessed
public var dateLastAccessed:Date
// this method can be used to retrieve the data
public function get ():*{
dateLastAccessed = getCurrentDate();
return data;
}
// this method can be used to set the data
public function set(value:*):void{
data = value;
dateCached = getCurrentDate();
dateLastAccessed = getCurrentDate();
} } }

This is a very simple class, not much more than a glorified value object.

The CacheManager Class

The CacheManager class is a bit more complicated. This is your application's window into the cached data.

This is the class diagram for the CacheManager:

The CacheManager has two properties; minutesCached and cachedData. The minutesCached property is an internal value will be used to determine when data should be flushed and deleted. The cachedData is also an internal value, but it is a bit more complicated. I created that as an associative array of associative arrays. In Flex, an associative Array would be a Dictionary; in ColdFusion that would be a Struct. The first key of the associative array is the type of data you want to store. I call this the cacheKey. This may be "products" or "orders" or something similar, depending on the data you want to store. The second associative array's key is the dataKey. Examples of this may be "ProductID1" or "Order13" or anything that can be used to uniquely identify the type of data, such as its database's Primary Key.

The combination of the dataKey and the cacheKey is used to retrieve the data. The use of the two key structure allows a single instance of the CacheManager to be used to cache multiple types of data. There are also two methods as part of the cacheManager: store() and retrieve(). The store method accepts three arguments: the data, the cacheKey, and the dataKey. It will create a new object of CacheData object and call the CacheData.set method to store the data. It is the simpler of the two methods.

The retrieve method is where the magic happens. It first check's to verify that the data exists. Then it checks to make sure that the data is still relevant based on the current date and the date that the data was last accessed. If the data is too old; then it can be deleted. Otherwise it can be returned. This is a pseudo code class:


package{ class CacheManager{
// this value specifies how many minutes the data should be cached
protected var minutesCached : int = 1440;
// this value contains the cached data; using a two key structure. A CacheKey and a DataKey.
protected var cachedData:Dictionary = new Dictionary();
// this method can be used to retrieve the data
public function store (data:*, cacheKey:String,dataKey:String):void{
if(!cachedData[cacheKey]){
cachedData[cacheKey] = new Dictionary();
}
cachedData[cacheKey][dataKey] = new CacheData();
cachedData[cacheKey][dataKey].set(data);
return data;
}
// this method can be used to set the data
public function retrieve(cacheKey:String,dataKey:String):*{
var cacheObject = cachedData[cacheKey][dataKey]
if(!cacheObject){ return; }
var dateToClearCache :Date = getCurrentDate() - minutesCached
if(cacheObject.dateLastAccessed <= dateToClearCache){
cachedData[cacheKey][dataKey] = null; return;
} Return cacheObject;
} } }

Although it is beyond the scope of this article, you could also create a method to automatically clear old cache data. This is probably more memory efficient than waiting until the data is retrieved to clear it out.

Putting it All Together

Now that we have the code behind our CacheManager, the last step is to put that to use. First, create an instance of it; presumably in some globally accessible variable.


public var cacheManager :CacheManager = new CacheManager();

Let's say you just loaded a bunch of products from some remote source. You'd loop over them and store them in the CacheManager instance:


For each product in productArray
cacheManager.store (product, 'products',product.id):
End For Loop

In this code, we use the cacheKey named products and use a product ID for the dataKey. I once read something that said you when you file something; you want to make sure to file it in the way that you can find it when you need it. The dataKey for your cache should follow the same suit. When you need to retrieve the data, you want it to be filed under some name that you can use to retrieve the data later.

Retrieve the data from the cache when you need it, like this:


var product : Product = cacheManager.retrieve('products',product.id);

Be sure to check that you actually got a product back from the cache before you try to use it:


If(!product){
// do something to retrieve the product data from source
// or make sure your code accommodates for a non-existent product
}
// process product

Final Thoughts

I hope you found this article interesting. I did my best to make this as conceptual as possible, so you may have to modify the code in order to work in the language of your choice.

I have two other mini-announcements that I added to the recent Flextras Newsletter. First, the code that never became the Flextras Flex Spreadsheet Component has been open sourced by the original author. It is a very impressive piece of technology. Second, if you're in the mood for interesting weird music; I recorded a full album worth of songs for February Album Writing Month. It is a nice little diversion from programming at times.

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.

pure garcinia cambogia

payday loans online

seo services

seo services