ColdFusion 9, Mango Blog, and git

I made a few major changes to my site in one fell swoop.

A few people asked me questions about the changes so I figured I would explain.

Why a VPS?

I really like my hosting company, YoHost, but it was still shared hosting. That meant I couldn’t experiment with administrative settings and whatnot. Also I was constrained to my hosting provider’s upgrade schedule. Changing to a VPS meant that I can do whatever I want whenever I want. I like that freedom.

Why ColdFusion 9?

You mean other than that I am an evangelist for it? Well I actually used a few pieces of it. I built an admin piece for my events page using ORM and ColdFusion Builder’s code generation. I also added a page that pulls in my presentations from SlideSix. To not tax their servers too much, I used the new caching features of ColdFusion. So I’m not just using ColdFusion 9 to use it, I’m leveraging some of the features.

Why Mango Blog?

First off let me just say, I love Ray Camden. I’d go so far as to say I have a non-sexual man-crush on him. That being said, I went to Mango Blog. I’ve been using it in our internal blog that Ben talked about a while back. There are a few things that I completely love. I love the rich text editor. I love the plugin architecture. I love the caching. I love the skinning. It’s fantastic. Those were my big motivators. I felt that even with the changes I made to the default Mango Blog install I could easily keep it up to date, whereas I felt extreme apprehension about updating BlogCFC because of all of the changes I made to code to make it work the way I wanted. To be clear, I had to tweak both, it’s just that my Mango tweaks were mostly in a skin, which won’t get changed by future updates.

Why git?

Because I want to be one of the cool kids who’s all like “Subversion, oh yeah I did that like 8 years ago, I feel so bad for you for using a mature technology that you can rely on.”

Okay maybe not. The big motivator for me for git was online/offline changes. I often work without a good network connection. Being able to work properly, with multiple check ins even without connectivity was killer. I also appreciate the fact that the metadata is in one place. This makes copying the project during a build feasible instead of a network intensive svn export. This reduced my build process for my site from 3 or so minutes to 30 seconds. This means I’m more likely to update more often.

So there you go. This was a very practical upgrade for me, I got a lot out of it, and I have a few reports that the site is even faster then it was before. So except for a little blog barfing on the aggregators it seemingly went well.

ColdFusion Thoughts from a Longtime PHP developer

Serge Jespers is a colleague of mine on the Platform Evangelism team. He’s a longtime PHP developer and has recently dipped his toes into the ColdFusion waters. He recently developed the MAX widget that’s been going around. In fact, he used ColdFusion to power it. Here are his thoughts on the matter:

…I’m fairly new to ColdFusion. I actually first touched CF about a year a go on the On AIR Train Tour through Europe. That was the first time I played around with CF after oh… some 10 years of working with PHP. I looked at CF a few years ago and never really took another serious look at it. I’m sure there are many of you out there in the same situation and I would like to invite you to take another look at ColdFusion. CF has changed and matured a lot since the early days and is just a breeze to work with. With a minimum amount of code, I was able to rapidly code my database calls for the widget. Another cool thing about ColdFusion is that once you write your database code, you can use it in a number of different ways. You can directly call the methods using Flash Remoting in your Flex application, call it as a webservice from a mobile Flash application and/or call it from an HTML page without changing anything in the original code. I surely was pretty impressed when I saw that the first time. If you’re a long time PHP user and want to know more about ColdFusion, I’d like to invite you to my session at MAX. I’m going to talk about the difference and similarities between PHP and CF and also talk about what CF can do right out of the box….

If you want to find out more about his experience with the widget, check out the rest of the article.

ColdFusion Builder Extension Test Creator

When I build or debug ColdFusion Builder Extensions I typically do the following:

  • Alter the extension code to write IDE post contents to file
  • Call extension in IDE
  • Alter the extension code to read IDE post contents from file
  • Debug through the browser

I found my self frustrated with this workflow. Instead, what if I created an extension that could capture the IDE content and write it to the disk for me?

That’s what I did.

I still have to adjust my extensions to read in the file, but I can make that conditional:

So now much less work for me, and if you’re interested, much less work for you. The extension is now up on RIAForge.com: ColdFusion Builder Extension Test Creator.

