Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at NCDevCon 2011 (Raleigh, NC) with:

Learning ColdFusion 9: CFScript Updates For ColdFusion Components

Posted by Ben Nadel
Tags: ColdFusion

I am not a huge fan of CFScript. I prefer to work with tags. I find them have a nicer layout and provide a cleaner interface for defining tag-level properties. But, ColdFusion 9 does have a large number of CFScript updates and a few people have asked me personally to demo these upgrades. The implementation on the CFScript updates in ColdFusion 9 are spread out all over the CF9 documentation. As such, it's almost impossible to know if a feature doesn't exist or if you aren't just looking in the wrong place. Everything that I found out was through a combination of scouring the documentation, searching Adobe Help, leveraging Google, and much trial and error.

On top of that, Adobe is splitting the new tag implementations along three different, somewhat confusing lines:

  • Tags as functions.
  • Tags as operators (with and without bodies).
  • Tags as objects.

I understand why some of the service tags have to be objects - they are far too complex to be anything else. But, I guess what I don't understand is why any tag would be a function? Meaning, why would any tag (such as CFLocation) be a function (location()) rather than an operator (location)? Or why would any simple tag like CFExit be an operator (exit) and not a function (exit())? This split, between function and operator, seems to be completely arbitrary. Looks like there is going to be a lot of straight-up memorization to do.

That said, I figured I would start out with defining ColdFusion components in CFScript as components are a hot topic and people seem to like the idea of doing this in CFScript. I have to apologize ahead of time that the color coding on my site doesn't handle script-based code well, so this is all going to show up as black text. Also, I will not be talking about any ORM features because ORM it is not CFScript-specific (and really, I'm not yet qualified to be telling people about ORM).

In this demonstration, we going to set up two ColdFusion components: a Base component and a Girl component. The Girl component will be extending the Base component. Let's look at the base component first:

Base.cfc

  • component
  • output="false"
  • hint="I am the base component."
  • {
  •  
  • // Define the properties.
  •  
  • /**
  • * @getter true
  • * @setter false
  • * @hint This is a universal unique identifier for this component. It cannot be modified (hence the setter is false).
  • **/
  • property string uuid;
  •  
  • // Set the UUID. Because the UUID does not have an implicit
  • // setter, we have to set it manually in the variables scope.
  • // This will still let the implicit getter get to it.
  • variables.uuid = createUUID();
  • }

The first thing to notice is that there are no tags at all here, not even a CFComponent or CFScript tag. The entire body of the CFC file will be considered CFScript if you leave it as plain text. This component is relatively uninteresting, so I won't go into detail until after we look its extending class, Girl:

