Status and request-handling CFC

The following CFC handles all IM events, except onIncomingMessage. It maintains an Application scope buddyStatus structure that contains information on the gateway buddies. This structure limits the interactions that are needed with the IM server to get buddy and status information. The application also logs significant events, such as requests to add buddies and error messages from the IM server. In particular, it does the following:

This example uses the IM_ID column of the Employees database of the cfdocexamples database that is included with ColdFusion MX 7. The entries in this column assume that you use an XMPP server "company." To run this example you must configure an XMPP server with this name and with clients with names in this database, or you must change the database entries to match IM server clients. You must also configure a gateway instance in the ColdFusion MX Administrator that uses this server.

The following listing shows the CFC code:

<cfcomponent>

<cffunction name="onBuddyStatus">
   <cfargument name="CFEvent" type="struct" required="YES">
   <cflock scope="APPLICATION" timeout="10" type="EXCLUSIVE">
      <cfscript>
      // Create the status structures if they don't exist.
         if (NOT StructKeyExists(Application, "buddyStatus")) {
            Application.buddyStatus=StructNew();
         }
         if (NOT StructKeyExists(Application.buddyStatus, CFEvent.Data.BUDDYNAME)) {
            Application.buddyStatus[#CFEvent.Data.BUDDYNAME#]=StructNew();
         }
         // Save the buddy status and timestamp.
         Application.buddyStatus[#CFEvent.Data.BUDDYNAME#].status=CFEvent.Data.BUDDYSTATUS;
         Application.buddyStatus[#CFEvent.Data.BUDDYNAME#].timeStamp=CFEvent.Data.TIMESTAMP;
      </cfscript>
   </cflock>
</cffunction>
   
<cffunction name="onAddBuddyRequest">
   <cfargument name="CFEvent" type="struct" required="YES">
   <cfquery name="buddysearch" datasource="cfdocexamples">
      select IM_ID
      from Employees
      where IM_ID = '#CFEvent.Data.SENDER#'
   </cfquery>
   <cflock scope="APPLICATION" timeout="10" type="EXCLUSIVE">
      <cfscript>
         // If the name is in the DB once, accept; if it is missing, decline.
         // If it is in the DB multiple times, take no action.
         if (buddysearch.RecordCount IS 0) {
            action="decline";
            reason="Invalid ID";
         }
         else if (buddysearch.RecordCount IS 1) {
            action="accept";
            reason="Valid ID";
            //Add the buddy to the buddy status structure only if accepted.
            if (NOT StructKeyExists(Application,
                  "buddyStatus")) {
               Application.buddyStatus=StructNew();
            }
            if (NOT StructKeyExists(Application.buddyStatus,
                  CFEvent.Data.SENDER)) {
               Application.buddyStatus[#CFEvent.Data.SENDER#]=StructNew();
            }
            Application.buddyStatus[#CFEvent.Data.SENDER#].status=
               "Accepted Buddy Request";
            Application.buddyStatus[#CFEvent.Data.SENDER#].timeStamp=
               CFEvent.Data.TIMESTAMP;
            Application.buddyStatus[#CFEvent.Data.SENDER#].message=
               CFEvent.Data.MESSAGE;
         }
         else {
            action="noact";
            reason="Duplicate ID";
         }
      </cfscript>
   </cflock>
   <!--- Log the request and decision information. --->
   <cflog file="#CFEvent.GatewayID#Status" 
         text="onAddBuddyRequest; SENDER: #CFEvent.Data.SENDER# MESSAGE: #CFEvent.Data.MESSAGE# TIMESTAMP: #CFEvent.Data.TIMESTAMP# ACTION: #action#">
   <!--- Return the action decision. --->
   <cfset retValue = structNew()>
   <cfset retValue.command = action>
   <cfset retValue.BuddyID = CFEvent.DATA.SENDER>
   <cfset retValue.Reason = reason>
   <cfreturn retValue> 
</cffunction>

   
<cffunction name="onAddBuddyResponse">
   <cfargument name="CFEvent" type="struct" required="YES">
   <cflock scope="APPLICATION" timeout="10" type="EXCLUSIVE">
      <cfscript>
         //Do the following only if the buddy accepted the request.
         if (NOT StructKeyExists(Application, "buddyStatus")) {
            Application.buddyStatus=StructNew();
            }
         if (#CFEVENT.Data.MESSAGE# IS "accept") {
            //Create a new entry in the buddyStatus record for the buddy.
            if (NOT StructKeyExists(Application.buddyStatus,
                  CFEvent.Data.SENDER)) {
               Application.buddyStatus[#CFEvent.Data.SENDER#]=StructNew();
            }
            //Set the buddy status information to indicate buddy was added.
            Application.buddyStatus[#CFEvent.Data.SENDER#].status=
               "Buddy accepted us";
            Application.buddyStatus[#CFEvent.Data.SENDER#].timeStamp=
               CFEvent.Data.TIMESTAMP;
            Application.buddyStatus[#CFEvent.Data.SENDER#].message=
               CFEvent.Data.MESSAGE;
         }
      </cfscript>
   </cflock>
   <!--- Log the information for all responses. --->
   <cflog file="#CFEvent.GatewayID#Status" 
      text="onAddBuddyResponse; BUDDY: #CFEvent.Data.SENDER# RESPONSE: #CFEvent.Data.MESSAGE# TIMESTAMP: #CFEvent.Data.TIMESTAMP#">
</cffunction>

   
<cffunction name="onIMServerMessage">
   <!--- This function just logs the message. --->
   <cfargument name="CFEvent" type="struct" required="YES">
   <cflog file="#CFEvent.GatewayID#Status" 
      text="onIMServerMEssage; SENDER: #CFEvent.OriginatorID# MESSAGE: #CFEvent.Data.MESSAGE# TIMESTAMP: #CFEvent.Data.TIMESTAMP#">
</cffunction>   
</cfcomponent>

View comments in LiveDocs