MAX 2009 Unconference – ColdFusion for the Masses: PHP, Java, Ruby, and ASP Developers

Wow, that’s a long title.

I’m doing a session at the ColdFusion Unconference at Max 2009 on promoting ColdFusion to non-ColdFusion developers. It’s about going into other communities and focusing on the correct arguments for ColdFusion. I want to both share what I’ve learned in terms of winning arguments, and hear what you guys think resonate. So I’ll be presenting a bit, but I’ll also be listening to your experience (if you care to share.)

So sign up for MAX 2009, and check out the Unconference.

This session will be Tuesday October 6th from 1:30 – 2:30.

Also check out my main conference sessions:

Leveraging Exposed Services in ColdFusion Centaur
October 5 at 11:30AM
This session is about the new exposed services or CFaaS we have included in ColdFusion 9. I’ll be talking about how to leverage them in Flex and other languages, and even how to enhance previous versions of ColdFusion with them.

ColdFusion with Microsoft Office, SharePoint, and Exchange
October 5 at 05:00PM
I’ll be talking about how nice ColdFusion plays with Microsoft technologies. While Exchange integration has been around since ColdFusion 8, with 9 we’ve added the ability to interact with SharePoint and Office documents.

 

Student Discount for MAX 2009

I thought I had seen the best discount for MAX a few weeks ago, when I blogged about the educational/governmental/non-profit discount. It seems that I was wrong. There’s an even lower one for students:

  • $199 for a full pass
  • $99 for a day pass

That’s a phenomenal price. If you are a student and want to take advantage of it:

  • Go to the MAX registration page
  • Use the discount code: STU691
  • You’ll have to provide student identification

Icebergs

As a developer, I know that awful feeling where you show a client/customer/constituent your work, and they ask you to make tweaks that they consider “easy changes” which for you are “complete architectural redesigns.” A large driver of this is the fact is that they don’t understand the amount of work that goes into building an application. They can’t really. To do so one has to fully understand the application architecture design, building, and coding process. In most cases to understand that you have to be a developer capable of it. If you are a developer capable of it, why are you hiring others? All this leads to the guy or gal in front of you asking you to change “just this little thing.”

People do it because people tend to think anything they don’t know how to do is easy. I think this is because our touch points with each other’s disciplines are so small and shallow. Our work is all icebergs. There is a little that can be seen, but underneath the surface it goes on and on.

What does this have to do with design?

The other day a typography site named Typedia.com launched. I follow a couple of the founders, and thought it was a cool idea. Then I happened to read a blog entry from the guy who designed the logo. (He’s John Langdon by the way, who did the ambigrams for the Dan Brown novel Angels and Demons.) In it he talks about the logo and the process of creating what is essentially a custom font for it.

Look at the logo. Did you have any idea that there were volumes and volumes of thought behind that logo, dating back to the invention of the printing press? I certainly didn’t.

Which leads me to think about the hundreds of fonts on my system (working for Adobe has its perks.) Each one of them contains some measure of this thought. Each of them is an iceberg too.

This leads me to think that every design comp I’ve ever seen is also an iceberg with hours of thought and volumes of reference and knowledge behind it. Makes me wonder about the push back I’ve given.

This does not lead me to say that all of these icebergs mean that I should not criticize other people’s work, or ask for changes. Volumes of content condensed into the wrong logo are still wrong, as John Langdon’s post reveals. It also does not make me naïve enough to think that every comp has had hours put into it, just that there are hours of expertise leading up to it.

It leads me to the thought that we need to be more mindful of the fact that what other people produce is not only what we see, but the accumulation of their expertise. We as developers need to see it when we look at the work of designers. We also need to see it when we look at the work of other developers. Once we do that we just need to go out and convince the rest of the world to look at our work that way. How we do that is a mystery to me, but I suppose it starts with doing it ourselves.

 

Co-working at IndyHall

Today I tried out co-working at Independents Hall. Co-working for those of you who might not know is basically people who don’t have traditional offices working in the same space. It’s for freelancers or independent contractors who tend to work out of their own homes or at their local coffee bar with WIFI. Instead of working alone, they can work with other independents and freelancers in a shared space. You get all of the benefits of having people working around you, the ability to talk to other people with similar drive, and a shared coffee maker.