Girl.cfc

  • // Define the ColdFusion componet in script. Notice that the next
  • // comment block starts with two stars "**". This is crucial if
  • // you want the following meta data to be applied to the component
  • // definition. If you only use one star "*" at the beginning of
  • // the comment block, the "@" properties will be ignored.
  • //
  • // Further more, the actual property definition lines must start
  • // with a single "*" otherwise they will be ignored. I am closing
  • // the comment block with "**" only for balance - not required.
  • /**
  • * @species human
  • * @kinky:hint Girl object used for blog post on CFScript.
  • **/
  • component
  • output="false"
  • extends="Base"
  • hint="I represent a girl object."
  • {
  •  
  • // Define object properties. Normally I wouldn't use any
  • // property tags; but, by using tags here, ColdFusion 9 will
  • // build implicit getters and setters (not actually, but it
  • // will handle the getXXX() and setXXX() of the properties.
  • // NOTE: It uses the VARIABLES scope to store properties.
  • // NOTE: These properties will show up in the CFDump output.
  • // NOTE: Implicit getters / setter are about 8x faster than
  • // manually created getter/setters.
  •  
  • // Define property using in-line attributes. Notice that
  • // when we define things this way, we have to define the
  • // name and type using name/value pairs (unlike following
  • // examples).
  • property
  • name="id"
  • type="numeric"
  • getter="true"
  • setter="false"
  • default="0"
  • hint="The ID of the girl in a persistence context."
  • ;
  •  
  • // Define the property using both comments as well as
  • // inline attributes.
  • //
  • // NOTE: This is the only way to get the default value
  • // to be an empty string.
  • /**
  • * @getter true
  • * @setter true
  • * @validate string
  • * @validateParams { minLength=1, maxLength=20 }
  • * @hint This is the name of the girl.
  • **/
  • property
  • name="name"
  • type="string"
  • default=""
  • ;
  •  
  • /**
  • * @getter true
  • * @setter true
  • * @validate regex
  • * @validateParams { pattern=(?i)(Blonde|Black|Brunette) }
  • * @hint This is the hair color of the girl.
  • **/
  • property hair;
  •  
  • /**
  • * @getter true
  • * @setter true
  • * @validate boolean
  • * @default false
  • * @hint This is a flag for hotness.
  • **/
  • property boolean isHot;
  •  
  •  
  • // Define the component constructor. Remember, ColdFusion 9
  • // will look for methods with the name Init() or with the
  • // name contained in the initmethod attribute above.
  • //
  • // Do not use both the "required" keyword AND provide a
  • // default value on an argument - it will override the
  • // required aspect, making the argument optional.
  • //
  • // Function attributes can be defined using the following
  • // comment block or after the signature (but before the
  • // opening brace).
  • //
  • // NOTE: Using both declarations for a single property will
  • // throw a ColdFusion error).
  • /**
  • * @hint I return an initialized instance.
  • * @description I return an initialize Girl object instance.
  • **/
  • public any function init(
  • required string name,
  • string hair = "",
  • boolean isHot = false
  • )
  • // Define optional method properties here if you did not
  • // define them in the property comment block above.
  • output="false"
  • {
  •  
  • // Store the properties. Remember, since ID does not have
  • // an implicit setter, we have to set it manually.
  • variables.id = 0;
  •  
  • // Use implicit stters for the rest of the properites.
  • this.setName( arguments.name );
  • this.setHair( arguments.hair );
  • this.setIsHot( arguments.isHot );
  •  
  • // Return this object reference. Remember, if this method
  • // is invoked via the implicit constructor, then it only
  • // returns what we return here, so be sure to return THIS.
  • return( this );
  • }
  •  
  • }

This component, just as the one above it, is defined entirely using CFScript. There's a lot here that's different than a tag-based ColdFusion component, so let's just start at the top and work our way down.

The first thing you might notice is that I am using two different kinds of code commenting. Some of my comments are single-line comments, starting with "//", and some of them are comment-blocks starting with "/*" and ending with "*/". Generally speaking, I prefer single line comments; but, with a CFScript-based ColdFusion component, you can use the comment-blocks to access some of the tag-equivalent functionality. And furthermore, these comment-blocks are specialized comment-blocks. Notice that the opening of a comment-block starts with two stars, not one: "/**". This is not an accident. You can define tag and function properties within these comment-blocks; but, only if they start with two stars. Start them with only one star and the entire comment-block is ignored.

Each one of these two-star comment-blocks can define zero or more properties for the operator that it precedes. To define a property (which would be the equivalent of a tag attribute in the tag world) is defined as the property name with a "@" prefix followed by the property value:

/**
* @PropertyName PropertyValue
**/

While the two-star opening is required, you do not need the two-star closing (it can be one-star) or the single star at the beginning of the property declaration. I put those in there only to maintain a certain visual balance and symmetry. The value of the property is a static value - any ColdFusion method calls are not evaluated and the actual text of the method call command becomes the value of the property. If you want the default value to be the empty string, you have to use inline property attributes; any attempt to leave the comment-based property values blank results in it becoming the boolean "Yes".

The CFComponent tag in CFScript becomes the "component" operator. And, as with other script-based operators that have a body, it is followed by open and close braces:

component { ... component body ... }

When defining the tag-properties of the component operator, we have two different options. We can use the comment-block as described above, or we can put name-value pairs between the "component" operator and the opening curly brace. You'll notice in my Girl.cfc code above that these properties can be name-spaced just as with their tag counterparts.

After the component operator, we can define our object properties using the "property" operator. Before ColdFusion 9, the CFProperty tag was fairly useless, leveraged only in Web Services and 3rd party frameworks; but, in ColdFusion 9, the property tag takes on a whole lot more functionality (much of which is used for ORM which I will not be covering here). The property operator can now be use to define private variables as well as the implicit getters and setters used to access and mutate those private variables.

The basic declaration of a property is the property operator followed by the name of the property:

property propartyName;

Between the operator and the name, you can also supply a data type:

property dataType propertyName;

... as in:

property string name;

If you are going to use this style of declaration, then all other properties (attributes) of the property operator must be defined in a comment-block preceding the operator. Keep in mind that simply declaring the property does not actually set any values in the private variables scope - you still have to set those manually in the component constructor.

By default, ColdFusion 9 provides implicit public-access getter and setter methods for all declared properties in the form of this.getPropertyName() and this.setPropertyName(); however, by using the attributes of the property operator, you can override this default:

  • @getter: This is a boolean value that determines if ColdFusion will provide an implicit getter method for the given property. By setting this to false, no implicit getter will be provided.
  • @setter: This is a boolean value that determines if ColdFusion will provide an implicit setter method for the given property. By setting this to false, no implicit setter will be provided.

In addition to getter and setter access, you can also use the @validate and @validateParams properties to define the validation rules to be used in the implicit setter methods:

  • @validate: This is the equivalent to the Type attribute of the CFParam tag.
  • @validateParams: This is the collection of qualifying attributes that would be used in the CFParam tag to augment the Type attribute. So, for example, if the @validate type was regex, the @validateParams would contain the Pattern to be used. This collection takes on the declaration of an implicit struct with name-value pairs for the various CFParam attributes.

If you look back up in the Girl.cfc code, you will notice that the constructor method of the component is using these implicit setters to store the init() arguments. Take note that the ID property is being manually stored in the variables scope. This is because we turned off the implicit setter on the ID property so that it would become a read-only property to the outside world.

If you don't want to use comments to declare your property attributes, you can use inline name/value pairs (thanks for pointing that out Sean Corfield):

property name="name" type="value" attribute="value" attribute="value";

All of the attributes available in the comments-blocks are also available in this method of declaration.

After the component and the property operators, the only thing left to know about are the function declarations. The basic function declaration is defined by the access mode, the return type, the function operator, and the name of the function:

access returnType function methodName(){ ... function body ... }

