Thursday, December 07, 2006

Some more cf profiling

What a great explanation of some of what's going on under the hood in the cf compiler.

As a side effect, there is a little bit of an argument in favor of using cfscript again.

Absolutely No Machete Juggling � Coldfusion’s Compiler

Thursday, November 30, 2006

Avoiding the Evaluate function

There is a good description about what is going on with the use of the evaluate function behind the scenes.

I still have one question after reading this that I'm sure somebody has already investigated. Do we pay the extra overhead for each occurrence of evaluate in a page, or just once? I don't mind so much if I'm just paying it once for 50 instances on a page. If the parser is getting invoked 50 times, I think I'm hunting them down and changing them.

ColdFusion MX 7 -- Avoiding the Evaluate function -- Version 7

Monday, November 27, 2006

filBuf bug

One of my cohorts is attempting to diagnose a filbuf issue on one of our production servers. It doesn't appear to be a coldFusion bug per se. It looks like it's probably an issue with the xmlparser that ships with cfmx6.1.

From my co-worker:

Here's a coldfusion file that demonstrates the issue and also includes my super lame hack for fixing it. all the fix does is put spaces around the brackets, since it's the >] and ]> constructs that seem to cause the error. if you're interested in the java file that demonstrates the problem when run under the JRE that comes with cfmx6.1, I can provide that, too.


<cfparam name="url.fixforwddx" default="false">

<cfsetting requesttimeout="1200">
<cfflush interval="100">

<cfset chars = "]]>">
<cfset chars2 = "">
<cfloop from="1" to="20000" index="i">
<cfset chars2 = chars2 & chars>
<cfwddx action="cfml2wddx" input="#chars2#" output="mywddx">

<cfif url.fixforwddx>
<cfset mywddx = fixForWDDX(mywddx)>
</cfif>
<!--- make sure both the deserialization and the check for wddx work --->
<!--- NOTE: add ?fixforwddx=true to the URL to apply the fix and see this not throw an error --->
<cfset y = isWDDX("#mywddx#")>
<cfwddx action="wddx2cfml" input="#mywddx#" output="z">


<cfoutput>#i# iswddx? #y#</cfoutput>
</cfloop>


<cffunction name="fixForWDDX">
<cfargument name="text">
<cfset var text2 = "">
<cfset text2 = replace(text,"]>"," ] >","ALL")>
<cfset text2 = replace(text2,">]","> ] ","ALL")>
<cfreturn text2>
</cffunction>


Any help greatly appreciated.

Tuesday, November 21, 2006

Handy user defined functions

Here are a few handy user defined functions that help with traditional form controls. Well, actually it's one udf and two variations on a theme.

They let you pass either a boolean value or two simple values that will be tested for equality.

You just use them in place of the attribute of the corresponding name in things like checkboxes, radio buttons and select controls. I always hated that embedded cfif approach. It always seems to flip out whatever editor you're using because of the nested angle brackets.


<cffunction name="checked">
<cfargument name="v1" />
<cfargument name="v2" />
<cfset var attrib = "" />

<cfif NOT structExists(arguments,"v2")>
<cfif IsBoolean(arguments.v1)>
<cfif arguments.v1>
<cfset attrib = 'checked="true"' />
</cfif>
<cfelse>
<cfthrow message="The parameter passed to the checked udf was not boolean" />
</cfif>
<cfelse>
<cfif arguments.v1 eq arguments.v2>
<cfset attrib = 'checked="true"' />
</cfif>
</cfif>

<cfreturn attrib />
</cffunction>

<cffunction name="selected">
<cfargument name="v1" />
<cfargument name="v2" />
<cfset var attrib = "" />

<cfif NOT structExists(arguments,"v2")>
<cfif IsBoolean(arguments.v1)>
<cfif arguments.v1>
<cfset attrib = 'selected="true"' />
</cfif>
<cfelse>
<cfthrow message="The parameter passed to the selected udf was not boolean" />
</cfif>
<cfelse>
<cfif arguments.v1 eq arguments.v2>
<cfset attrib = 'selected="true"' />
</cfif>
</cfif>

<cfreturn attrib />
</cffunction>

<cffunction name="disabled">
<cfargument name="v1" />
<cfargument name="v2" />
<cfset var attrib = "" />

<cfif NOT structExists(arguments,"v2")>
<cfif IsBoolean(arguments.v1)>
<cfif arguments.v1>
<cfset attrib = 'disabled="true"' />
</cfif>
<cfelse>
<cfthrow message="The parameter passed to the DISABLED udf was not boolean" />
</cfif>
<cfelse>
<cfif arguments.v1 eq arguments.v2>
<cfset attrib = 'disabled="true"' />
</cfif>
</cfif>
<cfreturn attrib />
</cffunction>

Tuesday, November 07, 2006

Named parameters, OH YEAH!

Hallelujah! Named parameters in cfstoredproc. I've been looking for this fix for so long now, I'd almost given up. I expect my ex will be on the phone any minute now ;) (fat chance). Thanks Adobe. Now, if only I wasn't working on mx6.1 all over the place. I guess I just need to do a little more flex work for the suits.

