In a ColdFusion application, I have a class called ProjectBeanService that extends another class called AjaxBeanService.
In CF8, where the code seems to be working properly, when debugging the application in IE, I see this rendered JavaScript:
<script type="text/javascript">
var _cf_ProjectBeanService=ColdFusion.AjaxProxy.init('/components/ProjectBeanService.cfc','ProjectBeanService');
_cf_ProjectBeanService.prototype.get=function(sPropertyName,sBeanType,nID,sSection,nRevision) { return ColdFusion.AjaxProxy.invoke(this, "get", {sPropertyName:sPropertyName,sBeanType:sBeanType,nID:nID,sSection:sSection,nRevision:nRevision});};
_cf_ProjectBeanService.prototype.getAll=function(sBeanType,nID,sSection,nRevision) { return ColdFusion.AjaxProxy.invoke(this, "getAll", {sBeanType:sBeanType,nID:nID,sSection:sSection,nRevision:nRevision});};
_cf_ProjectBeanService.prototype.set=function(sPropertyName,oPropertyValue,sBeanType,nID,sSection,nRevision) { return ColdFusion.AjaxProxy.invoke(this, "set", {sPropertyName:sPropertyName,oPropertyValue:oPropertyValue,sBeanType:sBeanType,nID:nID,sSection:sSection,nRevision:nRevision});};
</script>
However, when I try to run the same application under CF11, both the class methods and the superclass methods are rendered:
<script type="text/javascript">/* <![CDATA[ */
var _cf_ProjectBeanService=ColdFusion.AjaxProxy.init('/components/ProjectBeanService.cfc','ProjectBeanService');
_cf_ProjectBeanService.prototype.get=function(sPropertyName,sBeanType,nID,sSection,nRevision) { return ColdFusion.AjaxProxy.invoke(this, "get","4789898A8974AC60", {sPropertyName:sPropertyName,sBeanType:sBeanType,nID:nID,sSection:sSection,nRevision:nRevision});};
_cf_ProjectBeanService.prototype.getAll=function(sBeanType,nID,sSection,nRevision) { return ColdFusion.AjaxProxy.invoke(this, "getAll","4789898A8974AC60", {sBeanType:sBeanType,nID:nID,sSection:sSection,nRevision:nRevision});};
_cf_ProjectBeanService.prototype.set=function(sPropertyName,oPropertyValue,sBeanType,nID,sSection,nRevision) { return ColdFusion.AjaxProxy.invoke(this, "set","4789898A8974AC60", {sPropertyName:sPropertyName,oPropertyValue:oPropertyValue,sBeanType:sBeanType,nID:nID,sSection:sSection,nRevision:nRevision});};
_cf_ProjectBeanService.prototype.get=function(sBeanName,sPropertyName) { return ColdFusion.AjaxProxy.invoke(this, "get","4789898A8974AC60", {sBeanName:sBeanName,sPropertyName:sPropertyName});};
_cf_ProjectBeanService.prototype.destroySessionBean=function(sBeanName) { return ColdFusion.AjaxProxy.invoke(this, "destroySessionBean","4789898A8974AC60", {sBeanName:sBeanName});};
_cf_ProjectBeanService.prototype.createSessionBean=function(sBeanName,sBeanType,sDAOName) { return ColdFusion.AjaxProxy.invoke(this, "createSessionBean","4789898A8974AC60", {sBeanName:sBeanName,sBeanType:sBeanType,sDAOName:sDAOName});};
_cf_ProjectBeanService.prototype.getAll=function(sBeanName) { return ColdFusion.AjaxProxy.invoke(this, "getAll","4789898A8974AC60", {sBeanName:sBeanName});};
_cf_ProjectBeanService.prototype.getSessionBean=function(sBeanName) { return ColdFusion.AjaxProxy.invoke(this, "getSessionBean","4789898A8974AC60", {sBeanName:sBeanName});};
_cf_ProjectBeanService.prototype.set=function(sBeanName,sPropertyName,oPropertyValue) { return ColdFusion.AjaxProxy.invoke(this, "set","4789898A8974AC60", {sBeanName:sBeanName,sPropertyName:sPropertyName,oPropertyValue:oPropertyValue});};
_cf_ProjectBeanService.prototype.reInitSessionBean=function(sBeanName,argument1,argument2,argument3,argument4) { return ColdFusion.AjaxProxy.invoke(this, "reInitSessionBean","4789898A8974AC60", {sBeanName:sBeanName,argument1:argument1,argument2:argument2,argument3:argument3,argument4:argument4});};
/* ]]> */</script>
In this block of code, notice how after the "set" function is defined, it is defined again (and according to the superclass definition). It seems to me that ColdFusion 11 is rendering this superclass, whereas CF 8 did not.
Any suggestions?
UPDATE:
Here is a stripped down version of the application, wherein I was able to reproduce the error.
/components/AbstractAjax.cfc:
<cfcomponent displayname="AbstractAjax">
<cffunction name="sendError" access="private" returntype="void">
<cfargument name="sErrCode" type="string" required="yes" />
<cfargument name="sErrMsg" type="string" required="yes" />
<cfif IsNumeric(arguments.sErrCode)>
<cfscript>
GetPageContext().getResponse().sendError(arguments.sErrCode,arguments.sErrMsg);
</cfscript>
<cfelse>
<cfscript>
GetPageContext().getResponse().sendError(555,arguments.sErrCode & ' - ' & arguments.sErrMsg);
</cfscript>
</cfif>
</cffunction>
</cfcomponent>
/components/AjaxBeanService.cfc:
<cfcomponent displayname="AjaxBeanService" extends="com.AbstractAjax">
<cffunction name="createSessionBean" access="remote" returntype="struct">
<cfargument name="sBeanName" type="string" required="yes">
<cfargument name="sBeanType" type="string" required="yes">
<cfargument name="sDAOName" type="string" required="yes">
<cfset var oBean = StructNew() />
<cfset var oBeanArguments = ARGUMENTS />
<cfset var oDAO = application[sDAOName] />
<cftry>
<cfset oBean = createObject("component","com." & sBeanType) />
<!--- delete first 3 elements from arguments array --->
<cfset ArrayDeleteAt(oBeanArguments,1) />
<cfset ArrayDeleteAt(oBeanArguments,1) />
<cfset ArrayDeleteAt(oBeanArguments,1) />
<!--- make the DAO object the first argument --->
<cfset ArrayPrepend(oBeanArguments,oDAO) />
<cfset oBean.init.apply(oBean,oBeanArguments) />
<cfset SESSION.beans[sBeanName] = oBean />
<cfreturn oBean.getAll() />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
<cffunction name="destroySessionBean" access="remote" returntype="struct">
<cfargument name="sBeanName" type="string" required="yes">
<cfset rc = StructDelete(SESSION.beans, "#sBeanName#", "True")>
</cffunction>
<cffunction name="reInitSessionBean" access="remote" returntype="struct">
<cfargument name="sBeanName" type="string" required="yes">
<cfargument name="argument1" type="any" required="no" default="">
<cfargument name="argument2" type="any" required="no" default="">
<cfargument name="argument3" type="any" required="no" default="">
<cfargument name="argument4" type="any" required="no" default="">
<cfset var oBean = StructNew() />
<cftry>
<cfset oBean = getSessionBean(sBeanName) />
<cfset oBean.init(oBean.getDAO(),argument1,argument2,argument3,argument4) />
<cfset SESSION.beans[sBeanName] = oBean />
<cfreturn oBean.getAll() />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
<cffunction name="getSessionBean" access="remote" returntype="any">
<cfargument name="sBeanName" type="string" required="yes">
<cfset var oBean = StructNew() />
<cfif StructKeyExists(SESSION.beans,sBeanName) >
<cflock scope="session" type="readonly" timeout="5" throwontimeout="yes">
<cfset oBean = Duplicate(SESSION.beans[sBeanName]) />
</cflock>
</cfif>
<cfif StructIsEmpty(oBean)>
<cfthrow errorcode="500" message="No bean found by the name '#sBeanname#'" />
<cfelse>
<cfreturn oBean />
</cfif>
</cffunction>
<cffunction name="set" access="remote" returntype="void">
<cfargument name="sBeanName" type="string" required="yes">
<cfargument name="sPropertyName" type="string" required="yes">
<cfargument name="oPropertyValue" type="string" required="yes">
<cfset var oBean = StructNew() />
<cftry>
<cfset oBean = getSessionBean(sBeanName) />
<cfset oBean.set(sPropertyName,oPropertyValue) />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
<cffunction name="get" access="remote" returntype="any">
<cfargument name="sBeanName" type="string" required="yes">
<cfargument name="sPropertyName" type="string" required="yes">
<cfset var value = "" />
<cfset var oBean = StructNew() />
<cftry>
<cfset oBean = getSessionBean(sBeanName) />
<cfset value = oBean.get(sPropertyName) />
<cfreturn value />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
<cffunction name="getAll" access="remote" returntype="struct">
<cfargument name="sBeanName" type="string" required="yes">
<cfset var oBean = StructNew() />
<cfset var oStruct = structNew() />
<cftry>
<cfset oBean = getSessionBean(sBeanName) />
<cfset oStruct = oBean.getAll() />
<cfreturn oStruct />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
</cfcomponent>
/components/ProjectBeanService.cfc:
<cfcomponent displayname="ProjectBeanService" extends="com.AjaxBeanService">
<cffunction name="getBean" access="private" returntype="any">
<cfargument name="sBeanType" type="string" required="yes">
<cfargument name="nID" type="numeric" required="yes" hint="ProjectID or ImpactID">
<cfargument name="sSection" type="string" required="no" hint="ProjectSection or ImpactSection" default="">
<cfargument name="nRevision" type="numeric" required="no" hint="Commitment Revision" default="0">
<cfset var oBean = createObject("component","com." & sBeanType).init(nID,sSection,nRevision) />
<cfreturn oBean />
</cffunction>
<cffunction name="set" access="remote" returntype="void">
<cfargument name="sPropertyName" type="string" required="yes">
<cfargument name="oPropertyValue" type="string" required="yes">
<cfargument name="sBeanType" type="string" required="yes">
<cfargument name="nID" type="numeric" required="yes">
<cfargument name="sSection" type="string" required="no" default="">
<cfargument name="nRevision" type="numeric" required="no" default="0">
<cfset var oBean = StructNew() />
<cftry>
<cfset oBean = getBean(sBeanType, nID, sSection,nRevision) />
<cfset oBean.set(sPropertyName,oPropertyValue) />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
<cffunction name="get" access="remote" returntype="any">
<cfargument name="sPropertyName" type="string" required="yes">
<cfargument name="sBeanType" type="string" required="yes">
<cfargument name="nID" type="numeric" required="yes">
<cfargument name="sSection" type="string" required="no" default="">
<cfargument name="nRevision" type="numeric" required="no" default="0">
<cfset var value = "" />
<cfset var oBean = StructNew() />
<cftry>
<cfset oBean = getBean(sBeanType,nID,sSection,nRevision) />
<cfset value = oBean.get(sPropertyName) />
<cfreturn value />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
<cffunction name="getAll" access="remote" returntype="struct">
<cfargument name="sBeanType" type="string" required="no" default="ProjectBean">
<cfargument name="nID" type="numeric" required="yes">
<cfargument name="sSection" type="string" required="no" default="">
<cfargument name="nRevision" type="numeric" required="no" default="0">
<cfset var oBean = StructNew() />
<cfset var oStruct = structNew() />
<cftry>
<cfset oBean = getBean(sBeanType,nID,sSection,nRevision) />
<cfset oStruct = oBean.getAll() />
<cfreturn oStruct />
<cfcatch type="any">
<cfset sendError(cfcatch.ErrorCode,cfcatch.message) />
</cfcatch>
</cftry>
</cffunction>
</cfcomponent>
/Application.cfc:
<cfcomponent>
<cfscript>
this.mappings["/com"] = getDirectoryFromPath(getCurrentTemplatePath()) & "\components\";
</cfscript>
</cfcomponent>
/index.cfm:
<html>
<head>
<title></title>
<cfajaxproxy cfc="com.ProjectBeanService" jsclassname="ProjectBeanService">
</head>
<body>
<span>This is a test.</span>
</body>
</html>
So far, the only answer I have come up with is that this must be a bug in CF11, so I was able to "fix" it by marking the methods in the parent class as having access "public" rather than "remote". I do not yet know what unintended consequences this could have, but it seems to have fixed my problem. If anyone has a better suggestion, please let me know, and I'll give the answer check to that person.
So every so often I am getting this error, mostly caused by bots:
java.lang.IllegalArgumentException:
[Table (rows 0 columns ID, BOOKID, EDITIONID, EDITIONNAME, PRACTICEAREALINK, PUBLISHED):
...REALINK: coldfusion.sql.QueryColumn#2c12f137]
[PUBLISHED: coldfusion.sql.QueryColumn#f9a687c] ] is not indexable by webtypeid
However the columns it refers to are nowhere to be found in the query it's trying to reference.
so we have 3 files in play here, an index.cfm, a Business.cfc and a DAO.cfc. Within the business the code looks like:
<cfcomponent extends="_lbr._core.NativeBusiness">
<cffunction name="init" access="public" output="false" returntype="_lbr._who._publication._Edition.EditionBusiness" hint="Pseudo-constructor">
<cfargument name="oEditionDAO" type="_lbr._who._publication._Edition.EditionDAO" required="true">
<cfscript>
super.init(argumentCollection=arguments);
variables.oEditionDAO = arguments.oEditionDAO;
return this;
</cfscript>
</cffunction>
<cffunction name="getEditionByPracticeArea" returntype="query" access="public">
<cfargument name="nEditionID" type="numeric" required="false">
<cfargument name="nPraciceAreaID" type="numeric" required="false">
<cfargument name="bPublished" type="boolean" required="false">
<cfscript>
return variables.oEditionDAO.getEditionByPracticeArea(argumentCollection=arguments);
</cfscript>
</cffunction>
<cffunction name="getEditionsByPracticeArea" returntype="query" access="public">
<cfargument name="nPracticeAreaID" type="numeric" required="false">
<cfargument name="bPracticeAreaLink" type="boolean" required="false">
<cfargument name="bPublished" type="boolean" required="false">
<cfargument name="lstFields" type="string" required="false">
<cfscript>
return variables.oEditionDAO.getEditionsByPracticeArea(argumentCollection=arguments);
</cfscript>
</cffunction>
<cffunction name="getTypesByPracticeArea" returntype="query" access="public">
<cfargument name="nPracticeAreaID" type="numeric" required="false">
<cfargument name="nEditionID" type="numeric" required="false">
<cfscript>
return variables.oEditionDAO.getTypesByPracticeArea(argumentCollection=arguments);
</cfscript>
</cffunction>
</cfcomponent>
Nothing particularly unusual there.
the DAO looks like
<cfcomponent extends="_lbr._core.NativeDAO">
<cffunction name="init" access="public" output="false" returntype="_lbr._who._Publication._Edition.EditionDAO" hint="Pseudo-constructor">
<cfargument name="sDSN" type="string" required="true" hint="The datasource name to use to access the database through.">
<cfargument name="oCFML" type="_lbr._util._cfml.CFML" required="true" hint="The CFML object to use for scripting.">
<cfscript>
super.init(argumentCollection=arguments);
variables.sDSN = arguments.sDSN;
variables.oCFML = arguments.oCFML;
variables.lstFields = "p.publication_ID, p.publication_name, e.edition_id, e.edition_name, e.pub_year, e.pub_date";
variables.lstSubEditionFields = "id,bookid,editionid,editionname,practiceareaLink,published";
return this;
</cfscript>
</cffunction>
<cffunction name="getEditionByPracticeArea" returntype="query" access="public">
<cfargument name="nEditionID" type="numeric" required="false">
<cfargument name="nPraciceAreaID" type="numeric" required="false">
<cfargument name="bPublished" type="boolean" required="false">
<cfargument name="nStartRow" required="true" type="numeric" default="0">
<cfargument name="nEndRow" required="true" type="numeric" default="1">
<cfscript>
return selectEditionsByPracticeArea(argumentCollection=arguments);
</cfscript>
</cffunction>
<cffunction name="getEditionsByPracticeArea" returntype="query" access="public">
<cfargument name="nPracticeAreaID" type="numeric" required="false">
<cfargument name="bPracticeAreaLink" type="boolean" required="false">
<cfargument name="bPublished" type="boolean" required="false">
<cfargument name="lstFields" type="string" required="false">
<cfscript>
return selectEditionsByPracticeArea(argumentCollection=arguments);
</cfscript>
</cffunction>
<cffunction name="selectEditionsByPracticeArea" returntype="query" access="public">
<cfargument name="nStartRow" required="true" type="numeric" default="0">
<cfargument name="nEndRow" required="true" type="numeric" default="100">
<cfargument name="nEditionID" type="numeric" required="false" default="0">
<cfargument name="nPracticeAreaID" type="numeric" required="false" default="0">
<cfargument name="bPracticeAreaLink" type="boolean" required="false">
<cfargument name="bPublished" type="boolean" required="false">
<cfargument name="lstFields" type="string" default="#variables.lstSubEditionFields#" required="false">
<cfquery name="qQuery" datasource="#variables.sDSN#">
SELECT #arguments.lstFields#
FROM tbl_who_subeditions
WHERE 1
<cfif arguments.nPracticeAreaID gt 0>
AND bookid = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.nPracticeAreaID#">
</cfif>
<cfif arguments.nEditionID gt 0>
AND editionID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.nEditionID#">
</cfif>
<cfif structKeyExists(arguments,"bPublished")>
AND published = <cfqueryparam cfsqltype="cf_sql_bit" value="#arguments.bPublished#">
</cfif>
<cfif arguments.nPracticeAreaID gt 0 OR arguments.nEditionID gt 0>
<cfif structKeyExists(arguments,"bPracticeAreaLink")>
AND practiceareaLink = <cfqueryparam cfsqltype="cf_sql_tinyint" value="#arguments.bPracticeAreaLink#">
</cfif>
</cfif>
LIMIT #arguments.nStartRow#,#arguments.nEndRow#
</cfquery>
<cfreturn qQuery>
</cffunction>
<cffunction name="getTypesByPracticeArea" returntype="query" access="public">
<cfargument name="nPracticeAreaID" type="numeric" required="false">
<cfargument name="nEditionID" type="numeric" required="false">
<cfscript>
return selectTypesByPracticeArea(argumentCollection=arguments);
</cfscript>
</cffunction>
<cffunction name="selectTypesByPracticeArea" returntype="query" access="public">
<cfargument name="nStartRow" required="true" type="numeric" default="0">
<cfargument name="nEndRow" required="true" type="numeric" default="100">
<cfargument name="nEditionID" type="numeric" required="false" default="0">
<cfargument name="nPracticeAreaID" type="numeric" required="false" default="0">
<cfargument name="lstFields" type="string" default="#variables.lstSubEditionFields#" required="false">
<cfquery name="qQuery" datasource="#variables.sDSN#">
SELECT distinct webtypeid, typename
FROM tbl_who_webtype2practiceareas wp
JOIN tbl_who_webtypes w ON wp.webtypeid = w.id
WHERE 1
<cfif arguments.nPracticeAreaID gt 0>
AND bookid = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.nPracticeAreaID#">
</cfif>
<cfif arguments.nEditionID gt 0>
AND editionid = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.nEditionID#">
</cfif>
LIMIT #arguments.nStartRow#,#arguments.nEndRow#
</cfquery>
<cfreturn qQuery>
</cffunction>
</cfcomponent>
The only thing that is unusual here is that selectTypesByPracticeArea has a lstFields defaulted with variables.lstSubEditionFields, but since it's not being used in that function, it shouldn't prove an issue
so the index.cfm just has
variables.stArgs = {};
variables.stArgs.nPracticeAreaID = request.parameters.nPublicationID;
variables.stArgs.nEditionID = request.parameters.nSubEdition;
variables.qTypes = application.stObj.oEditionBusiness.getTypesByPracticeArea(argumentCollection=variables.stArgs);
if(variables.qTypes["webtypeid"].IndexOf(JavaCast("int",2)) GTE 0 OR variables.qTypes["webtypeid"].IndexOf(JavaCast("int",3)) GTE 0){
request.parameters.bHasTypes = true;
}
The error occurs on that if statement. It should only be receiving a query that contains webtypeid and typename, so where does it think that it's getting ID, BOOKID, EDITIONID, EDITIONNAME, PRACTICEAREALINK, PUBLISHED from? All i can reason is that it's getting confused with the lstfields... but that doesn't make any sense.
At first glance I suspect it's that you are not using var to declare qQuery local to the function, so it is being overwritten at times while you are executing these methods. If you try this before your CFQUERY tags you will likely see it go away:
<cfset var qQuery = "">
You can also use the LOCAL scope as in local.qQuery
I am getting Variable undefined error when i try to invoke a function from a cfc.
The best part is it is already defined above.
"IandI" is the cfc name.
Code snippet :
<cfparam name="TotalCorpAudits" default="0">
<cfset TotalAudits = TotalSiteAudits + TotalCorpAudits>
<cfinvoke component="#IandI#"
method="calcRate"
Cases="#TotalCorpAudits#"
Hours="#TotalAudits#"
iiFactor="1"
convertToPercent="true"
NumberFormatOn="true"
returnOnZeroHours="0"
returnOnNonNumericData="0"
returnvariable="TotalCorpRatioAudits"
>
Getting error at ... Cases="#TotalCorpAudits#"
CFC Code :
<cffunction name="calcRate" access="public" returntype="string"
displayname="calcs Rate" hint="" description="">
<cfargument name="Hours" required="Yes" type="string">
<cfargument name="Cases" required="Yes" type="string">
<cfargument name="IIFactor" required="No" type="numeric" default="200000">
<cfargument name="FormatMask" required="No" type="string" default="999.99">
<cfargument name="NumberFormatOn" required="No" type="boolean" default="false">
<cfargument name="returnOnZeroHours" required="No" type="string" default="0">
<cfargument name="returnOnNonNumericData" required="No" type="string" default="N/A">
<cfargument name="returnOnZeroCasesWithHours" required="No" type="string" default="0">
<cfargument name="convertToPercent" required="No" type="boolean" default="false">
CFINVOKE works like so:
<cfinvoke component="[CFC_FileName]" method="calcRate" returnvariable="TotalCorpRatioAudits">
<cfinvokeargument name="Hours" value="[whateverValueYouWant]">
<cfinvokeargument name="Cases" value="[whateverValueYouWant]">
</cfinvoke>
Notice a couple things: <cfinvokeargument> is underneath the <cfinvoke> tag. Also, I only used those two argument since they were required in the CFC, but you can add more if needed. Use https://wikidocs.adobe.com/wiki/display/coldfusionen/cfinvoke as a reference.
is the name of component comeing from a variables? Is IandI a variable? If it is not you dont have to wrap it in # signs. And that is what I think is causing the problem.
I've run into this a few times lately; it definitely seems like a bug in the ColdFusion engine. Seems as if the compiler is trying to evaluate the variable from within the CFC, rather than the calling page.
I've been able to work around it by defining my struct of arguments beforehand, then simply including the struct in the invoke().
<cfset argStruct = {argName1=val1,argName2=val2,argName3="hardcodedValue"}>
<cfinvoke component="cfcPath" method="methodName" argumentCollection="#argStruct#" />
I'm invoking a cfc, the cfc has a default set of arguments like so:
<cfargument name="EMAIL_TEMPLATE_CODE" type="string" required="yes" hint="EMAIL_TEMPLATE_CODE is required.">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string" required="no" hint="EMAIL_TEMPLATE_SUBJECT is NOT required.">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string" required="no" hint="EMAIL_TEMPLATE_BODY is NOT required.">
What I'd like to do is make these arguments not requred (as you can see by required="no") but I'd like to reassign the arguments variable if needed.
So something like:
<cfargument name="EMAIL_TEMPLATE_CODE" type="string" required="yes" hint="EMAIL_TEMPLATE_CODE is required.">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string" required="no" hint="EMAIL_TEMPLATE_SUBJECT is NOT required.">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string" required="no" hint="EMAIL_TEMPLATE_BODY is NOT required.">
<cfinvoke component="#Request.CFCPath#.email_template" method="getEmailTemplate" returnvariable="getEmailTemplate">
<cfinvokeargument name="EMAIL_TEMPLATE_CODE" value="#ARGUMENTS.EMAIL_TEMPLATE_CODE#">
</cfinvoke>
<cfif getEmailTemplate.RecordCount>
<cfparam name="ARGUMENTS.EMAIL_TEMPLATE_SUBJECT" default="#getEmailTemplate.EMAIL_TEMPLATE_SUBJECT#" type="string">
<cfparam name="ARGUMENTS.EMAIL_TEMPLATE_BODY" default="#getEmailTemplate.EMAIL_TEMPLATE_BODY#" type="string">
</cfif>
But I'm not able to override the default ARGUMENTS variable. Is there anything you can spot that I'm doing wrong?
EDIT:
I'm doing this because if no argument is passed to the cfc, I want to create one. I guess I should cfset a local variable if the argument doesn't have length?
<cfif Len(ARGUMENTS.EMAIL_TEMPLATE_ADDRESS_FROM)>
<cfset EMailTemplateAddressFrom = ARGUMENTS.EMAIL_TEMPLATE_ADDRESS_FROM>
<cfelse>
<cfset EMailTemplateAddressFrom = getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM>
</cfif>
<cfparam> works only if the variable has been undefined before. Your function parameters are not undefined, they just happen to have their default values. So you could do this:
<cffunction name="foo">
<cfargument name="arg" type="string" required="yes">
<cfargument name="opt" default="default" type="string" required="no">
<cfif arguments.opt eq "default">
<cfset arguments.opt = "whatever dynamic value">
</cfif>
</cffunction>
This way, if you don't supply "opt" (or deliberately set it to "default"), it will get assigned some kind of dynamic default value. And you can still make it empty, if you need.
Instead of "default", you could choose some other kind of improbable value that allows you to make a distinction between "not supplied" and "empty". (Sometimes I wish ColdFusion would support actual null values...)
<cfargument name="EMAIL_TEMPLATE_CODE" type="string"
default="#getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM#">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string">
or....
<cfargument name="EMAIL_TEMPLATE_CODE" type="string">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string">
<cfif NOT isDefined("arguments.EMAIL_TEMPLATE_CODE")>
<cfset arguments.EMAIL_TEMPLATE_CODE = getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM>
</cfif>
FYI, required="no" by default, so I usually don't specify it to the already verbose CFML. :)