As with the component operator, there are two ways to define the attributes of the function: using the preceding comment-block or by adding name-value pairs before the opening curly brace of the function body. Personally, I would always go with the comment-block as adding the properties before the opening curly brace in the context of a function just looks horrible (don't be that guy).

The parameters of the function are defined as a comma-delimited list within the open and close parentheses. The basic parameter declaration is defined by the data type, parameter name, and any default value:

dataType parameterName = defaultValue,
dataType parameterName = defaultValue,
dataType parameterName = defaultValue

By default, each parameter is considered optional. If you want to make a parameter required, you have to add the required operator before the data type:

required dataType parameterName

Do not use the required operator and a default value at the same time on a given parameter. If you use both, the default value declaration will turn the parameter into an optional parameter. And, of course, if you want the parameter to be optional but without a default value, simply leave off the default value part of the declaration:

dataType parameterName

That's really all there is to know about CFScript-based ColdFusion 9 components. We've covered the component, property, and function operators; everything else is really just a matter of non-specific script-based functionality upgrades (which we can cover in other posts). To see this quickly in action, I set up a small test:

  • <!--- Create a new girl object with the given properties. --->
  • <cfset girl = new Girl(
  • name = "Tricia",
  • hair = "Brunette"
  • ) />
  •  
  • <!---
  • Output the girl object so that we can see how its
  • properties and methods are being set.
  • --->
  • <cfdump
  • var="#girl#"
  • label="Girl Instance"
  • />
  •  
  • <br />
  •  
  • <!---
  • Output some properties. Notice that we are using the
  • implicit getters based on the properties even though
  • these getters were NOT shown in the methods above.
  • --->
  • <cfoutput>
  •  
  • UUID: #girl.getUUID()#<br />
  • Name: #girl.getName()#<br />
  • Hair: #girl.getHair()#<br />
  •  
  • </cfoutput>

Here, I am creating a new Girl object using the "new" operator. Then, I am CFDumping it out and accessing some of the implicit getters defined by the property operator. When we run the above code, we get the following output:

 
 
 
 
 
 
Defining ColdFusion Components In CFScript. 
 
 
 

There are a lot more CFScript-based upgrades in ColdFusion 9, but these are all the ones that are CFComponent-specific.




Reader Comments

I really like script our coding standards at work are almost guaranteed to change to full script based components. You can also specify the init method ie:

component
output="false"
extends="Base"
hint="I represent a girl object."
initmethod="Girl"
{
....

public Girl function Girl(
required string name,
string hair = "",
boolean isHot = false
}

So you don't need to have the constructor as init you can use a more conventional name ( same method name as the object ).

Reply to this Comment

@Paul,

While I appreciate that people like to use class names as the constructor name, I would suggest sticking with Init() for two reasons:

1. Java objects still must use Init() to call their constructor, so you are bound to have lots of calls that looks like this:

<cfset java = createObject( "java", "girl" ).init() />

2. The InitMethod attribute is only called implicitly when you use the NEW operator. As such, if you don't use the new operator, you'll end up with calls like:

<cfset girl = createObject( "component", "girl" ).girl() />

... which I think just looks kind of funny.

Reply to this Comment

This has nothing to do with your code, but just a reminder to everyone that in CF9, you should be able to pass struct like such:
<cfset girl = new Girl( { name = "Tricia", hair = "Brunette" } ) />

Reply to this Comment

@Todd,

Careful though - that will pass the struct as the first argument, not as the collection. If you want to use the argument collection, I believe you have to do this:

new Girl(
argumentCollection = { name = "Tricia", hair = "Brunette" }
);

Reply to this Comment

@Todd,

I think we can all agree that being able to pass implicit structs via method calls is wicked awesome! :)

Reply to this Comment

@Ben Actually by specifying the init() method on the component it calls the constructor you specify. ie
<cfscript>
hotGirl= new Girl("Angelina Jolie","Brunette");
</cfscript>

Reply to this Comment

@Paul,

Right, but only when using the new operator. The new operator is the only thing that either executes init() automatically or checks the initMethod attributes. What I'm saying is that you should stick with init() to maintain symmetry with calls that use createObject().

Reply to this Comment

That make sense symmetry is a good thing. Not sure which way will will head yet though but good to know we have options :)

Reply to this Comment

@Paul,

Plus, I guess we have to think that using the class name as the constructor is quite prevalent in so many other languages, so perhaps things will shift that way.

I'm simply used to using init(), so it feels more natural. But, even Java (which uses init() via createObjet()) actually uses class-name constructors in the class files :)

I guess I'm not against it, especially if we start using the "new" operator across the board. I'll be very curious to see what emerges as the trend. From what it sounds like at your company, you are all leaning towards class-name constructors?

Reply to this Comment

@Ben

Yes we would be leaning that way, and within script its the same. Hmmm

<cfset girl = createObject( "component", "girl" ).girl("Angelina Jolie","Brunette") />

is not that bad. Not 100% decided either way yet.

Perhaps this is because we also do alot of c++ and actionscript and having the constructor the same name as the object just feels right :)