Monday, November 06, 2006

CFC Fight Club Rules



A bit of a rant, but lets have some fun with it. I have lots of candidates for numbers 7 and 8. Any thoughts on what they should be? Preferably framework agnostic.



  1. 1st Rule: You do not reference external scopes in a component.

  2. 2nd Rule: YOU DO NOT REFERENCE EXTERNAL SCOPES IN A COMPONENT.

  3. 3rd Rule: Always use "var" for private variables in your methods including loop counters and query names

  4. 4th Rule: Always explicitly scope references to the arguments scope.

  5. 5th Rule: Always create an "init()" method to get your component started. Avoid the use of the implicit constructor since it can't take arguments.

  6. 6th Rule: Avoid using the "this" scope unless it is for something you KNOW is never going to change. Otherwise, code that uses your cfc will be susceptible to errors caused by changes in your cfc code.

  7. 7th Rule:

  8. 8th Rule:

Wednesday, September 27, 2006

Firefox 2.0 RC1 released

The next version of Firefox has reached RC1.

Download your copy here.

Two minor things that I find handy:

1. Close buttons on the tabs instead of all the way to the right.
2. Integrated spell check for textareas.

Monday, September 25, 2006

Anti-patterns

I just stumbled across this page about anti-patterns on wikipedia. I find it helpful to read about worst practices almost as much as best practices. I think I've mentioned before how much I enjoy the Unmaintainable Code site. You can learn a lot by finding out what not to do.

As usual, I find that I'm guilty of some of the issues mentioned. In the case of the anti-patterns, I tend to use the "BaseBean" anti-pattern a lot. While I always found that putting it in my UML diagrams really confuses things (so I generally just omit it completely), I found that the ease with which the utility methods can be called to be quite elegant. Calling myObj.dump() to get a listing of my private variables seemed to work really nicely.

Now I find out that this is considered bad practice because the nature of the relationship between the base object and it's children doesn't make a lot of logical sense.

So now the trick is to change the nature of the relationship between these classes such that the utility object winds up being delegated to instead of inherited from. It's going to require a bit of refactoring to shuffle things about and I hope I can keep the syntax almost as simple as the anti-pattern method. I don't think it will be too bad, but I'd like to hear if you've built utility delegates and if you've run into any issues I should be aware of.

I'm guessing I'll be reworking my cfcBlaster as well. Luckily, I've always got so much free time to do little projects like this (just kidding!).

Tuesday, September 19, 2006

Practical Database Design

Practical Database Design, Part 1; Keys and DataTypes
Practical Database Design, Part 2; Normalization, History, and Event Logging

This is a must read for cf developers of all types. The two, short articles present the fundamentals of building databases that are maintainable and flexible. Guidance is provided to help you avoid those nasty design problems that create difficult data anomalies once your db is in production and collecting data.

One of the best aspects of this pair of papers is that the author has a knack for making complex ideas (like 4th and 5th normal forms) understandable.

You want to pay particular attention to the end of the second paper where the discussion turns to premature optimization. I've heard seasoned db designers state that they don't bother with trying to get past 3NF since it is just premature optimization. Being assigned to take over an application built by one of these types of designers can make you fill your trousers.

The author, Philipp Janert, makes the argument that deviating from 5NF is the premature optimization. I whole-heartedly agree.

A few extra files for cfcBlaster

If you recently pulled down cfcBlaster and were thinking of giving it a try, you may have noticed that most of the files generated extend another class. These classes are primarily supporting functions and a little common functionality that I use across components.

Again, it's easy enough to strip out or change the extension markup to suit your own needs, but just in case somebody wants to see the components I use, I posted them up with the rest of the code as a separate download.

It's the same procedure as before, download the file, knock off the .txt extension and then unzip the contents. These components like to live in the same directory you put your generated cfcs.

LINK

Thursday, September 14, 2006

CFCBlaster - Simple code generator

I thought I would throw this out there just in case it can help somebody. This is a little tool I use to bootstrap a lot of my simple table driven cfcs.

It's not built with any framework in mind, but you are more than welcome to hack the code to suit your needs. I imagine that a lot of people will need to strip out my vss header, but that should be relatively trivial.

Also, it's built with MSSQL as the db, so if you are using some other db, you're probably going to have to do some hacking.

Let me know if you are able to make use of it at all!

Download CFCBlaster

Tuesday, September 05, 2006

OT:The FIXX rocks the Ram's Head

OMG these guys haven't missed a beat. An AMAZING show at the Ram's Head in Annapolis. No opening act allowed them to get more material in. They even played three new songs that have yet to be recored. The show lasted 1:24:14. How do I know the length of the concert so precisely? It's because when you left, you had the opportunity to pick up a little USB drive with an mp3 of the entire concert stored on it. They copied the file for you while you waited. Freakin' fantastic use of technology.

If you've ever been even a passing FIXX fan, you owe it to yourself to see them live. You won't be sorry you did.

Tuesday, August 29, 2006

The overlooked INI file

Here's one that you may not have looked at before.  ColdFusion has three functions that let you work with Windows style .ini files.  I think most people pretty much ignore these functions, but I've found them to be quite handy in setting up applications.

