Calling the same ColdFusion component from different templates - coldfusion

In a.cfm I have:
<CFSET VerObj = New cfcomponents.VerFold.Ver_Users()>
<CFSET VerObj.Functiion_1(userid)>
In the next few templates, c.cfm, I need to call a different function within Ver_Users.cfc I can do:
<CFSET VerObj = New cfcomponents.VerFold.Ver_Users()>
<CFSET VerObj.Function_2(userid)>
If I need to call the same cfc again from yet another template down the road and I keep doing this I think it is very awkward and repetitive? the purpose of using .cfc is so that I can reuse or call the functions by just doing:
<CFSET VerObj,Function_1()> or calling Function_2
from anywhere without keep instantiating the cfc am I correct? is there any example on how to accomplish This?

Instantiating a component has a very small performance penalty. It is not false to re-instantiate it in different templates.
If you really want to cut away these few nanoseconds an bytes of memory you can instantiate the component one time at the onApplicationStart() event im your Application.cfc and store it in the application scope.
<cfset application.verUser = new cfcomponents.VerFold.Ver_Users()>
And then call the functions in your cfm like:
<cfset application.verUser.Function_1()>

#Rbt - you could create an Application.cfc that instantiates the Ver_Users component, and call application.Function1() and application.Function2() in your cfm files. You could create a session and use Session scope, or use Application scope which would treat it as a global, depending on how you want to use it.

Related

How to access predefined variables within cfscript?

The following code works:
<cfoutput>#$.currentURL()#</cfoutput>
However, within a function, "$" is not available.
<cfscript>
function myTest() {
return $.currentURL();
}
</cfscript>
Does anyone know what actually is the equivalent of $ within a function?
Likewise, #pluginConfig.getDirectory()# works when used directly in cfoutput. However, within a cfscript function, it reports "unknown variable pluginConfig."
Thank you for advance for guiding me in the right direction.
When writing code outside the Mura Event Scope (like you do with that function), you have to obtain an instance of the Mura Scope ($) yourself. This can be done using the following code:
$ = application.serviceFactory.getBean('$');
Next you'll have to initialise the instance using an event object, a struct with value pairs or a 'siteID':
$.init(event);
$.init(myStruct);
$.init(siteID);
The same counts for the pluginConfig, this you can abtain via the Mura Scope. You'll have to pass the pluginID, moduleID, name or package of the plugin:
$.getPlugin(pluginID);
$.getPlugin(moduleID);
$.getPlugin(name);
$.getPlugin(package);
An other option you have is to pass the Mura Scope and the pluginConfig as arguments to the function. When writing a small plugin, this might be the easier way. But when writting medium or large plugins, it will get a bit messy when you're passing along these objects all the time.
The $ is used as a special framework variable in some CF frameworks (like Mura). You will need to figure out the framework context (if any) your code is executing in

Cannot find qryname14411 key in structure

I have an error that seems to be associated with <cfscript> db operation
// traffic tracking
myQry = new Query();
myQry.setSQL("INSERT INTO dbo.Traffic (Circuit, Fuseaction, IP_hash) VALUES (:circuit, :fuseaction, :ip_hash)");
myQry.addParam(name="circuit", value="#listfirst(rc.fuseaction, '.')#", cfsqltype="CF_SQL_VARCHAR");
myQry.addParam(name="fuseaction", value="#listlast(rc.fuseaction, '.')#", cfsqltype="CF_SQL_VARCHAR");
myQry.addParam(name="ip_hash", value="#cgi.remote_addr#", cfsqltype="CF_SQL_VARCHAR");
myQry.execute();
The really strange thing is, it looks like the operation completed. What kind of a error is this?
Short answer: It's probably a scoping issue. Try:
var myQry = new Query();
Long-winded waffley answer:
I'd call it an Adobe-developers-being-useless kind of error.
If you look at line 460 of that file, you'll see the error is due to a failure of StructFind to find the query name in the variables scope, and the reason it's appearing in debug input is because there's a try/catch with type any surrounding it. The same functionality could be achieved without causing/catching an error by replacing the try/catch with <cfif StructKeyExists(variables,tagAttributes['name']) > which is basic CFML knowledge, and certainly something a developer of the CF product should know!
The same code still exists in the CF10 version of base.cfc, so you may or not feel like submitting it as a bug in Adobe's CF bugbase - though it's unlikely they'll fix it for CF9 (and uncertain whether they'll feel CF10 is worth the effort either).
However, that would only be side-stepping the issue of the variable not existing, not addressing the real issue of why it doesn't actually exist. Given that the debug info shows the query is successfully executing, and the query code is basically right above that line (starts at line 442), it shouldn't be a repeated/common error, but it may be due to your myQry variable not being scoped, and thus it could be colliding with another variable also called myQry (or even the same var from a separate call to the function) which is happening between the execution of the new Query() and .execute() lines, and thus causing the original query to not be there when the StructFind looks for it.
The solution is to put the keyword var before the first use of myQry which will place it in the local scope for that function - something that should be done for all variables that are only for use within an instance of a function, (otherwise they are placed in the variables scope of the component/request that the function exists within).