Regardless CF9 is looking to be an awesome release.

Reply to this Comment

@Paul,

You're probably right. The more we move towards the paradigms set by many other programming languages, anyway, the more seriously we'll probably be taken :)

Reply to this Comment

One thing that I think will be controversial is using comments to change the meaning of code. The /** ... */ comments - called JavaDoc style comments BTW - are not the only way to specify the attributes. You can say:

property name="foo" getter="true" setter="false";

The CFML Advisory Committee were very unhappy about the idea that comments would change the behavior of code and were almost unanimous that this should be vendor-specific. Code should always mean the same thing - comments should never affect that meaning.

JavaDoc comments in Java are just that: comments - for documentation. That's why annotations use a non-comment syntax (e.g., for Hibernate / JPA).

Reply to this Comment

@Sean,

I'm glad you pointed that out. I'm one of those people that feels very strongly that comments shouldn't be able to affect the meaning of your code, and until you said that, I thought that it was going to be our only option in CF9 (I'm only half way through the docs :) The most frustrating part about it is that it allows people to intermingle regular comments with the semantic comments in a single block, which is just a bad practice, IMO.

I hope that as people start to create script based components, using the actual keywords/operators instead of the comments will evolve as a best practice. I truly feel sorry for the people that have to write parsers for this stuff - now they have 3 different syntaxes that they have to support!

Reply to this Comment

@Sean,

Ahhh, thank you. I tried putting name/value pairs in the property operator, but I always got errors. Thinking back on it now, it's because I tried to put the getter/setter *before* the name of the property. Ooops. Good tip!

I agree that it's a bit odd that comments do change the behavior of the code. However, in some cases, such as with function attributes, I found it to be much more readable than putting them before the curly brace.

Reply to this Comment

I like the idea of cfscript...but I'm now using Railo 3.1 (boo me if you want!) haha...so I'll have to see what happens with that. Hopefully they'll play catch up :)

Reply to this Comment

Railo is committed to implementing the CFML2009 spec :)

That means core CFML and extended core CFML. We'll have to evaluate the vendor-specific parts to see what is the best way to tackle things.

For the record, Hibernate integration was deemed vendor-specific for CFML2009 (even by Adobe) since it is a first implementation of a completely new (and fairly large) feature. Railo has been working with JBoss on plans for integrating Hibernate and, whilst we'll provide as compatible an implementation as we can (to Adobe's implementation) for the main use cases, we may provide what we consider enhanced features, based on feedback from the JBoss team.

The Advisory Committee will review Hibernate integration for CFML2011 and see whether it is ready to specify as extended core.

Reply to this Comment

@Sean: Care to elaborate on what 'working with JBoss' actually means. Is it more than just submitting support tickets on Hibernate? Is the Hibernate team actively involved in Railo development?

Reply to this Comment

Yup, the enhanced CFSCRIPT stuff is part of the CFML2009 spec so we are currently planning to implement that for our next "major" release (3.2) scheduled for year-end (approximately).

Reply to this Comment

@Adam, not sure what you're fishing for here? We're a JBoss community project, our bug tracker (JIRA) and SVN repo are hosted on jboss.org along with other JBoss projects (including Hibernate). We work with JBoss just like other community projects do. Back at Scotch on the Rocks 2008, the announcement was made jointly with Luc Texier of Red Hat, and Sacha Labourey of JBoss blogged about future collaboration plans:

"Railo and the JBoss.org community will be working on several enhancements to provide CFML® developers tag-based access to some core services available in JBoss AS today, including JBoss Cache, Hibernate and JBoss Messaging."

Reply to this Comment

@Sean,

Thank you for adding that. I was a little concerned when Ben explained that part since, like others, I think a comment in code serves a known purpose. Comments affecting the surrounding code (and being parsed!) seems rather counter-intuitive.

Reply to this Comment

I'm just trying to reconcile what JBoss is saying vs what the Railo team is saying.