Granted, if you're using one of the popular CF frameworks like Fusebox or Model-Glue, this may be of little interest since they tend to have ways of dealing with setting up environment variables.

For the rest of us, we generally wind up with some sort of cfswitch/cfcase construct in Application.cfm/.cfc to establish a set of environment variables in the application scope.  When you move your app to a new environment, we edit the values there or add a new case to our switch.

Using ini files instead of the switch approach is just an alternative and doesn't really add much in the way of different capabilities.  It's pretty much a stylistic decision.

I personally find the simplicity of ini files hard to beat, though.  Maybe that's because of my familiarity with them from past computing days.  Ini files (if you haven't worked with them before) are simply collections of name/value pairs stored in a plain text file.

You can segregate groups of name/value pairs with a section name and some bracket syntax.

A typical beginning ini file for an application might look like this:


;This file holds environment variables for myApp
;
;
[default]
dsn=myDatasource
root=/myApp
fullroot=http://myCompany.com/myApp
adminEmail=IBrokeIt@myCompany.com



I tend to name my file cfconfig.ini and store it in the root of my app, but you can do what you like.  You just need to put it in a place where cf can see it.

Enough yammering, how about some code:

Application.cfm/cfc excerpt




<!--- Environment variables --->
<cfset iniPath = getDirectoryFromPath(getCurrentTemplatePath()) & "/cfconfig.ini" />
<cfset section = cgi.SERVER_NAME & ":" & cgi.SERVER_PORT & ":" & cgi.REMOTE_USER />
<cfset sectionStruct = getProfileSections(iniPath) />
<cfif structKeyExists(sectionStruct, section)>
     <cfscript>
               iniPath = getDirectoryFromPath(getCurrentTemplatePath()) & "/cfconfig.ini";
               section = cgi.SERVER_NAME & ":" & cgi.SERVER_PORT & ":" & cgi.REMOTE_USER;
               keylist = structFind(getProfileSections(iniPath),section);
               
               for (k=1;k lte listLen(keylist);k=k+1)
               {
                    "application.#listGetAt(keylist,k)#" = getProfileString(iniPath,section,listGetAt(keylist,k));
               }
     </cfscript>
<cfelse>
     <cfinclude template="setup.cfm" />
     <cfabort>
</cfif>
    



If you use Application.cfc, then this would most likely go in your onApplicationStart method.  For Application.cfm, it usually just appears near the top.  Notice that I use a combination of the cgi.server_name, cgi.server_port and cgi.remote_user as a way to differentiate the different server environments.  This seems to work pretty good for me, although I sometimes have to implement a webserver based login in order to keep different development environments separate.  That's probably not needed by most people, but I tend to have more than one working environment for some apps.  The only reason I had to add the remote_user was because I tended to wind up with several localhost:80 for development environments that might not be set up exactly the same.

I have a file that I use to get an app started that I call setup.cfm.  The complete code follows:




Setup.cfm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
     <cfscript>
          iniPath = getDirectoryFromPath(getCurrentTemplatePath()) & "cfconfig.ini";
          section = cgi.SERVER_NAME & ":" & cgi.SERVER_PORT & ":" & cgi.REMOTE_USER;

          if (isDefined("form.fieldnames"))
          {
               // get rid of the two fields for a new value since we handle those separately
               form.fieldnames = listDeleteAt(form.fieldnames,listFind(form.fieldnames,"NEWKEY"));
               form.fieldnames = listDeleteAt(form.fieldnames,listFind(form.fieldnames,"NEWVALUE"));
               
               // loop over the form fields and add corresponding entries to the current section of the ini file
               for (k=1;k lte listLen(form.fieldnames);k=k+1)
               {
                    setProfileString(iniPath,section,listGetAt(form.fieldnames,k), evaluate("form." & listGetAt(form.fieldnames,k)));     
               }
               
               // add new name/value pairs to the ini file if they exist
               if (form.newKey neq "")
               {
                    setProfileString(iniPath,section,form.newKey,form.newValue);     
               }
          } else if (structKeyExists(getProfileSections(iniPath),"default")) {
               // Move any default entries to this section if it is the first time this section is being set up.
               defaultKeys = structFind(getProfileSections(iniPath),"default");
               if (NOT structKeyExists(getProfileSections(iniPath),section))
               {
                    for (i=1;i lte listLen(defaultKeys);i=i+1)
                    {
                         setProfileString(iniPath,section,listGetAt(defaultKeys,i),getProfileString(iniPath,"default",listGetAt(defaultKeys,i)));
                    }     
               }     
          }
          // reset the application
     </cfscript>
     
     <style type="text/css">
          body{
               background-color: #cfc;
          }
     </style>
</head>