Unable to call inherited method on Java object from coldfusion

I'm using the twitter4j library and am having problems with one of the classes. In my code i get an instance of RequestToken returned from a function. I can dump the variable to the screen and see that is in fact the correct class. It has 2 public methods of it's own that i can use without issue, but it has 6 public methods inherited from OAuthToken that i can't use. Coldfusion throws an error when i try to access any of them:
Either there are no methods with the specified method name and argument types, or
the getTokenSecret method is overloaded with argument types that ColdFusion cannot
decipher reliably. ColdFusion found 0 methods that matched the provided arguments.
If this is a Java object and you verified that the method exists, you may need to
use the javacast function to reduce ambiguity.
some of the relevant code:
<cfset twitterFactory = createObject("java", "twitter4j.TwitterFactory").init(config)>
<cfset twitter = twitterFactory.getInstance()>
<cfset RequestToken = twitter.getOAuthRequestToken()>
<cfset TokenSecret = RequestToken.getTokenSecret()>
Dumping the RequestToken i can see the java class names in the dump, and it shows the methods.
The two methods i need to use are getToken() and getTokenSecret(). Neither take any arguments, so there's nothing to javacast.
Using coldfusion8, and the latest twitter4j release 3.0.3
Everything looks right to me: both the class and methods are public. It might be a bug. CF uses reflection to identify and invoke the methods. It usually gets it right, but not always. I have seen that happen once or twice in older versions. Usually with inherited methods.
If that is the problem, you could use reflection yourself as a work-around:
<cfscript>
emptyArray = [];
method = RequestToken.getClass().getMethod("getTokenSecret", emptyArray);
result = method.invoke( RequestToken, emptyArray);
</cfscript>

ColdFusion Application.cfc & cfinvoke & THIS scope

