11 Replies Latest reply on Nov 1, 2013 10:36 AM by Aegis Kleais

    Component properties don't exist anymore.

    Aegis Kleais Level 3

      I have an component called: Event.cfc

       

      Long story short, I init() it by issuing a command like:

       

      <cfset eventObject = new 'com.Event'() />

       

      This component has 2 properties: data (a structure) and name (a string).

       

      The init() method calls a private method:

       

      <cfset VARIABLES.setName( VARIABLES.getAttribute( 'event' ) ) />

       

      The setName() method is implicit, ColdFusion builds it based on the name attribute.  I manually created the getAttribute() method which works with the data property.  In the getAttribute() method, I have a command that reads:

       

      <cfset LOCAL.retVar = VARIABLES.data[ ARGUMENTS.attributeName ] />

       

      Well, CF keeps saying that 'data' does not exist in VARIABLES.  But I thought that properties that were defined in a component were put into the VARIABLES scope.  So how can this variable NOT exist when I have it defined at the top of the Event.cfc component as a <cfproperty>?

        • 1. Re: Component properties don't exist anymore.
          Carl Von Stetten Adobe Community Professional & MVP

          Can you post the entire actual code of the Event.cfc component?

          -Carl V.

          • 2. Re: Component properties don't exist anymore.
            Aegis Kleais Level 3

            <!---

             

             

             

                      <!--- ***************************************************************************************** ************************** --->

                      <!--- ***************************************************************************************** ************************** --->

             

             

             

             

                      Name:                     Event object component.

                      File:                              Event.cfc

                      Desc:                              Handles View-initiated Event objects.

                      Version:          1.0.0 (2013-10-10T12:00:00-0500)

             

                      Todo:                              [none]

             

             

                      <!--- ***************************************************************************************** ************************** --->

                      <!--- ***************************************************************************************** ************************** --->

             

             

             

             

            --->

             

             

             

             

            <cfcomponent

                      output                     = "false"

                      accessors          = "true">

             

             

             

             

                      <!--- ========================================================================================= ========================== --->

                      <!--- ========================================================================================= ========================== --->

             

             

             

             

                      <!--- Component methods (explicit):

             

             

             

                                                    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::

             

             

                                                    Component methods (implicit):

             

             

                                                    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::

             

             

                                                    Component properties:

             

             

                                                    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::

             

             

                                                    Private variables:

             

             

             

                                                    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::

             

             

             

             

                                                    Public variables:

             

             

             

             

                                                    --->

             

             

             

                      <!--- ========================================================================================= ========================== --->

                      <!--- ========================================================================================= ========================== --->

             

             

             

             

                      <!--- Component properties: --->

             

                      <cfproperty

                                required          = "true"

                                type                              = "struct"

                                name                              = "data"

                                getter                    = "false"

                                setter                    = "false" />

             

             

                      <cfproperty

                                required          = "true"

                                type                              = "string"

                                name                              = "name" />

             

             

             

             

                      <!--- ========================================================================================= ========================== --->

                      <!--- ========================================================================================= ========================== --->

             

             

             

             

                      <!---          Method: init(). --->

             

                      <cffunction

                                access                              = "public"

                                returntype          = "Event"

                                name                                        = "init"

                                output                              = "false">

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!--- Arguments. --->

             

                                <cfargument

                                          required          = "true"

                                          type                              = "struct"

                                          name                              = "constructorData"

                                          default                    = "#{ 'event' = '' }#" />

             

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!--- Set LOCAL variables: --->

             

             

                                <cfset LOCAL.attributeName = '' />

             

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

                                <!--- Set instance variables: --->

             

                                <cfset VARIABLES.setName( VARIABLES.getAttribute( 'event' ) ) />

             

             

                                <cfif structCount( ARGUMENTS.constructorData )>

             

                                          <cfloop collection="#ARGUMENTS.constructorData#" item="LOCAL.attributeName">

                                                    <cfset VARIABLES.setAttribute( LOCAL.attributeName, ARGUMENTS.constructorData[ LOCAL.attributeName ] ) />

                                          </cfloop>

             

                                </cfif>

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!---          Return.          --->

             

                                <cfreturn THIS />

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                      </cffunction>

             

             

             

             

                      <!--- ========================================================================================= ========================== --->

                      <!--- ========================================================================================= ========================== --->

             

             

             

             

                      <!---          Method: getAttribute(). --->

             

                      <cffunction

                                access                              = "private"

                                returntype          = "any"

                                name                                        = "getAttribute"

                                output                              = "false">

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!--- Arguments. --->

             

                                <cfargument

                                          required          = "true"

                                          type                              = "string"

                                          name                              = "attributeName" />

             

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!--- Set LOCAL variables: --->

             

                                <cfset LOCAL.retVar = '' />

             

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

                                <!--- Capture the attribute value: --->

             

                                <cfset LOCAL.retVar = VARIABLES.data[ ARGUMENTS.attributeName ] />

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!---          Return.          --->

             

                                <cfreturn LOCAL.retVar />

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                      </cffunction>

             

             

             

             

                      <!--- ========================================================================================= ========================== --->

                      <!--- ========================================================================================= ========================== --->

             

             

             

             

                      <!---          Method: setAttribute(). --->

             

                      <cffunction

                                access                              = "private"

                                returntype          = "void"

                                name                                        = "setAttribute"

                                output                              = "false">

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!--- Arguments. --->

             

                                <cfargument

                                          required          = "true"

                                          type                              = "string"

                                          name                              = "attributeName" />

             

             

                                <cfargument

                                          required          = "true"

                                          type                              = "any"

                                          name                              = "attributeValue" />

             

             

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

                                <!--- Store the attribute value: --->

             

             

                                <cfset structInsert( VARIABLES.data, ARGUMENTS.attributeName, ARGUMENTS.attributeValue, true ) />

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                                <!---          Return.          --->

             

                                <cfreturn />

             

             

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

                                <!--- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::: --->

             

             

             

             

                      </cffunction>

             

             

             

             

                      <!--- ========================================================================================= ========================== --->

                      <!--- ========================================================================================= ========================== --->

             

             

            </cfcomponent>

            • 3. Re: Component properties don't exist anymore.
              Carl Von Stetten Adobe Community Professional & MVP

              I'm chewing through the code.  Next time, please don't post all that whitespace (it looks like a Ben Nadel blog post sample).   Just as a suggestion, you might want to take a look at the ColdBox CFML Standards and Best Practices guide as a way to make code a bit more readable for yourself and others.  I found it to be pretty good.

               

              Anyway, I'll get back to you in a bit if I can figure something out.

               

              -Carl V.

              • 4. Re: Component properties don't exist anymore.
                Carl Von Stetten Adobe Community Professional & MVP

                Aegis,


                What version of CF are you using?

                 

                -Carl V.

                • 5. Re: Component properties don't exist anymore.
                  Aegis Kleais Level 3

                  ColdFusion 10 Developer.

                   

                  And sorry about that.  I should have killed the whitespace.  I like my code having "breathing room" and only related "clumps" of code stick close together.

                  • 6. Re: Component properties don't exist anymore.
                    Carl Von Stetten Adobe Community Professional & MVP

                    Aegis,

                     

                    From the new CF10 docs it looks like <cfproperty> doesn't quite work like you thought:


                    Usage

                    You must position cfproperty tags at the beginning of a component, above executable code and function definitions. If a component is not used as a web service,  only provides metadata information of the property. It does not define variables or set values that you can use in your component. However, it creates implicit setters and getters for the property in the CFC depending on whether getter/setter attributes are enabled.

                     

                    Notice the part I italicized - it does not define the variables.  You'll need to add a pseudo-constructor to create the variables before the init() method.

                     

                    Not necessarily related, but something I noticed.  In your init() method you have this:

                     

                    <cfset VARIABLES.setName( VARIABLES.getAttribute( 'event' ) ) />

                     

                    On a newly created object, the data variable will be empty so calling your getAttribute() method won't return anything (and may error since there won't be an 'event' struct key inside the 'data' variable).

                     

                    Also, on methods inside your component, you don't need to call them with the "VARIABLES." scope prefix.

                     

                    -Carl V.

                    • 7. Re: Component properties don't exist anymore.
                      Aegis Kleais Level 3

                      Wow.  I can't believe I had been coding and things were working (by haphazzard chance it would seem) up til now, but that's a great piece of info.

                       

                      So I'll need to explicitly set VARIABLES in the component's pseudo constructor eh?  OK, That should be doable. 

                       

                      As for the setName() being called on the getAttribute(), I think I flubbed up.  I need to perform the setAttribute loop FIRST, and then once the attributes are set, THEN run that line of code, and it will get the 'event' attribute from the data structure and use it for the event Name.  Good catch Carl!

                       

                      Sorry if all the scoping is unnecessary.  I sometimes scope heavily as a previous belief that it is a good practice.  I guess I can keep the variables scoped, but leave off the scope for method calls.  Makes sense.

                       

                      I'm also reading up on that coding standards documentation you linked me to.  Carl, you are a freaking wealth of good information.  You ever drop down my neck of the woods, I owe ya a steak dinner and drinks.  Much appreciated!

                      • 8. Re: Component properties don't exist anymore.
                        Aegis Kleais Level 3

                        One area that Naming Convention website hits on is that it talks about storing my instance-based variables in 'variables.instance', a structure that I create in the 'init()' method.

                         

                        My only problem with doing this is, if I understand it correctly, this means I cannot use CF's implicit getters and setters.  Because as I understand it, if you set 'accessors="true"' on the component, and you have a property, say:

                         

                        <cfproperty required="true" type="string" name="age" />

                         

                        Then CF will create a getAge() and setAge() method, but the problem is that it references 'variables.age' and not 'variables.instance.age'.  This would mean I would have to manually create the accessor and mutator methods if I use 'variables.instance'.

                         

                        ...And on a sidenote, I really wish CF would allow me to specify the access property on implicit getter/setters.  I think it defaults them to public, but there are many times I'd love to make a read-only bean, and set the setter's access to private, but again, unless I manually code it, I don't think I can do that.  Maybe CF11?

                        • 9. Re: Component properties don't exist anymore.
                          Aegis Kleais Level 3

                          On an ADDITIONAL sidenote, I'm seeing an odd problem here.  My directory structure is as follows:

                           

                          (site root)/www/com/domain/fw/Event.cfc

                           

                          As you can see, the first subdirectory off my site root is 'www', well in my site root I have folders which all map to different subdomains.  (this maps to 'www.domain.com')  The problem here is that the "returnType" for these objects is:

                           

                          www.com.domain.fw.Event

                           

                          It seems I have to hardcode this value into these CFC's because putting a variable in there is not allowed.  So if I had another folder at root, let's say, called 'clients', and it was running a separate application off the same framework, I'd have to go to every CFC and change 'www.com.domain.fw.Event' to 'clients.com.domain.fw.Event'.

                           

                          I'd love to find a dynamic way to do that.

                          • 10. Re: Component properties don't exist anymore.
                            Carl Von Stetten Adobe Community Professional & MVP

                            How about adding a mapping to one of those folders in your chain (maybe 'fw')?  I'm not sure, but I think you can dynamically build the mapping based on the current context.  Then you could refer to the objects as "fw.Event" instead.  Do you have separate application.cfc files in each site?

                             

                            I gotta dash for a bit, I'll circle back when I get back in the office.

                            -Carl V.

                            • 11. Re: Component properties don't exist anymore.
                              Aegis Kleais Level 3

                              To this point I had always assumed CF per-application mappings were for just file/folder pathing, and did not equate it to the fully qualified dot-notation that CFCs use.  I don't see why that shouldn't work.  Great idea!  That way I can keep the CFCs in the framework specifying a package that is: [mapping].path.to.object.

                               

                              As for separate application.cfc files, well, it all depends if I'm hosting a separate app on a separate subdomain.

                               

                              For example:

                               

                              www.domain.com runs off of /[siteroot]/www/  -> It uses an application

                              cdn.domain.com runs off of /[siteroot]/cdn/  -> Since it just hosts files, there IS an application.cfc in there, but it's a "nullifyer application.cfc" designed to just prevent CF from traversing up out of the subdomain folder and hitting another application.cfc.

                               

                              And take your time, Carl.  I'm extremely appreciative that you're helping me understand this and have provided such great solutions.  It really shows me how much more "out of the box" I need to think when taking on these problems.  I sincerely appreciate your time!