<body>
     <cfoutput>
     <h1>Setup for #application.applicationName#</h1>
     <h2>[#section#]</h2>
     <a href="cfconfig.ini" target="_blank">cfconfig.ini</a>
     <hr/>
     <p>Run this page to establish application level variables the first time
     you install the application on a server or visit it with a new url.  
     You can re-run this file at any time to refresh the application
     variables.</p>
          <form id="setupForm" action="" method="post" name="setupForm">
               <table cellpadding="3" cellspacing="0" border="1">
                    <tr>
                         <th>Key</th>
                         <th>Value</th>
                    </tr>
                    <cfset keylist="">
                    <cfif structKeyExists(getProfileSections(iniPath),section)>
                         <cfset keylist = structFind(getProfileSections(iniPath),section)>
                    </cfif>
                    
                    <cfloop list="#keylist#" index="key">
                         <tr>
                              <td>#key#</td>
                              <td>
                                   <input type="text" name="#key#" value="#getProfileString(iniPath,section,key)#" size="100">
                              </td>
                         </tr>
                    </cfloop>
                    <tr>
                         <td>
                              <input type="text" name="newKey" value="">
                         </td>
                         <td>
                              <input type="text" name="newValue" value="" size="100">
                         </td>
                    </tr>
                    <tr>
                         <th colspan="2">
                              <input type="submit" value="Update">
                         </th>
                    </tr>
                    
                    </table>
          </form>
          <hr/>
          <h3>Full text of cfconfig.ini</h3>
          <cffile action="read" file="#iniPath#" variable="ini">
          <pre>#ini#</pre>
     </cfoutput>

</body>
</html>





The last piece is to put together a starting ini file.  If you create a section called [default], the startup.cfm file will copy any items you have under that section to any new section it creates when you move your app to a new location.

A few other items to note; if you use cflogin to protect your entire app, you probably will not be able to get to your setup.cfm page to get started.  I usually write a small exception for the setup.cfm file in the cflogin logic.  You also may want to disable the setup file or delete it once you have your ini file established in a production environment.  Let's face it, you probably don't need to deploy setup to production.  You can ALWAYS edit the ini file directly.  It's not really that hard.

The application.cfm file excerpt I have here is being used in a development environment, which is why you don't see a test for determining if the application has been initialized.  It's less robust, but it also makes any changes to environment variables immediately available.  Otherwise, I'd have to do things like restart the cf service to see changes to the environment variables.

Let me know if you find this as straight forward as I do.  

Monday, August 07, 2006

cflogin strangeness

I had an issue about a month ago with using cflogin on a site where special cflogin structure was outliving the session. After the session died, I wanted the user to be logged out so they could go back to the login screen and re-establish the session.

The answer seemed to be to set the loginstorage attribute of the cfapplication tag to "session". That way whenever the session timed out, the authentication credentials would be gone as well. It seemed to work great.

Except for one thing: Because I'm using j2ee sessions, the thought goes that after the last browser is closed, the current session is destroyed. That works as expected. The problem arises in that unless a cflogout was executed before closing the last browser, it seems like the authentication credentials survive.

The next time the user opens the application, the special cflogin structure is not detected, so the application throws the login screen (as expected). But, when the user authenticates, it appears to authenticate the user without executing any code inside the cflogin block. Very strange.

Biometrics hacked

We all knew it was bound to happen. Pretty much anything that can be recorded can be copied and no biometric security system is any more secure then the system that manages the data behind it.

ABC News: Expert Issues Warning About E-Passports

Tuesday, July 04, 2006

Way OT: Independance Day Resolution

Well, I've finally done it. I've found a political issue that I care enough about to actually become an activist for. I think it is of interest to nearly every American and can be a unifying goal for the increasingly extreme positions of both political parties. It's called the Fair Tax.

It's not an additional tax, it's a replacement for the existing mess of regulations that make up the federal income tax system. As such, it is revenue neutral to the government and does not deal with specific issues, such as which Federal programs are necessary or not. That's a different battle. It simply changes the manner in which we fund our Government's activities.

It replaces all federal income taxes including, personal, estate, gift, capital gains, alternative minimum, Social Security, Medicare, self-employment, and corporate taxes.

In their place would be a roughly 23% sales tax on all goods and services. Before you freak out and think that everything would be immediately 23% more expensive, consider this. Costs to produce all goods and services would have all of those payroll taxes from every step in the production cycle removed. There is every possibility that the prices we actually pay would remain roughly the same. And the amount you earn in your paycheck would be the amount you take home.

There are huge benefits to international trade. The cost to produce American goods would immediately drop over 20% (it varies a bit by industry becuase of the depth of the supply chain).

Because there is no corporate income tax, the United States would become a tax haven for foreign companies. That means jobs here plus foreign investment. American labor becomes much more competitive internationally because of the reduction in cost.

And April 15th becomes just another nice spring day. You would never have to file another income tax return.

Sound good so far? Well, it gets even better. In order to aid those poor people in this country living at or below the poverty level, each household would receive a pre-bate of the taxes on purchases necessary to survive at that level. It's paid each month. A single person household would receive $188/month, a married couple $376, etc. Everybody gets this prebate, not just the poor. This is to ensure that no American has to pay the fair tax on the basic necessities of life. That's fair.

There are lots of other positive rammifications of this approach, so if you want to learn more, you can visit the website at http://www.fairtax.org to learn more, or pick up the book that's floating around on the bestseller list, "The Fair Tax".

For me, this will be my one and only litmus test in future elections. I'll vote for anybody supporting this tax system regardless of party and I won't vote for anybody not supporting it.

I know I have only touched on a few points here, so I hope you'll take a look at it in more detail before you decide one way or another.

I think I have a few phone calls to make ;)