Though I don’t quite fit that definition, I come kinda close. I travel a lot and when I’m not traveling I’m in my home office. I figured I was close enough.

It wasn’t quite what I was expecting. If you read their website, you get this feeling that people are bumping into each other, figuring out that they have a startup idea that will change the world, and working on it to the betterment of themselves and the world. Um, it’s just a bunch of guys and gals working in the same office, with no real dress code. People occasionally talk. Some people are working together.

What a frickin’ relief. I was afraid I’d get all covered in startup cooties and granola.

It was great. It was really affordable. I had a good conversation. I got a lot of work done. It’s three doors down from a smoke shop.

Assuming I’m allowed back- I was high maintenance with the office manager; which is the only logistical problem I had with the place. After months of getting up, leaving, and coming back to my laptop whenever I want to, I’ve gotten used to not having to call to get myself let back in. I assume that if you become member they give you some sort of code. (And the office manager was very gracious with high maintenance me. )

I recommend it to whoever is on the fence about it.

ColdFusion AIR Synchronization

First, let me just cop to the fact that this post draws a lot from Jayesh Viradiya’s post on this ColdFusion/AIR Offline support. I had to simplify his stuff to wrap my mind around it enough to talk about it. So hats off to Jayesh, he’s done some awesome work here.

I was doing a demo on ColdFusion and AIR integration at the keynote for CFUnited, and I figured I would go into a little more detail here.

First off, to call it “ColdFusion and AIR integration” is to do it a bit of a disservice. What our engineers have accomplished is nothing short of “ORM for AIR.” It handles:

  • Creating and maintaining the SQLite database
  • Saving objects to SQLite without SQL statements
  • Handling relationships:
    • one-to-one
    • one-to-many
    • many-to-one
    • many-to-many
  • Syncing those records back to ColdFusion

So I have a sample application that shows a basic demo of this, without the relationships. Jayesh’s demo has the relationships. I’ve attached the code here, so if you want to look at it, just download the whole thing. Otherwise, let me take you through it. One little note, this stuff was written for ColdFusion 9 Beta. There are some bugs. I’ll point them out where I can, and assure you that the bugs are being worked on.

So let’s start in the ColdFusion. First I define an ORM cfc:


component persistent="true"{
property name="personID" fieldtype="id";
property name="firstName";
property name="lastName";
property name="twitter";

public string function serial(){
return "#This.getFirstName()#|#This.getLastName()#|#This.getTwitter()#|#This.getpersonID()#";
}
}

Pretty straightforward; then I define a corresponding ActionScript class:


package airdemo
{
[Bindable]
[RemoteClass(alias="AIRDemo.person")]
[Entity]
public class Person
{
[Id]
public var personID:int;
public var firstName:String;
public var lastName:String;
public var twitter:String;
}
}

Note the RemoteClass mapping to the CFC on the back end. Now let’s go to the application. I have a simple data grid and form designed to show and edit the details of these person objects. I’ll skip that and go right to the part where I hook up AIR to the ColdFusion server:


private function init():void
{
// Provide Credentials for Server side Connection and CFC
syncmanager = new SyncManager();
syncmanager.cfPort = 80;
syncmanager.cfServer = "centaur.dev";
syncmanager.syncCFC = "AirDemo.personManager";

// THis handler will be called when any COnflict
// occurs while writing back changes on serverside
syncmanager.addEventListener(ConflictEvent.CONFLICT, conflictHandler);

//Kick off the application.
getRemote();

}

This connects this application to the ColdFusion server centaur.dev on port 80 and wires the syncmanager to AIRDemo.personmanager. More on that later. But it also kicks off getRemote which takes care of populating this application with data from the server. So getRemote() fires:


//GET records from BACKEND SERVER
private function getRemote():void{
var token:AsyncToken= syncmanager.fetch("fetch");
token.addResponder(new mx.rpc.Responder(fetchSuccess, fetchFault));
}

Syncmanager.fetch calls the fetch method of the ColdFusion CFC we set as syncmanager.syncCFC above. That method just retrieves the records using ColdFusion ORM.


remote Array function fetch(){
return EntityLoad('person');;
}

In most cases it is successful, in which case fetchSuccess calls createLocalDB:


//CREATE the actual SQLite DB
private function createLocalDB():void{
//Create a pointer to actual SQLite db file
dbFile = File.userDirectory.resolvePath("AirDemo.db");

var sessiontoken:SessionToken =syncmanager.openSession(dbFile,017916);
sessiontoken.addResponder(new mx.rpc.Responder(connectSuccess,connectFault));
}

In most cases that is successful and connectSuccess calls createLocalCacheFromRemote


//PUT records from BACKEND SERVER in SQLite DB
private function createLocalCacheFromRemote():void{
var savetoken:SessionToken = session.saveUpdateCache(pc);
savetoken.addResponder(new mx.rpc.Responder(saveCacheSuccess, savefault));
}

Those three ActionScript functions in concert with the ColdFusion one:

  • Got the data from the ColdFusion server
  • Created a local SQLite database for the data
  • Populated the local SQLite data with that data

Okay, so now I go through the application, update some data, and want to save it back to the SQLite database:


//SAVE to SQLite DB
private function saveLocal():void
{
//Generate person object from form.
var person:Person = convertFormToObject();

//session.saveUpdate saves record to SQLite Database
var savetoken:SessionToken = session.saveUpdate(person);
savetoken.addResponder(new mx.rpc.Responder(saveSuccess, savefault));
}

ConvertFormToObject does exactly what it sounds like, converting values from a form into a Person object, then session.saveUpdate() handles saving the record back to the SQLite store. No SQL required. Then we need to send it off to the ColdFusion server:


//SAVE to BACKEND SERVER
private function saveRemote():void
{
var committoken:SessionToken = session.commit();
committoken.addResponder(new mx.rpc.Responder(commitSuccess, commitFault));
}

That’s it. That transmits all of that changes made in this session to the ColdFusion server, where it is processed:


remote any function sync(required array operations,
required array clientobjects,
array originalobjects = ArrayNew(1)){

var i= 0;
var conflicts = ArrayNew(1);
var conflictcount = 1;

for (i=1; i <= ArrayLen(operations); i++ ){

var operation = operations[i];
var clientobject = clientobjects[i];
var originalobject = originalobjects[i];

if (operation eq "INSERT" ){
var obj = ORMGetSession().merge(clientobject);
EntitySave(obj);
}
else{

if (isinstanceOf(originalobject,"person")){
var serverobject = EntityLoadByPK("person",originalobject.getpersonID());
}
else{
throw "Invalid Object";
}

if (not isdefined('serverobject')){
var text="CONFLICT::SERVER OBJECT NOT FOUND, RECORD MAY BE DELETED ALREADY";
var conflict = New CFIDE.AIR.conflict();
conflict.clientobject = clientobject;
conflict.originalobject = originalobject;
conflict.operation = operation;
conflicts[conflictcount++] = conflict;
continue;
}

var isNotConflict = (originalobject.serial() eq serverobject.serial());
if (isNotConflict){
if (operation eq "UPDATE"){
obj = ORMGetSession().merge(clientobject);
EntitySave(obj);
}
else if (operation eq "DELETE"){
obj = ORMGetSession().merge(originalobject);
EntityDelete(obj);
}
}
else{
var text="is a conflict";
var conflict = New CFIDE.AIR.conflict();
conflict.clientobject = clientobject;
conflict.originalobject = originalobject;
conflict.operation = operation;
conflicts[conflictcount++] = conflict;
continue;
}
}
}
if (conflictcount gt 1){
return conflicts;
}
}
}

So this is a lot of code, but basically it performs the following steps:

  • Check to see if the record is new
    • If so insert it
  • Then check to see if the update is in conflict
    • If not, delete or update accordingly
    • If so, send a conflict back to the AIR client

Now back in the client you have to handle the conflict, in this version of the application, I just replace the client details with the server details:


//OVERWRITE from BACKEND SERVER
public function conflictOverwrite(conflicts:ArrayCollection):void{
var token:SessionToken = session.keepAllServerObjects(conflicts);
token.addResponder(new mx.rpc.Responder(conflictSuccess, conflictFault));
}

Again, one function, session.keepAllServerObjects, handles overwriting everything on the client.

So that is the gist of what I was going to show at CFUnited. The code is attached, (Down at the bottom there is a “download” link) feel free to give it a try and see what you can do with it.