Accessibility
 
Home / Developer Center / ColdFusion Developer Center

ColdFusion Article

Icon or Spacer Icon or Spacer Icon or Spacer
Anthony McClure
Anthony McClure
RemoteSite Technologies
 
CFC Best Practices: Component Functions and Function Invocation


Macromedia ColdFusion MX and the introduction of ColdFusion Components (CFCs) add an exciting new paradigm for the architecture and development of applications.

Through this new paradigm, the engineers at Macromedia have provided developers a consistent programming methodology for creating MVC (model view controller) based applications.


To better understand the importance of this new feature to the language and how CFCs fit into the overall application development architecture, read Ben Elmore's white paper, ColdFusion MX Components: A New Methodology for Building Applications (PDF 770K). This white paper details all of the various features of CFCs and presents a basic methodology for their usage in application development.

This article takes a closer look at an actual CFC in order to understand the basic programmatic structures of CFC Functions and their invocation methods. As one of the more powerful features of CFCs, functions provide a way for developers to call specific sections of ColdFusion code through a variety of invocation methods (direct code invocation with the cfinvoke tag, URL parameters, form posting, Macromedia Flash Remoting, Flash ActionScript, cfscript . Also, Web Services optionally pass arguments to CFCs, and receive return responses from CFCs.

To illustrate CFC Function invocation, this article steps through a familiar example for developers. It is necessary to understand not only the logical reasons for using a CFC (instead of a Custom Tag, for example), but also to show an actual working code example of a CFC to learn from.

The problem for consideration: A basic security model
For our example, consider a problem that most developers face on an ongoing basis, the "basic security model." Nearly all applications that secure data in one form or another require a security model to be in place. That security model may be as simple as a username and password check. A much more advanced security model could have a multiple level, cascading, roles-based model with inherited access permissions.

This article is not a discourse on security implementations, but it's important that a developer first understands the problem in order to figure out a suitable solution.

In most cases, security models must provide the following:

1
Authentication—This is the most basic requirement. Ensure that an individual user is who they say they are. This is handled by comparing username and password provided by the user (through a form, for instance), against a listing of usernames and passwords in a system (generally through a database lookup).
2
Authorization—Once a user is authenticated, and the user is identified in the system, you'll often need to know if the user has access to a specific function of the system that he or she may request. For example, a general "site" user should not be allowed to access the site's administration functions. Authorization is handled by assigning the user to "security groups" and then checking that user's security group assignment against an access list of acceptable groups for that particular function in your application. For instance, the general user may be assigned to the security group, "site users," but the administration area of your application may require a user to be in the security group, "administrators," to gain access to the area. Therefore, since the user is assigned to the "site users" group, he cannot gain access to the administration area.

Since the problem is clear, you can generate a solution. First, look at your database to create a security model. The database is comprised of three tables: Security, Groups, and Security_Groups.

1
Security—This table holds the username and password information. Notice that there is a userID as well. This ID is a foreign key for the specific user information stored in a separate system table that is dependent on the particular application.
2
Groups—This table contains the name and ID of the various security groups.
3
Security_Groups—This table is a many-to-many lookup table and contains the usernames and groupIDs for users. In this way, users can be affiliated with more than one group.

Database schema


Note:
You can download the ZIP file at the end of this article to view the database table.

The solution
The problem has been defined, and a database has been created. At this point, it's up to the developer to design a code solution around the database presented.

Keep in mind, in ColdFusion 5, the best solution to the problem would be to create custom tags to manage the authentication and authorization functions. You might have created one custom tag to accept a username and password provided by code. It would return a result to the "caller" variable scope with the userID if the match was successful, or a "no results found" result if the match was unsuccessful.

You might have created a second tag could that could accept a list of accepted Security Groups for the function requested and the username of the user. It would return a Boolean result to a "caller" variable scope if the user is assigned to one of the groups in the list.

This solution works well and is an accepted way of coding this problem prior to CFCs. But what if you needed to access this functionality through a Flash Movie, or wanted to provide access to the authentication and authorization functions through a web service, or needed to add additional security functions?

With the custom tag solution, you would create additional ColdFusion pages to handle the different ways of access and functionality. Also note that although these two functions are both considered security functionality, they are actually two independent ColdFusion pages. If the security database ever changed, you would need to search and replace all data source references within security templates throughout the application.

None of these issues are new of course, but with the advent of CFCs, these issues are easily solved!

The CFC solution
Since you can invoke CFCs in multiple ways, contain many functions in one CFC, and generate the required information for use as a web service, it is easy to see that the CFC is a far better alternative to multiple custom tags

But how does it all come together?

It's simple. You create CFCs with ColdFusion tags, just like all other CFML applications. The new tags explained below include everything you need to create a fully implemented CFC. The new tags are as follows:


the cfcomponent tag
the cffunction tag
the cfargument tag
the cfreturn tag
the cfinvoke tag

It all starts with the cfcomponent tag. This tag surrounds the entire page and identifies the code as being a CFC. 


   <cfcomponent>	
       .
       .
       .
   </cfcomponent>

Inside of the cfcomponent tags, our core functions are identified and coded. As discussed above, we need two functions for our CFC, Authentication and Authorization. These functions are defined within the CFC with the cffunction tag. This tag also has an opening and closing tag surrounding all code to take place when the function is called.


     <cfcomponent>	
       <cffunction>
		.
		.
		.
       </cffunction>
     </cfcomponent>

This cffunction tag contains several important attributes that need to be defined for the function to work properly when called. Take, for example, the code for our first function "Authenticate":

<cffunction name="authenticate" access="public" output="false">

This cffunction tag contains three attributes:


name="authenticate"—This attribute defines the name of the function or the component method that will be used when invoking this function.
access="public"—CFC functions have two different security options available to them. The first is the "access" level attribute, and is shown here. The access level determines where the function can be executed. For this example, the access level is public, which means that it can be called from all other ColdFusion pages and CFCs. The other security attribute is "roles," a group security scheme that is beyond the scope of this article. For more information, see the ColdFusion MX documentation and CFML Reference manual.
output="false"—This argument tells the CFC that the code is for execution only and does not produce HTML. This is the preferred way of using CFCs. That is, to provide method-based functionality for your application, and not end-user display. In MVC architecture, CFCs act as the conduit for data and business logic access.


At this point, you have now built a functional CFC. Not much interesting would happen when it is called, however, but the CFC is operational.

To authenticate a user, pass in data to the CFC. This is done through arguments in a similar manner to custom tags. In addition, you must also identify those arguments within the CFC functions themselves. This is done with the cfargument tag.


     <cfcomponent>	
         <cffunction>
		   <cfargument name="arg1"/>
		   <cfargument name="arg2"/>
		   <cfargument name="arg3"/>
	     </cffunction>
     </cfcomponent>
To authenticate a user, provide the CFC with two arguments: a user and a passwd. These arguments should both be required and have a data type of "string." Within the cffunction tag, the cfargument tag would be as follows:

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

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

The attributes for the cfargument tag define each argument's purpose. There are four attributes you can use, as follows:


name—The name of the argument to pass in.

type—The data type for the argument. If another data type is passed other than that which is listed in this attribute, an exception is thrown.

required—Determines whether the parameter is required to execute the component method.
default—A type; if no argument is passed, specifies a default argument value similar to the cfparam tag. If this attribute is present, the required attribute must be set to "false" or not specified.

Any values passed into the CFC are accessible through a new variable scope called "arguments." This scope functions similarly to the custom tag "attributes" scope. For example, to access the value of the user argument as defined above, the code would be as follows:

arguments.user

Once the component is built to this point, you can write the execution logic. The following is the completed CFC including the function for authentication (this code is included in the accompanying CFC security.cfc included with the ZIP file at the end of this article):


     <cfcomponent>	
         <cffunction name="authenticate" access="public" output="false">
		   <cfargument name="user" type="string" required="true"/>
		   <cfargument name="passwd" type="string" required="true"/>

		   <cfquery name="checkAuthentication" datasource="SecurityDB">
			SELECT username
			FROM Security
			WHERE username = (#arguments.user#)
			AND password = (#arguments.passwd#)
		  </cfquery>
	  </cffunction>
     </cfcomponent>

There is still one remaining issue: no results were delivered to the invoker. In a ColdFusion custom tag, the result is passed to a calling ColdFusion page with the "caller" scope. This was problematic if you tried to call the custom tag from outside of ColdFusion Server. Luckily, CFCs provide a simple way to return values, regardless of the calling process. This is accomplished with the cfreturn tag.

The cfreturn tag has a simple signature:

<cfreturn expression />

In the following example, the code is complete and includes a cfreturn tag that checks to see if a record was returned. If it is true, and the username and password match the data in the system, the CFC returns the username to the caller for future use. If it is false, then a Boolean false result is returned. The following example demonstrates this logic:


     <cfcomponent>	
         <cffunction name="authenticate" access="public" output="false">
		    <cfargument name="user" type="string" required="true"/>
		    <cfargument name="passwd" type="string" required="true"/>

		    <cfquery name="checkAuthentication" datasource="SecurityDB">
			  SELECT username
			  FROM Security
			  WHERE username = (#arguments.user#)
			  AND password = (#arguments.passwd#)
		    </cfquery>

		    <cfif checkAuthentication.recordCount>
			   <cfreturn checkAuthentication.user/>
		    <cfelse>
			   <cfreturn false/>
		    </cfif>
	     </cffunction>
     </cfcomponent>

Now that the first function is complete, it's time to add the second function for authorization. The following is a complete CFC that includes the function for authorization:


     <cfcomponent>	
          <cffunction name="authenticate" access="public" output="false">
		     É
	       </cffunction>

	       <cffunction access="public" name="authorize" output="false">
            <cfargument name="user" type="string" required="true"/>
            <cfargument name="lAcceptedGroupIDs" type="string" required="true"/>
		
	       <cfquery name="getUserGroups" datasource="SecurityDB">
			  SELECT groupID
			  FROM Security_Groups
			  WHERE username = '#arguments.user#'
	       </cfquery>
		
    <!--- use a query of query to determine if group IDs for user are in list --->
           <cfquery name="checkGroups" dbtype="query">
			  SELECT groupID
			  FROM getUserGroups
			  WHERE groupID IN (#arguments.lAcceptedGroupIDs#)
	        </cfquery>
		
	        <cfif checkGroups.recordCount>
			  <cfreturn true/>
	        <cfelse>
			  <cfreturn false/>
	        </cfif>
	     </cffunction>
 </cfcomponent>

Invoking the CFC
Invoking a CFC can happen in many ways. This feature alone makes CFCs a far more powerful solution to the problem at hand than what a custom tag could provide. This one page of code can be used throughout not only this application, but also any other ColdFusion application, exposed as a web service, called from a Macromedia Flash movie, and so forth, with very little or no changes in code!

The two most common ways to invoke a CFC function are through the cfinvoke tag and inside of a cfscript block (something not possible in ColdFusion 5 with custom tags), using the createObject() ColdFusion function.

Using the cfinvoke tag
The cfinvoke tag provides a simple CFML based solution to executing a CFC function. For instance, if we wanted to call the authenticate function by submitting a form with username and password form variables, the cfinvoke tag would look something similar to the following:

     <cfinvoke 
	 component="security" 
	 method="authenticate" 
	 returnVariable="authenticated" 
	 user="#form.username#" 
	 passwd="#form.password#"
     >

Note: This code is in the accompanying ColdFusion file, index.cfm, starting at line 34. It is included in the ZIP file at the end of this article.

You can place this code block in any ColdFusion application on your ColdFusion server to execute the security authenticate function (or method). It returns a local variable called "authenticated" that your application logic can manipulate in any way appropriate to the particular application. That's all there is to it.

The attributes for this cfinvoke tag are as follows:


component="security"—This attribute specifies the name of the component to execute. In this case, the component name is "security" and corresponds to the CFC filename, security.cfc. Save all CFCs with a CFC extension (example, security.cfc) and place them in an accessible location for ColdFusion MX. You can place them outside of your webroot, but you will need to add a web server mapping. Additional rules apply to CFCs in directory structures, called "packages," that will be addressed in future articles. This is required if the "method" attribute is not specified.
method="authenticate"—This is the name of the method (or function) within a component (or CFC file). For a web service, it is the name of an operation. This is required if the "component" attribute is not specified.
returnVariable="authenticated"—Specify the name of a variable for the invocation result. For this call, either the username of a properly authenticated user, or "0" is returned as the value for this variable. See the index.cfm file that accompanies this article (in the ZIP archive) for more information on using this code.
arguments as defined in the CFC—These are the name-value pairs for the arguments defined by the cfargument tags in the function. Note that this is not the only way to pass arguments to a CFC with the cfinvoke tag. You can also use the "argumentCollection" attribute, which holds a structure of name/value pairs. This is useful when you need to supply a large amount of arguments.


Using the cfscript tag and the createObject() function

The ability to call CFCs with the cfscript tag is a wonderful addition to ColdFusion MX, and the best part about it: it is easy to use. Using a ColdFusion function called createObject(), places an instance of the CFC into a variable. From that variable, you can call the functions by using programmatic dot notation. Take a look at the following code sample (line 45 in the index.cfm file, in the ZIP available at the end of this article):


     <cfscript>
	    objSecurity = createObject("component","security");
	    bAuthorized = objSecurity.authorize(form.user,form.groupID);
     </cfscript>

This code calls the authorize function with two lines of code.

First, it creates a "component object" called "objSecurity" by setting the "objSecurity" variable equal to the createObject ColdFusion function. This function takes two arguments. The first argument tells the function that a component object will be created. The second argument names the component to use. In this case, the security.cfc file is used.

Next, it creates and initializes a local variable called "bAuthorized" to the return value of the authorization security function call. By using programmatic dot notation (such as objectName.functionName(arguments)), the code executes the function. If you instead wanted to call the authenticate method, the code would be as follows: objSecurity.authenticate(arg1,arg2).

As with the cfinvoke tag, you can call a function and pass arguments in a cfscript tag block in multiple ways as well. See the ColdFusion MX documentation for more information on passing arguments.

Other methods
As touched upon throughout the article, you can call CFCs in other ways: through a URL, from a form post, as a web service, and through Flash Remoting (with ColdFusion MX and Macromedia Flash MX, within a Macromedia Flash movie). Read more about these other methods in the ColdFusion Developer Center.

How does this work?
To enable a CFC for execution through an external source (such as a URL, form post, Flash Remoting, and so forth), modify one slight code attribute. Change the access attribute of the cffunction tag to remote="access". That's it!

Creating a web service is a little more involved, but CFCs come to the rescue here as well. All CFCs contain metadata that describe their functions. With this metadata information, the WSDL file (an XML document used to describe an exposed web service) can be auto-generated! In fact, a method exists for all CFCs (called "cfcToWSDL") that will generate the file for you.

These methods are covered in other tutorials, articles, sample applications, and white papers in the ColdFusion Developer Center, and will continue to be discussed in future articles. Also refer to the ColdFusion MX documentation and the sample applications in your ColdFusion MX administrator.

Download the sample files
You can experiment with this ColdFusion MX component by downloading the sample files below:


1
Download the ZIP file. 
 
Download the components CFCSecurity.zip (15 KB)
2
Extract the files to your ColdFusion MX webroot.
3
Browse index.cfm from your browser. For example, browse the following URL in a browser: http://localhost/securitycfc/index.cfm. Change this URL based on your web server configuration.
4
Test the authenticate functionality.
5
Test the authorize functionality

Conclusion
CFCs have created a new paradigm for the architecture and development of ColdFusion MX applications.

CFCs provide all of the following:


1
A consistent model for the creation of MVC based component architectures.
2
The ability to work with sets of functionality in one template.
3
A simple, yet powerful syntax for function creation.
4

A multitude of ways to invoke functions created including:

a
The cfinvoke tag.
b
Between the cfscript tag blocks and the createObject() ColdFusion function
c
direct URL
d
form post
e
Macromedia Flash movies through Macromedia Flash MX and Flash Remoting
f
as a web service (with auto-generating WSDL)


By implementing the downloadable test case for this simple security model as a CFC, and comparing this new way to the challenges of doing the same functionality with custom tags, it is clear that CFCs are indeed a more powerful and elegant solution. The CFC is a welcome addition to any developer's toolset when creating ColdFusion MX applications.


About the author
Anthony McClure is a Senior Technologist with RemoteSite Technologies Inc., out of Austin, TX. He is a long time developer with over 8 years of experience in all aspects of development from Mainframe to Internet. As a Macromedia Certified Instructor and Advanced ColdFusion Certified Developer, Anthony has distinguished himself within the ColdFusion development platform. He is an active member of the ColdFusion community speaking at Macromedia ColdFusion User Groups, leading technology seminars, and generally pushing Macromedia technology amoung his peers. Other publications by Anthony include a Macromedia Developer Center article for Macromedia Spectra and wireless technology, and an upcoming book on dynamic publishing using the Macromedia ColdFusion MX platform.