Monday, May 29, 2006

A case against DAOs?

Ok, maybe the title is a little provocative, but here is the thought. 100% of the work that I do, plan to do, and have done in the past have dictated the database to be used. A lot of CF devs are pushing the use of DAOs as a way to encapsulate the interaction between their business objects and the database. The argument goes that it's easier to swap out the database, roll a new set of DAOs and you're back in business.

For some projects this is probably true, especially when you need your project to support multiple databases (MSSQL, ORACLE, etc.) out of the gate. You let the user/administrator set a switch for the type of db and the code is already in place. This makes a lot of sense when you are building an application that you plan on distributing.

For the type of work that I do, this looks like a lot of extra work for little or no gain when the db choice is stable and your app has little chance of seeing any kind of distribution.

For me, just adding the CRUDS (create, read, update, delete, save) methods to the business objects themselves seems to work just fine and reduces the size of the app. As long as they are done consistantly and in roughly the same place, I don't really see a down side. If you found that you had to change to support multiple dbs down the road, it's not really that much trouble to strip the functions out and set up DAOs if needed, although it's a little more work than if you had set it up that way from the beginning.

Is this too short-sighted?

Some new blogs

I started a few new blogs to segregate some of my postings. Now that I'm doing more work with Flex (and have a lot more questions than answers), I put up FlexFactory. I plan on putting my posts about Flex and ColdFusion that interacts with Flex there since they may contradict some of the stuff I do with CF alone. There isn't much there yet, but I imagine that eventually, it will become the blog that I post on most, although I am still working on doing more with CF. I'm currently working on building out a library of collaboration patterns for cfcs, but I've got a lot of work to do with that yet. (I'm not sold on the idea completely myself yet).

I'm a huge movie fan, so just for fun, I put up Drive-in Movies. I do short little movie reviews there just as an experiment to see if I want to do more. I focus mainly on B-movies, but anything is fair game. There are a few other posters on that one, and I'd be happy to open it up to other people that want to try posting a review or two.

Wednesday, May 17, 2006

Bad cfc form?

Is the following code considered bad form?


<cffunction name="init" access="public" output="false" returntype="templateSectionName">
<cfargument name="dsn" required="false" default="#session.managedApp.getDsn()#" type="string" />


How big of a problem is it to violate encapsulation by pulling values in from persistent scopes? Are there varying degrees of acceptability, for example, is it okay to do this hear where I'm just supplying a default value as opposed to using a value in the rest of the component.

Are different scopes more acceptable than others for doing something like this. I would guess that pulling in a value from the application scope is probably more reliable than pulling something in from the session scope.

The problem I see with the code above is that code that uses this component may be written without defining a datasource directly. In that case the component may still work as long as the user's session is maintained and the ManagedApp component is in good shape in the session scope. The problem that I think this approach introduces is that where this code


<cfargument name="dsn" required="true" type="string" />


fails the first time it's run and fails consistently until corrected, the other method may run fine for quite a while before it fails because a session has timed out. Had the value existed in the application scope, I'd be more inclined to let it slide.

Any thoughts?

Tuesday, May 16, 2006

FB2 and VSS Plugin for Eclipse

I can't seem to get the fantastic VSS Plugin for Eclipse to install on the FlexBuilder stand-alone version. I haven't yet tried it on eclipse with FB installed as a plugin.

Let me know if you've been able to make this work.

SourceForge.net: VSS Plugin for Eclipse

Monday, May 08, 2006

Flex2Beta3 on its way

Looks like the download page has been updated for Beta3. I think we're just waiting for the files to be pushed to the fulfillment server.

Adobe - Downloads

Thursday, April 20, 2006

Next time, I'll have to rtfm.

A few weeks ago, I joined a discussion about flex remote objects in CF. The question of the day was: "How do you set separate result/fault handlers for each method in a cfc?"

You've probably seen this construct in one of the examples already. It looks something like this:


<mx:remoteobject id="a_named_reference_to_use_in_mxml"
destination="CustomID"
result="my_CFC_handler(event)">


You would normally set one of these up for each cfc you intend access from within Flex.

Some of the comments mentioned that people are either creating switch statements and picking apart some header information returned in the result to get the name of the method call. Others were creating a separate remote object for each method (I'm not sure that this would even work).

Had I bothered to scour the docs a little better, I would have found the real way to do this. the mx:RemoteObject tag can take a child tag. It might wind up looking something like this:

<mx:remoteobject id="a_named_reference_to_use_in_mxml" destination="CustomID">
<mx:method name="method1" result="method1Result">
<mx:method name="method2" result="method2Result" fault="method2Fault">
</mx:method>

Problem solved. Thanks to Simeon Bateman for showing this on his terriffic presentation at BACFUG!

Thursday, April 13, 2006

FireFox bookmark shortcuts (keywords)

I wish somebody would have told me about this feature long ago.  Firefox supports keywords on bookmarks.  I've seen that in the interface for many releases and never bothered to figure out what the heck it's for.  I always figured it was for some sort of searching/tagging feature in the bookmark manager.  I don't usually keep that many bookmarks, so I instantly ignored it.

Big mistake.  They work like shortcut keys in the address bar.

For example, if you were to bookmark "http://weblogs.macromedia.com/mxna/index.cfm?query=byCategory&categoryId=1&categoryName=ColdFusion", you could add "mxna" as a keyword.  Now, if you type mxna into the address bar, the bookmark gets loaded.

This is great for all those developer locations that you collect as you work.

Ok, I've got some bookmarks to tag ;)

Wednesday, April 05, 2006

OT:Flash / Honda Accord Ad

WOW! I've always been fascinated by Rube Goldberg machines and this has got to be one of the best. Very entertaining.

Albino Blacksheep - Flash / Honda Accord Ad

Can you hear me now?

Can you see me now? Can you interract with me now?!

Congratulations on a terrific partnering win. I've been waiting for this shoe to drop since MAX03. I'm guessing this is the first of many deals once the platform starts to gain momentum.

Adobe Brings Flash To Verizon - Forbes.com

Tuesday, March 21, 2006

Flex2Beta2 released

Lots of changes between Beta 1 and Beta 2. One of the more interesting changes I'm looking to take for a spin is that data binding can now be done to properties. Couple this with the automatic conversion between cfcs and .as value objects and you could have some pretty slick auto-wiring in your app. Getting it to actually work is the next trick.

Another change that looks like it will save a lot of confusion is that addition of a ColdFusion Flash Remoting Service project option in FlexBuilder. It takes care of managing the flex-services.xml file for you. Cool.

There are tons of other changes to the mxml language which will probably disrupt at least a piece of any previous work you've done with beta 1. Definitely check out the bottom of the linked page to see the extent of your search and replace job.

Flex:Beta 1 to Beta 2 Changes - Adobe Labs

Tuesday, March 14, 2006

Flex 2 Style Explorer (beta) available

Thank you Adobe Consulting!

This is a fantastic productivity tool to help get your design work in Flex 2 (beta) jump started. You can use it to spend an hour or two and have a complete style sheet for you app done!

The consulting group asks that if you find anything strange with the app that you let them know. I've been through it a bit now, and it seems ready to go to me. The only thing I haven't found is an entry for the buttonBar, but it might be in there somewhere and I just haven't run across it yet.
Adobe Consulting: Flex 2 Style Explorer (beta) available

Monday, March 13, 2006

Getting CFC/AS Auto-conversion working

This is regarding Flex 2 Beta 1 and CF 7.0.1.

Concept
One of the new features with the ColdFusion Flex Connectivity is going to be the ability to have your value objects automatically converted between CFCs and .as when you move them back and forth.  It should be a very handy tool.  For example, you might create a user object in Flex and populate it with a username and password collected from a login screen.  Your remote object passes it to a cfc that looks up the user, validates any credentials and populates additional properties.  It then gets passed back to Flex (flash) and updates the original object you passed in.  You then can use the new property values in the rest of your flex app.

Problem
There are a few examples floating around that show you how to do this.  Ben Forta has a pretty detailed example on his blog.  I was also able to find an example on the FlexCoders list: http://groups.yahoo.com/group/flexcoders/message/28768

Both of these examples, while being very informative, sort of left me hanging.  The last step is to validate that you have received a typed component back in Flex.  For me, both of these came back appearing as cf typed objects.  However, in flex they were treated as generic objects and would not automatically convert into the corresponding .as object or populate its values.  The part that was difficult to find/notice was that the typed object that cf was returning was all lowercase, whereas up to that point, the component name and some of the directories were in mixed case.

Use of the c:\CFusionMX7\runtime\logs\coldfusion-out.log was instrumental in finding this bug.

Solution
I think this should be classified as a workaround at this point, since we're still working with beta software.  The mixed case issue for properties has been dealt with in CF by supplying metadata with the cfproperty tag.  Now, I think we need a similar approach for the fully qualified component path/type as well.

I was able to make it work by changing all of the component paths and filenames to lowercase.  Not a very elegant solution, but it lets you keep working.

I've posted about this issue in several blogs and mailing lists, but I've never received a response from anybody running into the same issue.

If there is some other issue that I've overlooked (my coding error, installation problem, wrong software versions, etc.), or if there is a solution in the works, please let me know.

Tuesday, February 21, 2006

New CFEclipse Web Site

No sooner had I finished pushing people to download a copy of CFEclipse, than Sean Corfield mentions that there is a new website for the product up. It sounds like 1.3 is going to be available quite soon.

For a quick peak at what's coming for cfc's, check out Mark Drew's post about the work he is doing on the Component Explorer

Monday, February 20, 2006

Flex - A Call to Arms

Inertia is a terrible thing in developers. There is nothing more depressing to me than walking into a cf shop and finding that they are still using CFStudio 5 with a single development server supporting the entire department. I usually find that this is an outfit that was unable to keep their visionary developers and now have a room full of grey cube drones, pounding away at uninspired code. No one in the department has ever been to Max or CFUnited, no one actually knows where the closest cfug is, few have actually read a blog, and no one actually has a copy of flash.

There is a lot of blame to go around when you find an organization like this. Part of the blame goes to the individual developers. They have been complacent enough to allow their curiosity and hunger for knowledge be driven out of them by the organization. Most of the time, the truly inspired have been frustrated to the point of finding a different position. Or worse; looked down upon by the organization as trouble-makers and malcontents.

A larger part of the blame goes to the lead developers and project managers. They are the ones that let their day-to-day responsibilities crowd out a spirit of innovation and discovery from their teams and departments. While the developers are responsible for the stagnation of themselves, these people are responsible for sucking the life out of groups of 5 or 10 people.

The largest part of the blame has to go to executive management for being out of touch with their core business processes. They are the ones that have failed to realize that by not exploring new technologies, they are ceding competitive advantage to the competition. They are the ones that have failed to recognize that changes in their companies initiatives have gone from sweeping technological breakthroughs to functional tweaks.

So, if you have suffered through this post to this point being insulted along the way, here is your official kick up the arse:

Official Kick Up The Arse
Developers: Download the Flex Beta now. Do it both at home and at work. If you are working in ColdFusion in any capacity today, you will be affected by Flex in some way. Get to know it now so it doesn't trample you when it's forced upon you. Exploring it is great fun. It brings back that "lightbulb" effect when you first get something to work the way it should. You will start to see where your upcoming projects could be made more engaging for the user and more fun to build for you.

While your at it, try downloading cfeclipse. Once you get it configured to the point where you can actually work on a file, uninstall CFStudio 5. If you are still using CFStudio5 a month from now, expect another big kick up the arse. The rest of us will all be pointing at you and laughing.

Project leads/managers: Take a risk. Set aside some time for your developers to look at Flex. Let them come up with a small project that they could build that could be used internally. Something that won't break the bank but that could be made visible to other parts of your organization once it's in place. You know there is always a list of small products your toolsmith wants built that never get paid any attention. Maybe there is something there you could put together.

Your developers will find lots of other uses for the technology as they build. KEEP A LIST! Take credit for spearheading the research activities.

CxOs: If it is important enough for your company to have a development team, then you realize how important it is to use it to make your company more competitive. If your teams spend 100% of their time working on maintenance projects or incremental improvements in existing software, then either 1) your development team is too small, 2) your middle management lacks vision, 3) you're milking your Cash Cows (hey, that's funny), but not building Stars in your quest for short term gains.