You've implied that the Railo implementation of Hibernate will be somehow 'enhanced' by your relationship with JBoss. How is that so?

Reply to this Comment

@Sean,

Thanks again; I have updated the code sample and the explanation to point out the name/value pair approach as well.

Reply to this Comment

@Adam, what I said was "based on feedback from the JBoss team".

I was just adding a caveat to our plans for compatibility. No more, no less.

I think you're looking for an issue where there isn't one...

Reply to this Comment

Hi Ben
Just because something has parentheses, doesn't mean it's a function. Give consideration to for(), if(), catch(), etc. Not functions.

As for why would a tag be a function? I reckon any tag that:
a) doesn't have a closing tag;
b) takes attributes and returns a value;

makes more sense as a function than a tag.

I do agree it's confusing that CF9 has things like throw and throw() as two separate constructs (and both working slightly differently!). Hopefully throw will get dropped.

I also hope the fact that some attributes in the javadoc comments actually perform actions gets dropped too. A comment is a comment, as Sean alludes to. It should not impact how the code runs at all.

--
Adam

Reply to this Comment

@Adam,

You make a good point; maybe my gut feeling is that those other operators (if, catch, for) all have bodies and things like location() do not. I don't really know where I'm going with that... but, I guess something is just not sitting right in my gut.

I guess I just need to get down and start to memorize this stuff.

Also, are there are any CFHeader or CFContent script equivalents? I was not able to find any?

Reply to this Comment

Great post Ben. I'm a fan of the JavaDoc style syntax, but I also agree that comments shouldn't change code. I'm using a hybrid approach for my functions to get rid of the "noise" attributes. Also I've found that ColdFusion assumes that any text without an @xyz qualifier is a hint so my code looks something like this:

/**
* I am the hint for this method
* @output false
* @description I'm am a dumb and boring getter
*/
public string getSomeString()
{
return variables.somestring;
}

Reply to this Comment

I also agree that putting stuff in comments that affects the code seems wrong. If anything, I just don't like this 2 different ways to do the same thing, seems like it'll be more confusing than anything. Pick one. Preferably the one not in comments!

Reply to this Comment

I'm with you ben. I prefer the tag syntax but I do think that the cfscript looks pretty. I guess that comes with me starting out with php, and coming from php to cf is like OMFG I didn't think it would be this simple. Long live cf

Reply to this Comment

CFScript style syntax is definitely my preferred modus operandi. I'm extremely excited that you'll be able to build a site soup-to-nuts with CFScript.

Does anyone know if CF will support a HEREDOC syntax? Eg:
text = <<<FOO
I can be casual about my use of " and ' marks here, no worries about escaping problems!
FOO;

I'm with the others in thinking that it's a massive mistake to give comments compiler significance. Especially because they so closely resemble an existing industry standard with a different purpose that lacks compiler significance.

If you really want this sort of compiler significant metadata, instead of starting these significant blocks with "/**", they should start with something not already being used in the industry, such as "/!". They're writing a new parser for this, they could decide on whatever syntax they want, yet the fact that they choose one with such a collision seems like a decision which will bite us all down the road.

From a formal language perspective they are introducing context sensitivity into the parser (a bad thing mmkay) which, while realistically nearly impossible in practice, could be easily avoided in this case.

Reply to this Comment

@Eric,

Someone else mentioned HEREDOC notation somewhere on this blog. I haven't heard of ColdFusion adopting it at all though.

Reply to this Comment

