Passing variables to cfinclude - coldfusion

How can I pass a variable to a cfm page that I'm including from another page?
Example:
<cfset a.name = "me">
<cfset a.age = 135>
<cfinclude template="displayNameAndAgeFrom_A.cfm">
and displayNameAndAgeFrom_A.cfm is
<cfoutput>#a.name# #a.age#</cfoutput>
Thanks!

AFAIK, this should work, exactly the way you posted it, without having to pass anything at all. Any values available in the outside/calling page are available in the included page.

Also worth noting that you also have <cfmodule ... /> available. cfmodule will let you call the same template but you can pass in different values for the same attributes.
Check out ColdFusion 9 documentation on cfmodule.
This template/module however will only have access to a handful of scopes that the caller template has access to: request, session and application

Related

How to get the information about the page that call .cfc page and function? ColdFusion9

I have global function in my system that was implemented while ago before I even started maintaining the system. One of the recent projects involved some major updates in that function. I have set the cfmail with some information inside in hope that I will get the .cfm page that call that function. So far only that I got is the page where the function is located but I already knew that. I got this information with this function:
GetDirectoryFromPath(path)
I was wondering if there is any other function that can give me the name of the page that called the function? If anyone can help me solve this problem please let me know. I'm still doing research but there is nothing that I came accross that would be helpful in my case.
I use CF9 and did this:
In a CFC
<cffunction name="dumpCGI" returntype="void" output="yes">
<cfdump var="#cgi#">
</cffunction>
In the calling template:
obj = createObject("component", "Something");
obj.dumpCGI();
I saw 3 variables that correctly identified the calling template. Once you pick the one you want to use, you can decide how to process it.

Verify if a method of an object exists

I'm calling a web service through ColdFusion which returns an object, and I want to verify if one of the methods of this object exists as it won't always exist.
I found this source which seemed promising however based on my tests I can see the results are always negative and the method is never found when it's clearly there.
<cfif structKeyExists("#Result.getNotifications().getValidationResult(0)#","getField")>
Result is my underlying object, and my end goal is to verify if the method getField() exists.
Is there a clean way to do this as opposed to a try/catch?
Update:
Unfortunately, I am not sure IsInstanceOf() works with web services, due to the fact that CF uses a Proxy object to "wrap" the underlying web service class. If not, another simple option is to check class name. That avoids the ambiguity of checking for method name only (which could potentially exist in many different classes). Plus I suspect it may be more light-weight than IsInstanceOf() anyway.
<cfif compare(yourObject.getClass().name, "org.tempuri.ValidationResultField") eq 0>
Found ValidationResultField. do something
</cfif>
It looks like the dump contains several different types of objects/classes: ArrayOfValidationResult, ValidationResultField, etecetera. It sounds like what you are really trying to determine is which of those classes you are working with, so you know exactly what fields and methods will be available, per the web service definitions. Given that, I think IsInstanceOf() would be a more appropriate test, than checking for method names. More accurate as well. Nothing prevents two different classes from having the same method name. So even if method X or Y exists, there is still a possibility it may be a different class than expected.
<cfif IsInstanceOf(yourObject, "org.tempuri.ValidationResultField")>
do something
</cfif>
As far as I know, the mentioned structKeyExists approach only works if CF wraps the class internally, e.g. all instances of cfcomponent.
The only option left is to actually reflect the class:
<cftry>
<cfset Result.getNotifications().getValidationResult(0).getClass().getMethod("getField", javaCast("null", ""))>
<!--- method does exist --->
<cfcatch type="coldfusion.runtime.CfJspPage$UnsupportedBaseTypeException">
<!--- method does not exist --->
</cfcatch>
</cftry>
If the method doesn't exist, it throws UnsupportedBaseTypeException, which seems to be a follow-up of NoSuchMethodException.
Honestly, you might as well just invoke the method and catch it. Reflection comes with an additional overhead and you have to catch it anyway.
Like Miguel-F, I think this is something for getMetadata(). The following should return an array containing the respective functions of the object:
<cfset funcs = getmetadata(nameOfObj).functions>
The names of the functions are then funcs[1].name, funcs[2].name, and so on.
In general, you may obtain the metadata of all the functions of a webservice, given the URL of the WSDL, with something like
<cfhttp method="get" url="http://www.webservicex.net/globalweather.asmx?WSDL" result="res">
<cfset wsXml=xmlparse(res.filecontent)>
<cfset wsOperations = xmlsearch(wsXml,"//wsdl:operation")>
<cfdump var="#wsOperations#">
Another method you could look at (perhaps undocumented) is to get the method names from the class names in the stubs directory.
The code to run is:
<cfscript>
wsargs = structnew();
wsargs.savejava="yes";
</cfscript>
<cfset convert=createobject("webservice","url_of_wsdl",wsargs)>
Then figure out how to fish out the names from the stubs directory, {CF_INSTALL}/stubs. In my case, CF_INSTALL is C:/ColdFusion2016/cfusion/