It's time to kick your teams out of their rut. Spearhead a labs group. Make sure it has access to domain specialists across the organization. Devote at least an hour a month to stay in touch with the group. Make sure that the person you choose to lead your labs group reports directly to you regarding this part of their job. Provide the Labs manager with the authority to draw resources from the rest of your organization within reason. No one should spend more than 20% of their time on labs projects until you find a project that you decide should move into development.

Ok, that's it for this kick up the arse. Feel free to post here if you want another ;).

Tuesday, February 14, 2006

Google completely over-valued

This is purely my opinion, but I can't understand why Google's stock is priced so high. In light of their recent behavior towards both the US and China regarding privacy and human rights, it's obvious that the main motivating emotion driving the company is greed. I think a lot of us had hoped that the "Don't be evil" tag line would finally be true for a large company. Unfortunately, it's just not true, and I think it may not even be possible for a large, publicly traded company. Had Google remained a private company, then the personality of the owners would be the driving force behind the businesses activities. Now it must be the never-ending quest for the quarterly earnings figure.

As far as the technologies go that Google is releasing, Adobe Flex/Flash is WAY ahead of the AJAX toolkit that Google has built. All you have to do is look at Breeze vs. GMail to get a good sense of the relative maturity of the two technologies. The Google/Sun announcement has turned out to be vapor to date. What was the point?

