CFOBJECT and COM
As we have already seen, ColdFusion enables us to work with a variety of Java objects and components, but that's not all we are limited to. ColdFusion gives you access to COM/DCOM
A Little About COM and DCOMCOM is Microsoft's attempt at building robust, portable, and reusable components with their Distributed Component Object Model distributable components, much like JavaBeans or Enterprise JavaBeans.
COM and DCOM are powerful
Note To find out more about COM, go to www.microsoft.com/com. In addition, look at www.cfcomet.com, which is a web site totally devoted to working with COM objects from ColdFusion. It's a great resource! Working with COM Objects and ColdFusion
You can call a COM object that resides either on your local machine or
C:\> regsvr32 someobject.dll If a COM object has been registered on your machine, you can access it from CFOBJECT using this syntax: <cfobject type="com" name="name" action="action" class="progID" context="context" server="your server name" When you connect to a COM component, you need to set the CFOBJECT type attribute to COM . The name attribute is a reference variable and is also required. It is needed, as are other CFOBJECT calls, to provide a pointer to an object's attributes and methods. class is a required attribute and points to the COM component's program ID for the object you want to invoke. You might have trouble finding the program ID, and if so, you should check the documentation for that component, which provides you with a list of its methods as well as the ProgramID. You can also use the OLE/COM Object Viewer that comes with Visual Studio or you can download it from www.microsoft.com/com/resources/oleview.asp.
The
The context attribute is an optional attribute that enables you to specify the context under which your object is running. Table 16.1 provides the various contexts. Table 16.1. Context Attribute Values
The final attribute needed to call COM objects from CFOBJECT is server , which is required if the context attribute is set to remote . server simply specifics a valid server. Properties and MethodsAny object has a series of methods and properties that you need to set and use. To set a property of a COM object, you only need to use the CFSET tag: <cfset someobject.someproperty = "somevalue"> You can also access or get a property's value by doing this: <cfset getProperty = someobject.someproperty> To invoke a method with no arguments is just as simple: <cfset variablename = someobject.somemethod()> Methods that require arguments need to have those arguments passed by value: <cfset somevar = 4> <cfset anothervar = someobject.somemethod (somevar, someOutput) You can also pass arguments by reference. Arguments passed by reference have their values modified by the COM object variable on the calling page, so the calling page can use the resulting value. To pass a variable by reference, surround the name of an existing ColdFusion variable with quotation marks. If the argument is a numeric type, assign the variable a valid number before you make the call. For example: <cfset somestring="Print PI"> <cfset somenumeric=0> <cfset result=myCOMObject.calculate(somestring, " somenumeric ")> The string "Print PI" is passed to the object's calculate method as an input argument. The value of somenumeric is set by the method to a numeric value.
Let's look at a real example. Let's
Listing 16.9 mailmerge.cfm
<cfquery name="getCustomers" datasource="ICF" dbtype="ODBC">
SELECT Customer.CustomerID, Customer.CustomerFirstName, Customer.CustomerLastName,
Customer.CustomerAddress, Customer.CustomerCity, Customer.CustomerStateID,
Customer.CustomerZip, Customer.CustomerPhone, Customer.CustomerEmail,
Customer.CustomerPassword, Customer.CustomerNotification
FROM Customer, State
</cfquery>
<cftry>
<!--- If it exists, connect to it --->
<cfobject
action="Connect"
class="Word.Application"
name="objWord"
type="COM">
<cfcatch>
<!--- The object doesn't exist, so create it --->
<cftry>
<cfobject
action="create"
class="Word.Application"
name="objWord"
type="COM">
<cfcatch type="ANY">
<cfabort showerror="<FONT COLOR='RED'>Cannot create Word Object<BR>Make sure Word
is installed and that ColdFusion has permissions to use the Word COM
objects</FONT><BR><B>Error Details:</B> #CFCATCH.MESSAGE#">
</cfcatch>
</cftry>
</cfcatch>
</cftry>
<cfscript>
/* This will open Word if running locally */
objWord.Visible = true;
/* This returns the 'Documents' collection the Word Object */
objDoc = objWord.Documents;
/* Create a new document */
newDoc = objDoc.Add();
</cfscript>
<cfset strLoc = Application.DrivePath & "\temp\worddata.doc">
<!--- Delete file --->
<cfif FileExists('#Application.DrivePath#temp\worddata.doc')>
<cftry>
<cffile action="DELETE" FILE='#Application.DrivePath#temp\Worddata.doc'>
<cfcatch TYPE="Any">
</cfcatch>
</cftry>
</cfif>
<cfscript>
/* Save the document to a location */
newDoc.SaveAs(strLoc);
/* We specify the range of '0' -- start at the beginning of the document */
docRange = newDoc.Range(0);
</cfscript>
<cfset strtemp = "">
<!--- Loop through the query --->
<cfloop query="getCustomers">
<cfset i = getCustomers.CurrentRow>
<cfset strtemp = strtemp & "#CustomerID#" & ",">
<cfset strtemp = strtemp & "#CustomerFirstName#" & ",">
<cfset strtemp = strtemp & "#CustomerLastName#" & Chr(13) & Chr(10)>
</cfloop>
<cfscript>
/* Add text to the range */
docRange.Text = strtemp;
/* Save the changes */
newDoc.Save();
/* Print document
objWord.ActivePrinter = "HP LaserJet 6L on NE01:";
objWord.PrintOut();*/
/* Close the document */
newDoc.Close();
/* Quit Word */
objWord.Quit();
</cfscript>
Although this looks like a complicated template, it's really not. We connect to the Word object by specifying the class name "Word.Application" . Then we use a try-catch statement to see whether an instance of the object already exists and, if so, to connect to it. If not, we create an instance of it. We then simply use the Word document's COM objects to add text to the created Word document.
Note Before you get excited about automating your Office applications through ColdFusion and CFOBJECT , make sure to go to http://support.microsoft.com/default.aspx?scid=kb;EN-US;q257757. There you can read about some pitfalls and Microsoft's official view of automating Office applications. Best Practices When Using COM Objects
Although using
CFOBJECT
and COM to create rich ColdFusion applications is easy, it is also easy to get yourself in trouble if you do not consider what you are doing. One of the main issues with calling COM objects from ColdFusion is improper threading. You must make sure that your COM object is thread-safe. If you do not, you might experience major issues under load and bring your server to its knees. An object is thread-safe if it can be called from many programming threads
Visual Basic ActiveX DLLs are typically not thread-safe. If you use such a DLL in ColdFusion, you can make it thread-safe by using the OLE/COM Object Viewer to change the object's threading model to the Apartment model.
If you are planning on storing a reference to the COM object in the application, session, or server scope, do not use the Apartment model. This threading model is intended to service only a single request. If your application requires you to store the object in any of these scopes, keep the object in the Both model, and lock all code that
Summary
In this section, you have learned how to work with COM objects through
CFOBJECT
. You are provided with an invaluable tool to extend or
It's important to note that although it is very simple and easy to work with COM from ColdFusion, there are risks and you need to read all the documentation on your COM object. You need to make sure it is thread-safe, or you must force it to be thread-safe through the OLE Object View application. Then you must rigorously test it before you use it in production. |