Heredoc syntax was discussed but the committee has not yet been able to agree on an appropriate syntax that is idiomatic for the language ("""...""" is used in some languages but that is already valid in CFML - similarly we can't use '''...''' either).

Language design is hard!

Reply to this Comment

Just curious, is there something about traditional syntax (heredoc indicator followed by token identifier, such as <<<TOKEN from PHP, <<'TOKEN'; from Perl, <<TOKEN from Ruby, etc) which makes them infeasible for doing the same from ColdFusion script context? It seems to me that using a syntax which developers are already familiar with would reap easy rewards.

I'll be disappointed if heredoc doesn't make the cut, if for no other reason than writing SQL statements.

Reply to this Comment

Language design is all about compromise and consensus. None of the committee like the PHP/Perl style heredoc - they just think it's ugly. Look at the long-running threads on my blog about CFML syntax and you'll see there's not much consensus out there in the community either.

I think that because CFML has always allowed multi-line strings and you either use " and double-up internal "s or use ' and double-up internal 's most people don't feel enough pain to want to change this.

Reply to this Comment

Hey Ben, you'll want to update the code above to add accessors=true for the two component definitions, otherwise it fails in the final release.

For readers, this entry was written in July but in the final release CF9 has changed and requires one to add accessors=true in order to have CF auto-generate the getters and setters. Without setting accessors to true, one will get an error that "the method getName was not found in component".

I realize Ben now knows about this, as I see him commenting on the discussion in a recent entry on the subject at Dan Vega's blog (http://www.danvega.org/blog/index.cfm/2009/10/6/ColdFusion-9-Implicit-getters--setters-change). For those concerned, other comments there explain why this change was made.

I realize as well that Ben just hadn't gotten back to the entry here to correct this, but I wanted to point it out as well for readers who may find the same problem on other folk's older blog entries.

Hope that's helpful.

Reply to this Comment

@Charlie,

Thanks for posting the comment. When I saw Dan's blog post, my first thought was - Uggg! My blog posts are totally wrong now :) Honestly, I wasn't sure what do to. I think I'll put a NOTE at the top or something to talk about the necessary changes.

Reply to this Comment

Happy to help. About putting a note at the top, I hope you do mean in addition to changing the code itself, in case people just copy/paste and don't read. :-) Thanks for all you do.

Reply to this Comment

Hey Ben,

I'm learning how to do complete cfscript components at the moment (bit late to the party I know!) and this has been a great resource, as has your blog in general - I've been programming in Javascript exclusively all year so I'm just catching up on all the CF9 goodness now.

So a massive thanks for the effort you put into keeping us in the loop and making CF updates easy to assimilate. Cheers!

Reply to this Comment

I was reading over this and I had a question how are you getting the getters and setters to work without the accessors property being set to true? Is there a CF Admin setting that can override this, that I am missing?

Reply to this Comment

@Jed,

That's awesome to hear! Glad I could help. I still do stuff mostly in CF8 for production (we haven't upgraded yet), so I'm mostly in tags as of yet. But, when we upgrade, I'm really looking forward to seeing how this feels.

@John,

In CF9, you can now create implicit getters/setters (this didn't exist pre-CF9). I can't remember if this blog post came out pre-release or not. At some point, they changed it slightly. I think you now need to include the following in you your CFComponent tag:

<cfcomponent accessors="true">

... once you have that, you can then conditionally turn them getters and setters off using the individual property getter/setter attributes.

Reply to this Comment

Potentially a dumb question, but when using CFSCRIPT style code for method definition, is there any way to add hint description for an arguments, as there is using CFML tag? I'm very much a stickler for internal code documentation, and these is one of those things that seems to be missing from the scripting syntax.

Reply to this Comment

@K. Anderson,

Yes you can. Something like this:

/**
* I am the method hint
* @foo I am the foo argument hint
* @bar I am the bar argument hint
*/
boolean function doFoo( required string foo, required string bar ) {
return true;
}

Reply to this Comment

Great post Ben, one thing I might add to any newbie that is following your post and giving it a try for themselves and not able to get it the getters and setters working, you mentioned it in a previous comment, you will need to add accessors="true" to your component attributes.

Might want to edit your post to include that line, as some might be banging their heads as to why it is not working.

Long time reader of your site, which has helped me on numerous occasions.

Thanks.

Reply to this Comment

@Thomas, @Don,

You guys make a good point. If I recall correctly, they actually changed this behavior between the Beta and the Release to allow for onMissingMethod() usage. Honestly, I'd love to keep the posts as up-to-date as possible; but, things keep changing with each release.

What I should probably do is make a note of when I'm dealing with a Beta release vs. an actual release of ColdFusion.

But then again, even the dot-releases can change things.

Arrrrg... it makes my head hurt.

Reply to this Comment

@Todd Rafferty,

I think you meant this:

<cfset girl = new Girl(name = "Tricia", hair = "Brunette") />

So you don't pass it as struct, but as a collection of attribute name / value pairs; of course in this case the order of arguments is not important anymore.

Reply to this Comment

Regarding the use of CreateUUID().

Last time I checked, this:
createUUID()

Was 2x slower than this:
createObject("java","java.util.UUID").randomUUID().toString()

They produce slighlty different results too.

createUUID():
0310A4B5-CC59-EA05-43BB229A4D46B69C

java.util.UUID:
f4601c32-5814-4148-9ec9-7621a9e71518

(note the additional "-" and lowercase)

CreateUUID is already pretty quick, but if you want even more performance and you don't specifically need a uuid use a randRange(0,2147483647) - where 2147483647 is the largest allowed int value. It's around 8x faster on my machines.

Reply to this Comment

It seems like there's something missing here and maybe it's me... Is it impossible to dynamically define an attribute for the component? For example, I was trying to define a component like this:

  • /**
  • *@namespace application.appBaseUrl
  • **/
  • component{...}

That didn't work, so I tried it like this:

  • component namespace=application.appBaseUrl{...}

That didn't work either. I tried it with quotes and pound signs too, with no success of course. So I'm coming to the conclusion that I've got to include the statically coded url value in each of these components and I'll have to change it in each of my environments - surely I'm wrong about this and I'm just being stupid and missing something, right?

Reply to this Comment

@Ken, compilation happens before code runs so you cannot have dynamic (runtime) values in static (compile time) metadata - it just doesn't make sense and isn't possible.

Reply to this Comment

Sorry to jump on a very old thread, i hope it finds you. i want to use the coldfusion FBsdk it written to work on CF9+ and im on CF8.

At the start of the thread between you and Paul, you mentioned how one would init a component if 'new' wasnt used.

  • <cfset girl = createObject( "component", "girl" ).girl() />

I tried doing the same this with Facebook sdk but it returns an error

  • import facebook.sdk.FacebookApp;
  • import facebook.sdk.FacebookGraphAPI;
  • facebookApp = new FacebookApp(appId=APP_ID, secretKey=SECRET_KEY);
  • FacebookApp = createObject( "component", "fbsdk.FacebookApp" ).FacebookApp(appId=fbAppid, secretKey=fbAppAPIkey);



The method FacebookApp was not found in component D:\folder\location\project\fbsdk\FacebookApp.cfc

Can you please help in showing me what im doing wrong here?

thank you.

Reply to this Comment

@David, aw dang, my fault. David, the main issue here is you're on CF8.
iirc... import, new, cfscript based components... all these features were introduced in CF9, that FB framework linked above probably won't work for you.

Sorry for mis-reading your comment.

Reply to this Comment

Hi Don,

Thanks for the reply. I've already tried that, and it returned a similar error as the one i posted.

The method init was not found in component

Reply to this Comment

This has been bothering me lately, I personally use shared hosting, which usually runs the latest version of ACF (now I am on ACF10 and some of my components won't work even for ACF9). In fact there was a hosting provider who I had been using for about 7 or 8 years, and they always tried to have the latest version of ACF, but unfortunately they didn't update to ACF10, so I had to give them up for that reason and switch to Hostek. I feel for developers who can't switch to newer version (because they have to buy it and its not cheap), and who are stuck with older ones. Well, as an option one could use Railo, though I've never tried it myself in production. Now, when web is developing so rapidly, we can't afford being stuck with old versions of software.

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.