The real question for the long haul, is can Google deliver more advanced software and still survive on the unobtrusive advertising model? It's an interesting question. It would be interesting to see if they could deliver an enterprise class software solution for free based on advertising revenues generated by the product inside the enterprise. Could they move into the Salesforce.com space with an offering, or maybe a twist on a small business accounting application. It's hard to imagine such an application being successful when technically, clicking one of the ads means you are no longer working.

Another problem that has cropped up for Google that is probably much more important than most people are admitting and that is the problem of click fraud. Click fraud with Google is where a system is set up to simulate clicking on Google's delivered ads. It results in essentially stealing from Google's advertising customers by Google's affiliates. In a small way, if you click on a few ads on a blog or website you like solely for the purpose of delivering a few pennies to the site's owner, you are committing click fraud. Imagine the trouble you could cause if you set up a couple of cfhttp bots and hammer away a constant stream of your own spurious websites. The big problem here is that Google has enabled the entire system of fraud from end to end. I'm not sure they could ever completely stop it.

So with a known (severe?) flaw in their core business model, can somebody tell me why this stock is valued so high? Are we so desperate to find an honorable company that we ascribe that characteristic to the first company that gives us a marketing campaign claiming to be "not evil" when its actions belie that image?

Tuesday, February 07, 2006

Google adds cool new feature to GMail and GTalk

