Entries for month: February 2008

Important *Gotcha* for web service and application.cfc users

I recently learned about a neat feature of Coldspring that allows me to create remote proxy's of beans. I went through the doc and set everything up per examples, and my remote proxy's were generated, woohoo! So, I setup my function to return a proper value and I bind a cfgrid to the remote object. I invoke it, and get:

CFGRID: The response is empty

Weird.. so I try to call the CFC directly in the url, and I get a completely blank page. Fast forward about 2 hours of digging through CF and IIS logs trying to figure out why no error is being throw and no output is being displayed, then I find a web post about using cfc's and the onRequest function. For some reason, if you have anything in your onRequest, your call to the remote cfc will fail and give you an illuminating blank response! Here is what I placed in my onRequestStart function to fix it up, and now remoting and web service requests are working perfectly ;)

 

<cffunction name="onRequestStart" returnType="boolean" output="false">
      <cfargument name="thePage" type="string" required="true">   
      
      <!---// Necessary code to determine if a cfc is being requested and
            remove the onRequest function from this currently running process,
            otherwise a blank page gets returned and no error thrown //--->
      <cfif listLast(arguments.thePage, '.') eq 'cfc' OR isSOAPRequest()>
         <cfset StructDelete( THIS, "OnRequest" ) />
      </cfif>
   <cfreturn true>
  </cffunction>

 

2 Comments

Using a Transfer decorator to log all database changes

This is a quick and dirty blog entry, just wanted to hop on and blog about a method Im using to log database changes or additions done via Transfer.

All of my Transfer objects have decorators that were auto-generated by the very slick Illudium PU36 Code Generator, which basically adds a simple validate method. Normally a transfer decorator will extend transfer.com.TransferDecorator. Well, I have changed all of my decorators to extend a custom decoratorUtility, so that I can create shared functions across all transfer objects. Here is what my utility looks like:


<cffunction name=<span class='cc_value'>"save"</span> access=<span class='cc_value'>"public"</span> returntype=<span class='cc_value'>"void"</span> output=<span class='cc_value'>"false"</span> hint=<span class='cc_value'>""</span>>
   <cfargument name=<span class='cc_value'>"logData"</span> default=<span class='cc_value'>""</span> required=<span class='cc_value'>"false"</span> hint=<span class='cc_value'>"Accepts a string to be logged as the 'action' instead of the default"</span> />
   <cfset var className = '' />
   <cfset var pkName = '' />
   <cfset var pkType = '' />
   <cfset var pkValue = '' />
   <cfset var action = '' />
   <cfset var user = getAuthUser() />
   <cfset var logDate = now() />
   <cfset var log = '' />
   
   <!--<span class='cc_comment'>-// Gather some information about what we will be saving //---></span>   <cfset className = getClassName() />
   <cfset pkName = getTransfer().getTransferMetadata(className).getPrimaryKey().getName() />
   <cfset pkType = getTransfer().getTransferMetadata(className).getPrimaryKey().getType() />
   
   <!--<span class='cc_comment'>-// Determine if this record is a create or an update //---></span>
   <cfif getIsPersisted()>
      <cfset action = 'Updated' />
   <cfelse>
      <cfset action = 'Created' />
   </cfif>
   
   <!--<span class='cc_comment'>-// Invoke the underlying Transfer save function //---></span>   <cfset getTransfer().save(this) />
   
   <!--<span class='cc_comment'>-// Get the primary key value //---></span>   <cfset pkValue = this.getID() />
   
   <!--<span class='cc_comment'>-// Construct and save our transaction log record //---></span>   <cfset log = getTransfer().new('transactionLog') />
   <cfset log.setCompanyID(0) />
   <cfset log.setLogItem(className) />
   <cfset log.setlogID(pkValue) />
   <cfset log.setlogDate(logDate) />
   <cfset log.setlogData(arguments.logData) />
   <cfset log.setlogType(action) />
   <cfset log.setlogIP(cgi.REMOTE_ADDR) />
   
   <!--<span class='cc_comment'>-// If the user is logged in, add to the log //---></span>   <cfif isNumeric(user)>
      <cfset log.setlogUser(user) />
   </cfif>      
   <cfset getTransfer().save(log) />      
</cffunction>

This simply overrides the auto-generated save() function and will first get information about the transfer object to be saved, log it (using transfer still), then invokes the built-in save function. Obviously this has possibilities outside of logging, you could do security checks here, you could add utility / encryption functions here (think encrypting all data in your database, and then decrypting it after reading all in 1 spot)

Anyone else doing something like this?

Getting a web hosting deal is not a problem. The problem is to decide between startlogic or bluehost or the complex netfirms.

4 Comments

Grouped Output with Coldfusion

When I first started writing reports, I would jump through all different hoops to output grouped data.  Read on to see how Coldfusion and grouped output can make these reports a snap!

1 Comment