In using the CF application.cfc - there is a need to create some vars to begin with (in the THIS scope) - such as this.name and this.applicationtimeout() etc.
I ran across something I consider an odd behavior - and hope someone can explain why this happens and a possible workaround.
There are quite a few "THIS" vars accepted that can work to set application specific variables (of course you have to check "allow application specific vars" in the CFADMIN - which I did)
One of these is THIS.mappings - which is an array of mappings - MINE looks something like this:
this.path = GetDirectoryFromPath( GetCurrentTemplatePath() );
this.mappings = {
'/files' = '#this.path#_my_files\'
,'/functions' = '#this.path#_my_functions\'
,'/logs' = '#this.path#_my_logs\'
};
it works fine - when it is set inside a cfscript block at the top of the application.cfc
it works fine - if I put that script block in it's own file and cfinclude it in the application.cfc
however - In an attempt to segment my code - I wanted to put ALL of my application setting in a settings.cfc... (the thought here was IF some setting had to be changed - I wouldn't have to worry about 'where' to look, I don't really want to split the THIS stuff on my app.cfc and other application or session settings in the settings.cfc
SO I created a method in the settings.cfc called getTHIS, and I put the script block there... then used
<cfinvoke component="settings"
method="getTHIS"
returnvariable="THIS"
/>
Which WORKS - except (it seems) on the mappings...
The this.name etc, all seem to work and get set - as a matter of fact the this.mappings gets set fine too (so it appears) if i do a
<cfdump var="#THIS#" label="THIS" />
The dump is identical to the dump of THIS when I set it 'literally' on the app.cfc page..
HOWEVER - any attempt to call a template thru the mapping - results in a standard "if you want to use absolute paths you have to create a mapping blah blah..."
MY BIGGER goal was (on application start) to scan a directory for sub-directories, and create mappings based on certain sub-directories.. but if I can't abstract that functionality out into it's own function - I'll be forced to write it directly in the app.cfc (which wouldn't KILL me, but again, I was trying to segment my code logically... There seems to be a limitation of when and where these mappings can be set... true?
So I guess the big question is - can I SET this.mappings thru an outside method??
I guess I could bring back the 'settings I want' using the cfc call, and then just do the 'set this.whatever = return form cfc' - (this may be my answer...)
Thanks
Mappings can only be set in the 'pseudo-constructor' and not inside any of the methods inside Application.cfc - http://adobe.ly/QN2oX1
You could try setting this.mappings to the result of a CFC call (I cannot think of why this would not work), but if it depends on a mapping to do so, it will likely not work.
I haven't tested this, but I'm pretty sure it would work if your application.cfc extends your settings.cfc.
component {
public any function getMappings() {
var mappings = {};
//code to get your directories etc.
return mappings;
}
}
component extends="settings" {
this.name = "xxxx";
this.mappings = getMappings();
...
}

Undefined error when using CFThread in Custom Tags in ColdFusion 10

NOTE: I have completely rewritten this question to take into account new information. Please reread if you've already been through this one.
I'm getting errors when using a cfthread from within a custom tag in ColdFusion 10. In the Application log, I get the following entries:
Variable _cffunccfthread_cfThreadTag2ecfm16902001291 is undefined.
The name of the function it's returning as an error is _cffunccfthread_cf[Page Name Calling the CFThreadTag] then a number that doesn't change from request to request. I can duplicate this every time with the following code:
Application.cfc:
component
{
this.name = "CFThreadCustomTagTest";
}
ThePage.cfm:
<cfthread action="run" name="ThreadTestInPage">
<cflog log="Application" text="The thread in the page successfully ran" type="information" />
</cfthread>
<cf_ThreadTag />
ThreadTag.cfm:
<cfif thisTag.ExecutionMode EQ "start">
<cfthread action="run" name="ThreadTest">
<cflog log="Application" text="The thread within the tag successfully ran" type="information" />
</cfthread>
</cfif>
Just drop all three files in a directory in ColdFusion 10 and load ThePage.cfm. I get the following entries in the Application log:
"Severity","ThreadID","Date","Time","Application","Message"
"Information","ajp-bio-8012-exec-1","06/19/12","07:18:11",,"C:\ColdFusion10\cfusion\logs\application.log initialized"
"Information","cfthread-11","06/19/12","07:18:15","CFTHREADCUSTOMTAGTEST","The thread in the page successfully ran"
"Error","cfthread-9","06/19/12","07:18:15",,"THREADTEST: Variable _cffunccfthread_cfThreadTag2ecfm16902001291 is undefined. "
I also noticed that in the error for the thread within the custom tag, it does not contain the application name. While the log entry for the thread in the page does. Notice that the error line simply has ,, for the Application column of the log, while the successful thread has "CFTHREADCUSTOMTAGTEST".
If I change ThreadTag.cfm to wait for the thread within the tag to finish processing, then everything works fine, and I get the two entries in the log as I expect:
<cfif thisTag.ExecutionMode EQ "start">
<cfthread action="run" name="ThreadTest">
<cflog log="Application" text="The thread within the tag successfully ran" type="information" />
</cfthread>
<cfthread action="join" name="ThreadTest" timeout="10" />
<cfdump var="#cfthread#">
</cfif>
And to verify that there are no funky settings anywhere, here's my local development environment's settings summary.
So it seems that if I just throw the thread out there, and don't wait for it to finish, then the thread seems to be looking for something from the parent page that is no longer in memory. At least that's my completely unfounded guess :).
I've also filed a bug with Adobe. Bug number 3218452.
I understand your predicament, but there's no actual question here.
Basically you've found a bug in CF. A few people - myself included - can replicate it.
No-one's missing anything, except for the Adobe engineers who missed including this sort of thing in their regression testing when implementing CF10. That's no indictment of them, really, as I think this is reasonably edge case, perhaps?
The "variable" CF ain't finding is actually the name of the compiled class that the CF compiler makes when compiling the code. It looks like there's a compiler bug to me.
For example, my error is this:
THREADTEST: Variable _cffunccfthread_cfThreadTag2ecfm13713410591 is undefined.
However the compiled class is:
cfThreadTag2ecfm1371341059$func_CFFUNCCFTHREAD_CFTHREADTAG2ECFM13713410591.class
I don't know what part of the class name the variable is supposed to be named for, but I suspect it should be looking for func_CFFUNCCFTHREAD_CFTHREADTAG2ECFM13713410591. Or on the other hand the compiler should not be compiling the ThreadTag.cfm file as a FUNCTION? But I'm guessing... it might need to compile the thread code as a function so as to call it in a separate thread? That's a guess. Either way: it's compiling the code as one thing, and then looking for a different thing. because of a bug.
But bottom line here: yep, you've found a bug. And you've flagged it with Adobe. I dunno what else there is for you to do here?
So basically we now know one cannot have a <cfthread> call in a custom tag (I also tested via <cfmodule>: same problem). You're gonna have to write yer code a different way, using an include or a method or something. Less than ideal, I know, but what can you do?
Footnote:
I looked at the compiled code and it looks like the problem is CF is compiling the class with that func_ prefix, but it's referring to it in its code without. I didn't follow the code all the way to checking everything that's happening, but it looks to me like there are references to it trying to load _cffunccfthread_cfThreadTag2ecfm13713410591 rather than the correct name: func_CFFUNCCFTHREAD_CFTHREADTAG2ECFM13713410591.class.
Dan,
Please look on this page:
http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSc3ff6d0ea77859461172e0811cbec0b2e1-7ff0.html
And this section "Determining the tag execution mode"
And try the equivalent mode check code <cfswitch expression=#thisTag.ExecutionMode#>
To see if this causes a different compiler code gen. Maybe it will gen code a bit different and the variable will get generated.
Also, another test to try is to put you tag first in "ThePage.cfm" and see if that causes a different code gen as well.
Finally, are you on a newer JVM, as newer ones use the latest Fork/Join features of the Java concurrency approach such as Futures, etc. and they may be causing different code gen. Maybe set your JDK to an older one and see if the code gen is different.
No real answer, but some things to look at.
I ran into this as well.
My solution was to refactor and put the cfthread stuff into a .cfc and call that from the .cfm page.