Check out your GMail inbox and you may notice a new icon on the left.  It's a place to search you chat histories from GTalk.  If you've been irritated that you only have a few lines of viewable chat history in GTalk, you will probably find this feature to be a great new addition.

While Google has been recently tarnishing their "Don't be evil" reputation/mantra recently in the eyes of some because of their dealings with the Chinese government, they appear to be trying to bring back a little of that luster with this feature.

While it doesn't appear to be available in my account yet, there will eventually be able to go "off the record" with a particular contact.  When you do that, chat histories are not saved on either end for the conversation.  I guess the real question is if the data is being saved and used by Google if you are "off the record".

Thursday, February 02, 2006

Performance, Architectural Limits and RAM

Just for future reference, I dug this up from the Microsoft site when I was trying to figure out why my jvm was imploding. You can definitely hit some of these limits earlier than you would think. The tricky part is that your box can be humming along quite nicely while one trouble-making app runs into one of these barriers.

Quote:
On machines where you have 2GB of memory or more, you shouldn't set your maximum heap size larger than 1430 MBytes.

On any computer system, as load (number of users, amount of work being done) increases, performance (how long it takes to do each task) will decrease, but in a non linear fashion. Any increase in load (demand) beyond a certain point will result in a dramatic decrease in performance. This means that some resource is in critically short supply and has become a bottleneck.

At some point, the resource in critical short supply can not be increased. This means an architectural limit has been reached. Some commonly reported architectural limits in Windows include:

  1. 2 GB of shared virtual address space for the system
  2. 2 GB of private virtual address space per process
  3. 660 MB System PTE storage
  4. 470 MB paged pool storage
  5. 256 MB nonpaged pool storage

One sure fire way to run into this issue is to stuff lots of nested components into the session scope. Add a few cross joins to populate them with lots of meaningless data and you'll have a meltdown almost as fast as building infinite loops.

Thursday, January 26, 2006

Is cfproperty necessary for the Flex2 CFAdpater?

At the very top of the of the User.cfc in the UserManager sample application, I notice the there is a note that says:

In order for this CFC object to map correctly to an actionscript class, we must define each public property and the type, which maps to the public properties of the actionscript class.

It's followed by a cfproperty tag for each public property in the user object. It has been my experience that cfproperty does pretty much nothing unless you are trying to define a hash-map in a web service. Has this changed with respect to the CFAdapter? If I comment out the tags, the application appears to still work (although I seem to have some issues with caching sometimes).


I have posted this entry in Labs as well.

Thursday, January 19, 2006

CF hiring market heating up?

I'm generally not in favor of business combinations that diminish the number of participants in the competitive landscape. The acquisition of Macromedia by Adobe was no exception for me. I was pretty strongly against it from the beginning since I saw little benefit from the merger for the customer base of both companies. I'm sure that most businesses that had a desire to use the products of both companies already had relationships with each of them.

I also feel that most mergers of this type generally involve sacrificing some talented people in the quest to eliminate redundancies; a genuinely unpleasant situation for you if you happen to be one of those made redundant. Lack of competition generally leads to increases in pricing for products that loose competitors to the detriment of customers.

Over the last month, however, I've personally noticed a sharp increase in the demand for people with ColdFusion skills. Is it possible that Adobe really DID bring something to the table for Macromedia customers? Could it be that the simple recognition of Macromedia by an enterprise class vendor like Adobe as an acquisition target raises the profile of Macromedia technologies in the eyes of enterprise decision makers? I certainly hope so. If that is the case, I can only see that as a win/win/win for Adobe/Macromedia/combined talent base.

There are certainly lots of other factors that could contribute to the situation including time of year, pent up demand from the merger uncertainty, general economic outlook, maturity of technologies, etc. ad infinitum. My experience is purely anecdotal, so it could easily vanish like a wisp of smoke. Until it does, though, I guess all I can say is "cheers to 2006" and mark this as yet another instance where I was completely wrong (crap).

Given the choice between higher earning potential and being able to say I was right, I don't really have to think to hard about it. Feel free to call me stupid if you want to back it up with a check .

Anyone else noticing a change?

Thursday, January 12, 2006

How to make RequestTimeout work

Here's another beginner tip for an issue that had me hunting around for over an hour (Doh!). Since CFMX, the cfsetting tag has had an attribute called "requesttimeout". It allows you to force a long running page to use a longer timeout in seconds than is set in the administrator. I've used the cfsetting tag a few times since CFMX came out and I just figured it was one of those things that seems to not work as I expect sometimes. The requesttimeout attribute of the cfsetting tag is supposed to override any value set in the ColdFusion Administrator.

The keyword in that last sentence is override. It does not act to actually enable the request timeout feature of cf. If you don't have the checkbox and a default value set in the administrator, the value you set with the cfsetting tag doesn't have anything to override.

Your mileage may vary on this next point, but it is what caused my confusion for the longest time. If you don't have the checkbox in the administrator selected, you might expect all of your requests to run until they finish. What I have found is that in most cases, timeouts get taken over by the webserver settings. In my case, IIS has a cgi request timeout value that seems to kick in if I don't have request timeouts enabled in cf.