cfproperty – I ask you: why not default correctly?

When CF 9 arrived, one significant change was the elevation of the cfproperty tag thanks to all the new ORM goodness. What this meant was the arrivial of synthesised getter and setters and the fact that cfproperty values were now stored in the variables scope.

Overall this means very succinct code based around object properties. Except for one very annoying bug, that is.

I speak of the default attribute on the cfproperty tag.

If I write the following simple component:


<cfcomponent output="false" accessors="true">

	 <cfproperty name="foo" default="" />

	 <cffunction name="init" access="public" returntype="void" output="false"> 
	 	<cfset setFoo("bar") />
	 </cffunction>
	 
	 
	 <cffunction name="dumpVariablesScope" access="public" returntype="void" output="true"> 
	 	
	 	<cfdump var="#VARIABLES#" label="variables scope" />
	 
	 </cffunction>

</cfcomponent> 	

Now if I create the object and call dumpVariablesScope() I get the following output:

You can see that the foo property, despite having a default set to “” is not a first class citizen in the variables scope. Why not?! It is mentioned in the this.properties – not the same thing of course.

So I actually need to set that foo property in some way first. For example in the init() we could add this:

...
	 <cffunction name="init" access="public" returntype="void" output="false"> 
	 	<cfset setFoo("bar") />
	 </cffunction>
...

Or even this:

...
	 <cffunction name="init" access="public" returntype="void" output="false"> 
	 	<cfset variables.foo = "bar" />
	 </cffunction>
...

Then you see foo as it should be: a first class citizen in the variables scope:

I wish I didn’t have to write silly blog posts about this, I’m not sure if this is a bug or a feature, but it seems very counter-intuitive to me.

This entry was posted in Uncategorized and tagged , . Bookmark the permalink.

8 Responses to cfproperty – I ask you: why not default correctly?

  1. Fred says:

    Feature or bug? One way or the other.. I am annoyed.

  2. Ciaran, there seems to be a workaround: setting the persistent attribute on the CFC causes the defaults to be set. See this blog post for more detail.

    • Fred says:

      Yep tried it out.. it works pretty well as long then getter is set to true in the cfproperty tag… should not be a big problem.

      seems like the function that sets default attributes for me is a thing of the past.. 🙂

  3. GMS says:

    This had me for a bit you should be calling moo.getFoo() not moo.getFoo. Implicit getters and setters are function calls….

    so i had a filter model
    component accessors=”true” persistent=”true” {
    property getter=”true” setter=”true” name=”sortBy” default=”company” type=”string”;
    property getter=”true” setter=”true” name=”sortdir” default=”asc” type=”string”;
    property getter=”true” setter=”true” name=”maxresults” default=”25″ type=”numeric”;
    }

    and a service:
    component {
    public any function getListings(){
    var f = request.context.filter;
    entityLoad(“listing”,
    {},
    f.getSortBy() & ” ” & f.getSortdir()
    );
    }
    }

    The default values worked as soon as i treated them as a function which they are…

  4. Aidan Whitehall says:

    As much as I hate to say it, I don’t think this is a bug. (I *do* think the choice of attribute name “default” is very misleading, however.)

    http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7e0b.html
    “If no property value is set when the component is used for a web service, specifies a default value. If this attribute is present, the required attribute must be set to no or not specified. For ORM-specific usage of the default attribute, see ColdFusion ORM.”

    (Note that this ONLY refers to web service and ORM.)

    http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec0999c-7ff5.html
    “If a property has a type attribute value, ColdFusion validates the data you pass to the setter function. The default attribute has no effect on the property and does not set an initial property value.
    The validate attribute available with takes the validator to be used for validating data when implicit setter for this property is called.”

    These two bits of info (upsettingly) make it clear that not only does “default” not set the property’s value to as a default when instantiated, the values of the “type” and “validate” attributes ONLY have an effect when you use the implicit/synthesized setters to assign a value to the property… and if you don’t want public setters (which you often don’t) and so use “setter=false”, these attributes all buy you nothing 😦

Leave a reply to Aaron Neff Cancel reply