Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

best practice for cfcomponent init 1

Status
Not open for further replies.

Signit

MIS
Oct 17, 2003
114
US
I am writing a ColdFusion component for LDAP Active Directory interactions for my company. This is my first ColdFusion component and I want to ensure that I get the init (initialization) function done correctly. Essentially, I am looking for an okay that I have not violated a best practice or appropriate guideline. I have multiple networks which I will need to draw Active Directory information from. Each network has its own set of server variables (address, username etc.) so I want to specify which network I will be connecting to upon the invoking of an object of this type. I am utilizing the CreateObject method of invoking objects as I have read that it is no different than cfinvoke. At any rate, the beginning of my component is below any feedback would be greatly appreciated.

Code:
<cfcomponent displayname="LDAP Active Directory Interaction" hint="This component handles all LDAP AD transactions.">
  
  <!--- allows component to be referenced w/o specifying .init call on component invoke --->
  <!--- making <cfset computerObject = CreateObject("component", "components.ldap_ad")> valid and defaulting to tinytim --->
  <!--- to specify which network use <cfset computerObject = CreateObject("component", "components.ldap_ad").init("X")> --->
  <cfscript>
    init();
  </cfscript>

  <cffunction name="init" access="public" returntype="ldap_ad" output="false">
    
    <!--- sets default argument for network for invoke w/o .init("X") specified --->
    <cfargument name="network" type="string" default="tinytim">
    
    <cfif network eq "tinytim">
      <cfset serverAddr = "tinytim.christmas.org">
      <cfset port = "636">
      <cfset userName = "christmas\cratchitTinyTim">
      <cfset password = "fezziwig">
      <cfset secure = "CFSSL_BASIC">

      <cfelseif network eq "martha">
        <cfset serverAddr = "martha.christmas.org">
        <cfset port = "636">
        <cfset userName = "christmas\cratchitMartha">
        <cfset password = "belle">
        <cfset secure = "CFSSL_BASIC">
      
      <cfelseif network eq "bob">
        <cfset serverAddr = "bob.christmas.org">
        <cfset port = "636">
        <cfset userName = "christmas\cratchitBob">
        <cfset password = "scrooge">
        <cfset secure = "CFSSL_BASIC">
    </cfif>
    
    <!--- returns built object of type ldap_ad --->
    <cfscript>
      return this;
    </cfscript>
    
  </cffunction>

<!--- componenent methods go here --->

</cfcomponent>
 
var all of your cfc variables and scope your arguments for starters.

use <cfreturn> instead of kicking into cfscript.

if this is something used a LOT on the site, put the cfc in the application scope.

I would still not recommend hard coding a default domain name in the cfc.

If you load it in the application scope, with .init, than you can call the method anywhere later without invoking the object again and agian, but you can still pass the method arguments.

Code:
<cfif NOT structKeyExists(application,"isReady") OR structKeyExists(url,"resetapp")>

<cfset application.objThisCFC = CreateObject("component","cfcs.ThisCFC").init("dsn","network","etc")>

<cfset application.isReady = true>
	
</cfif>

then use.
application.objThisCFC.thisMethod("this","this","etc")

no reason to lock, since the variable is only written once per application timeout, and only read while being used.

 
As far as sticking the CFC in the application scope where is that typically done? On any page that I intend to invoke the cfc?
 
In the applicatio.cfc or Application.cfm

The application.isready variable will prevent it from reloading every page request, so it sits in server memory until the application scope times out or resets.

the idea of the application scope is that every template udf, tag or cfc can access it, and it is persistant. It stays in server memory for reuse.




 
This is what I have ended up with any final comments on what I have put together? What interests me about the loading of the CFC object into the application scope is that I have not been able to get any text to appear on the screen when w/in the <cfif>. I am utilizing my CFC with the following code on a seperate CFM:
Code:
<html>
  <body bgcolor="cornsilk">
    <cfif not structKeyExists(application, "isReady") or structKeyExists(url, "resetapp")>
      in cfif<br>
      <cfset application.objThisCFC = CreateObject("component","components.ldap_ad").init()>
      <cfset application.isReady = true>
    </cfif>
    <cfdump var="#application.objThisCFC.getComputerByName('DC=tinytimDC=christmas,DC=org','s860577')#">
  </body>
</html>

