CFC-based Custom Tags by Example - Part 2
CFC based Custom Tags In the first Part we have looked at the major functions for CFC based Custom Tags, and how you can manipulate the environment and control the flow. In this entry we will look into exception handling.
Let me start with the first example, which is catching an exception. For this we take the example "savecontent" from first part.
<cfoutput>#urs#</cfoutput>
<cffunction name="onStartTag" output="no">
<cfargument name="attributes" type="struct" required="yes">
<cfargument name="caller" type="struct" required="yes">
<cfset this.attributes=attributes>
<cfset this.caller=caller>
</cffunction>
<cffunction name="onEndTag" output="no">
<cfargument name="attributes" type="struct" required="yes">
<cfargument name="caller" type="struct" required="yes">
<cfargument name="output" type="string" required="yes">
<cfparam name="attributes.variable">
<cfset caller[attributes.variable]=output>
</cffunction>
<cffunction name="onError" output="no" returntype="boolean"
hint="invoked when a failure occurs while executing the tag inside a function or the body. The return value defines if the exception should be caught or not">
<cfargument name="err" type="struct" required="yes" hint="exception information as a struct. The same one you get as inside a cfcatch block">
<cfargument name="source" type="string" required="yes" hint="Define where the failure has occurred, possible values are [start,body,end]">
<cfparam name="this.attributes.catch" type="boolean" default="#false#">
<cfset this.caller[this.attributes.variable]="error:"&err.message>
<cfreturn not this.attributes.catch>
</cffunction>
</cfcomponent>
error:Hello Urs As you can see we have introduced a new function here called "onError". You can compare this function with the "onError" method of Applcation.cfc. But with the "onError" of the tag you catch only exceptions that are thrown in the body, the method "onStartTag" or the method "onEndTag" of the tag. The first argument "err" gives you the cfcatch struct of the error whereas the second argument informs you where the exception was thrown, in the start-, endtag or in the body. With the return value you define whether the exception should be ended here or rethrown. In this case you can define with the help of the attribute "catch" whether the exception should be rethrown or not.
Ok, now we have a method that is invoked when a failure occurs. As you can see in the example above, the methods are never invoked both. If a failure occurs in the body, the method "onEndTag" will not be executed. If no failure occurs the method "onError" will not be invoked either. In some cases it would be good to have a method that is invoked no matter whether an exception has occurred or not. Let me make an example for this. We will use the savecontent custom tag again for this.
<cf_savecontent2 variable="urs">
<cfthrow message="Hello Urs">
</cf_savecontent2>
<cfcatch></cfcatch>
</cftry>
<cfoutput>#urs#</cfoutput><br />
<cf_savecontent2 variable="urs">Hello Urs</cf_savecontent2>
<cfoutput>#urs#</cfoutput>
<cffunction name="onStartTag" output="no">
<cfargument name="attributes" type="struct" required="yes">
<cfargument name="caller" type="struct" required="yes">
<cfset this.caller=caller>
<cfparam name="attributes.variable">
<cfset this.name=attributes.variable>
<cfset this.value="empty">
</cffunction>
<cffunction name="onEndTag" output="no">
<cfargument name="attributes" type="struct" required="yes">
<cfargument name="caller" type="struct" required="yes">
<cfargument name="output" type="string" required="yes">
<cfset this.value=output>
</cffunction>
<cffunction name="onFinally" output="no" returntype="void" hint="invoked after the tag is executed in any case, even the tag throws a non caught exception">
<cfset this.caller[this.name]=this.value>
</cffunction>
</cfcomponent>
empty
Hello Urs Here we now have the last method supported by CFC based Custom Tags: "onFinally". This method is executed after all other methods, in any case, even if an exception has occurred in the body or in one of the functions executed before. This can be really helpful for example to close streams (ftp,file,...) opened in one of the functions before or doing something that has to be done in every case. Ok, this was exception handling with CFC based Custom Tags. In the last part we will look how you can use CFC based Custom Tags as Build in Tags and how you can define requirements for custom tags.



.brett
- cfassoicate
- getbaseTagList
- getBaseTagData
you have the same control with the return values of the function, as you have with cfexit, but a much more clearer than cfexit.
i always had problem to undertsand what cfexit does when i look into a cfml custom tag and i have implemented this tag ;-)