Learning ColdFusion 9: CFScript Updates For ColdFusion Components

Posted July 23, 2009 at 10:10 AM 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.


You Might Also Be Interested In:



Reader Comments

Jul 23, 2009 at 10:24 AM // reply »
5 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 ).


Jul 23, 2009 at 10:30 AM // reply »
10,638 Comments

@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.


Jul 23, 2009 at 10:30 AM // reply »
211 Comments

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" } ) />


Jul 23, 2009 at 10:33 AM // reply »
10,638 Comments

@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" }
);


Jul 23, 2009 at 10:35 AM // reply »
211 Comments

Bah, yes, it makes sense. Sorry. :|


Jul 23, 2009 at 10:37 AM // reply »
10,638 Comments

@Todd,

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


Jul 23, 2009 at 10:38 AM // reply »
5 Comments

@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>


Jul 23, 2009 at 10:39 AM // reply »
211 Comments

Yup, long time overdue. :)


Jul 23, 2009 at 10:41 AM // reply »
10,638 Comments

@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().


Jul 23, 2009 at 10:43 AM // reply »
5 Comments

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


Jul 23, 2009 at 10:46 AM // reply »
10,638 Comments

@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?


Jul 23, 2009 at 10:53 AM // reply »
5 Comments

@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.


Jul 23, 2009 at 10:56 AM // reply »
10,638 Comments

@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 :)


Jul 23, 2009 at 11:04 AM // reply »
105 Comments

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).


Jul 23, 2009 at 12:10 PM // reply »
44 Comments

@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!


Jul 23, 2009 at 12:18 PM // reply »
10,638 Comments

@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.


Jul 23, 2009 at 12:47 PM // reply »
12 Comments

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 :)


Jul 23, 2009 at 12:59 PM // reply »
26 Comments

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.


Jul 23, 2009 at 1:04 PM // reply »
1 Comments

Railo should also get full script support soon: http://railo.uservoice.com/pages/21016-general/suggestions/230165-full-cfscript-support


Jul 23, 2009 at 1:21 PM // reply »
4 Comments

@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?


Jul 23, 2009 at 1:21 PM // reply »
26 Comments

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).


Jul 23, 2009 at 1:54 PM // reply »
26 Comments

@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."


Jul 23, 2009 at 2:10 PM // reply »
1 Comments

@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.


Jul 23, 2009 at 2:16 PM // reply »
4 Comments

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?


Jul 23, 2009 at 2:36 PM // reply »
10,638 Comments

@Sean,

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


Jul 23, 2009 at 2:47 PM // reply »
26 Comments

@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...


Jul 23, 2009 at 3:47 PM // reply »
67 Comments

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


Jul 23, 2009 at 3:51 PM // reply »
10,638 Comments

@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?


Jul 23, 2009 at 4:03 PM // reply »
38 Comments

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;
}


Jul 23, 2009 at 4:13 PM // reply »
11 Comments

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!


Jul 23, 2009 at 4:59 PM // reply »
34 Comments

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


Jul 24, 2009 at 9:36 AM // reply »
32 Comments

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.


Jul 24, 2009 at 9:55 AM // reply »
10,638 Comments

@Eric,

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


Jul 24, 2009 at 3:40 PM // reply »
26 Comments

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!


Jul 24, 2009 at 4:48 PM // reply »
32 Comments

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.


Jul 24, 2009 at 5:14 PM // reply »
26 Comments

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.


Oct 14, 2009 at 10:07 PM // reply »
11 Comments

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.


Oct 15, 2009 at 8:28 AM // reply »
10,638 Comments

@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.


Oct 15, 2009 at 10:51 AM // reply »
11 Comments

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.


Aug 30, 2010 at 2:38 AM // reply »
1 Comments

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!


Sep 1, 2010 at 9:53 AM // reply »
1 Comments

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?


Sep 3, 2010 at 10:17 PM // reply »
10,638 Comments

@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.


Jan 17, 2011 at 4:35 PM // reply »
1 Comments

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.


Jan 18, 2011 at 5:02 AM // reply »
10 Comments

@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;
}


Jan 24, 2011 at 3:09 PM // reply »
2 Comments

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.


Feb 18, 2011 at 5:36 AM // reply »
12 Comments

@Thomas

gah! Thank you, didn't know what I was doing wrong.

Ben! Edit your post.


Feb 18, 2011 at 10:19 AM // reply »
10,638 Comments

@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.


Sep 13, 2011 at 12:44 AM // reply »
6 Comments

@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.


Sep 14, 2011 at 3:03 AM // reply »
21 Comments

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.


Jan 23, 2012 at 11:54 PM // reply »
1 Comments

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?


Jan 24, 2012 at 1:48 AM // reply »
26 Comments

@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.



Post A Comment

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.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 3, 2012 at 10:49 PM
How I Got Node.js Running On A Linux Micro Instance Using Amazon EC2
Wow this was really helpful! Only thing I would add is you need to update your .bash_profile after you edit the secure_path. This is what I did: $ . ~/.bash_profile Otherwise, NPM won't be found. ... read »
Feb 3, 2012 at 10:14 PM
Pushing Base64-Encoded Images Over HTML5 WebSockets With Pusher And ColdFusion
@Ben, Just wanted to let you know that pusher are soon to start limiting sizes on messages. This was the detail that came through in the Feb dispatch: "However, we will soon be limiting the s ... read »
Feb 3, 2012 at 5:05 PM
Regular Expressions Make CSV Parsing In ColdFusion So Much Easier (And Faster)
I tried using your RegEx in my C# program, but it was matching an extra empty-string at the end and so I would end up with an extra field that doesn't exist, so I changed it to this: (^|,)("(?: ... read »
Feb 3, 2012 at 3:47 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
Josh Cyr posted this on Twitter just a little bit ago. Thought it was appropriate. http://stackoverflow.com/questions/1619152/how-to-create-rest-urls-without-verbs/1619677#1619677 ... read »
Feb 3, 2012 at 2:28 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
@Michael, You definitely make a good point (and extra points for quoting movies - I love movies). When you use a return() statement to define the object's public API, it does provide a consistent a ... read »
Feb 3, 2012 at 2:04 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
To quote Jurassic Park: "Just because you can doesn't mean you should". I completely, utterly disagree with the thought that this is more readable. Consider the current module pattern: if ... read »
Feb 3, 2012 at 1:10 PM
REST API Design Rulebook By Mark Masse
@Jordan, Yeah, WRML was created by Mark Masse (author of the book). I also found it to be a bit convoluted. I suppose it is intended to allow the Client to be able to programmaticaly respond to cha ... read »
Feb 3, 2012 at 1:08 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
@Jason, To be honest, I don't have good answers for that kinds of stuff. And, to the point, that is specifically why I *really* liked the REST API Design Rulebook by Mark Masse - he just cuts throu ... read »