I want to specify the most commonly used servers and their addresses in my init(), but want the option of setting them to differnt values on the objects load. I think my CFC allows for that. Have I missed anything? The code for my CFC is below:
Code:
<cfcomponent displayname="LDAP Active Directory Interaction" hint="This component handles all NWIS LDAP AD transactions.">
  
  <!--- test for existence of variable if not exists assign default value for each --->
  <cfparam name="variables.network" default="" />
  <cfparam name="variables.serverAddr" default="" />
  <cfparam name="variables.port" type="numeric" default=0 />
  <cfparam name="variables.userName" default="" />
  <cfparam name="variables.password" default="" />
  <cfparam name="variables.secure" default="" />
  
  <cffunction name="init" access="public" returntype="ldap_ad" output="false">
    
    <!--- sets default argument for network for invoke w/o .init("network") specified --->
    <cfargument name="network" type="string" default="tinytim" />
    <cfargument name="serverAddr" type="string" default="" />
    <cfargument name="port" type="numeric" default=0 />
    <cfargument name="userName" type="string" default="" />
    <cfargument name="password" type="string" default="" />
    <cfargument name="secure" type="string" default="" />
    
    <cfif arguments.network eq "tinytim">
      <cfset variables.serverAddr = "tinytim.christmas.org" />
      <cfset variables.port = 636>
      <cfset variables.userName = "christmas\cratchitTinyTim" />
      <cfset variables.password = "fezziwig" />
      <cfset variables.secure = "CFSSL_BASIC" />

      <cfelseif arguments.network eq "martha">
        <cfset variables.serverAddr = "martha.christmas.org" />
        <cfset variables.port = 636>
        <cfset variables.userName = "christmas\cratchitMartha" />
        <cfset variables.password = "belle" />
        <cfset variables.secure = "CFSSL_BASIC" />
      
      <cfelseif arguments.network eq "bob">
        <cfset variables.serverAddr = "bob.christmas.org" />
        <cfset variables.port = 636>
        <cfset variables.userName = "christmas\cratchitBob" />
        <cfset variables.password = "scrooge" />
        <cfset variables.secure = "CFSSL_BASIC" />
    </cfif>
    
    <!--- returns built object of type ldap_ad --->
    <cfreturn this>
    
  </cffunction>
  
  <cffunction name="getComputerByName" returnType="query" access="public"
     displayname="Get AD Info By Computer Name"
     hint="Returns a machines AD entry based on its name">
    <cfargument name="start" type="string" required="true">
    <cfargument name="filter" type="string" default="*">
    
    <cfset results = "">
    
    <cfldap
       <!--- connection attributes set by init --->
       server="#variables.serverAddr#"
	   port="#variables.port#"
	   username="#variables.userName#"
	   password="#variables.password#"
       secure="#variables.secure#"
       
       <!--- result set name --->
	   name="results"
       
       <!--- ad interaction attributes --->
       action="query"
       scope="subtree"
	   attributes="canonicalName,CN,DN,name,objectClass"
       start="#arguments.start#"
	   filter="(CN=#arguments.filter#)">
    <cfreturn results>
  </cffunction>
  
  <cffunction name="addComputer" returntype="boolean" access="public"
     displayname="Add machine to AD"
     hint="Returns true or false based on success of adding machine">
    <cfargument name="cn" type="string" required="true">
    <cfargument name="ou" type="string" required="true">
    <cfargument name="objectClass" type="string" required="true">
    <cfargument name="dn" type="string" default="CN=#arguments.cn#,#arguments.ou#,#dcString#">
    
    <cftry>
      <cfldap
         <!--- connection attributes set by init --->
         server="#variables.serverAddr#"
	     port="#variables.port#"
	     username="#variables.userName#"
	     password="#variables.password#"
         secure="#variables.secure#"
       
         <!--- ad interaction attributes --->
         action="add"
         attributes="objectClass=#arguments.objectClass#"
         dn="#dn#">
      <cfcatch>
        <cfreturn false>
      </cfcatch>
    </cftry>
    <cfreturn true>
  </cffunction>

</cfcomponent>

Thank you for all of your help and I apologize for my novice questions. :)
 
try to find some resources on the talk more about cfcs and best practices. macromedia has the cfmx developers guide which is free, and there are a lot of good discusions and articles that go into more depth on this.


for starter, this

Code:
<cfif not structKeyExists(application, "isReady") or structKeyExists(url, "resetapp")>
      in cfif<br>
      <cfset application.objThisCFC = CreateObject("component","components.ldap_ad").init()>
      <cfset application.isReady = true>
    </cfif>

should be in the Application.cfm or application.cfc
 
Right, I actually realized what you meant after I posted my last message. Amazing what you figure out on the way from your desk to your car. I will readup and post some more if I still have questions. Thank you for your help!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top