Access Variable in CFC using URL Invocation Method

I've a variable in my Application.cfm that stores the datasource for cfqueries.
<cfset mydatasource= 'somedatasorce'>
I can use it in any normal cfm page as below:
<cfset any_var = #mydatasource#>
I've a cfm page that calls a cfc which builds a query dynamically. This is the URL Invocation Method of CFC.
I'm not able to access "mydatasource" in the CFC using the above statement. It says "mydatasource" is undefined. I tried storing this in Application scope & accessed in CFC but again it says "mydatasource" is undefined in "Application".
On a bit of search, I found that the CFC needs to be instantiated in order to access the Application scope. But the URL Invocation method doesn't create an instance.
I can pass the datasource using query string but I'm looking for a better & more secure alternative.
Any suggestions are highly appreciated.
Thanks!! :)
I have been adding a number of ajax calls to an old application here and in order to get some application specific settings I created a file I called App.cfc. The contents of it are simply:
<cfcomponent>
<cfscript>
this["datasource"] = "something";
..... and so on .....
</cfscript>
</cfcomponent>
Then the CFC files I am making my URL calls to they simple extend App. So within those CFCs I can do datasource="#this['Datasource']#"
May not be the most "pretty" of ways to get the job done but it has been working here without issues.
UPDATE
I should have also mentioned that in order to avoid having settings in both that CFC and in the Application.cfm, I have something like this in my Application.cfm:
<cfscript>
objApp = CreateObject("component", "Components.App");
StructAppend(App, objApp);
</cfscript>
These old applications I am working with have a structure withing VARIABLES called App that is a copy of all Application variables. I see no reason why in this case you could not just do a structure appending to VARIABLES since appears that is where you are expecting things like the datasource to be on in your CFM pages.

Attributes scope vs attributes structure

Custom tags have an attributes scope. Cool.
I've also seen some other apps (and possibly ColdBox?) where the developer put everything into an attributes structure. For example in login.cfm:
<cfparam name="attributes.username" default="some value">
Is there a point to this besides having to specify attributes.foo which does improve readability, I'll admit but why reuse a name of a full scope?
Is this personal preference or am I missing something profound with the attributes scope?
It's nothing profound. A lot of frameworks (and individual developers) like to combine the form and url scopes into a single "event" object or something (ala your "attributes" example), but it doesn't really buy you much.
That said, naming a new object after an existing scope is misguided, and I'd recommend against it. What happens when you want something out of the attributes scope, not the attributes object?
You could always reference the object via variables.attributes.foo for explicitness, but that's a pain and a bit ugly. And of course, nothing stops you from accessing the attributes scope (scope priority would check attributes before variables.attributes), but then the person that has to read the code after you is more confused. It's essentially created a problem instead of solving one.
In Fusebox, the idea was that a individual file could be used as either a part of the framework, or it could be used as part of cfmodule. Inside of corefiles/application.cfc is:
...
<cfparam name="variables.attributes" default="#structNew()#" />
<cfif isDefined("URL")>
<cfset structAppend(attributes,URL,true) />
</cfif>
<cfif isDefined("form")>
<cfset structAppend(attributes,form,true) />
</cfif>
...
See GitHub for details

attributes.someParam cannot be evaluated in coldfusion

I have in my cfm something like this
<CFModule name="MyModule"
someParam_one="#something.one#"
someParam_two="#something.two#"
someParam_etc="etc_etc_etc"/>
And inside my module, I have an
<CFSet param_name = "someParam_one">
...
evaluate("attributes." & param_name)
On most of our servers, this work. But on one of our servers, I get a
Error resolving parameter ATTRIBUTES.SOMEPARAM_NAME
Any ideas why?
Thanks
Have you verified that someParam_one is actually getting created? I've found, for example, that if I do something like this:
<cfset foo = myObject.getSomething() />
and getSomething returns a void value or runs a Java function that doesn't return anything, that CF will choke on it. The variable will be "defined", or so the application seems to think, but attempting to access it will throw an error. So do the following to track down and catch the problem:
Dump your attributes scope to make sure that what you want is indeed actually there.
Run a StructKeyExists(Attributes, param_name) before attempting to access the variable.
Get rid of the evaluate, and instead use Attributes[param_name]
Tangential to your question, but Evaluate() is evil, and an unnecessary evil in this situation. You can write this instead, and it will be more clear, more secure, and faster:
<cfset param_name = "someParam_one">
...
<cfset param_value = Attributes[param_name]>
A shot in the dark:
There's a bug in CFMX where if you
make a CFMODULE call to a template (or
use custom tag) from within a CFC and
that tempate uses the CALLER scope to
return data, the data is never
available to the CFC function. This is
bug 51067 and it is related to the
VARIABLES scope bug, 45138.
Seen in the user comments in the CFMX 6 docs on CFMODULE.
Ok, we did something really stupid :-)
We had two set of these files deployed and one was updated while the other was not, thus the error.
Thanks for all your help.