Variable name in the method of ColdFusion Object - coldfusion

I am trying to set a variable in a cffunction.
The result is this:
<cfset local.layouts.appLayout = '../../app/layouts' & local.appController.new()>
The above code works. In the local.layouts.appLayout structure it assigns the return of the new method in the appControler. That is what I need it to do.
My problem is that I need to dynamically assign the method portion of that statement. I have another variable coreRoute.action that equals "new" in that function but I cannot seem to get the syntax right.
I have tried this:
<cfset local.layouts.appLayout = '../../app/layouts' & local.appController.coreRoute.action()>
That does not work and I can see why. I have also tried this:
<cfset local.layouts.appLayout = '../../app/layouts' & local.appController & #coreRoute.action# & '()'>
I have tried many variations of this syntax and I just cannot get it right.
Anyone have any ideas about how to do this. I am stuck.
Thanks in advance for any help.
UPDATE: With Todd Sharp's help I ended up using this and it worked great:
<cfinvoke component="#local.appController#" method="#coreRoute.action#" returnvariable="local.act">
<cfset local.layouts.appLayout = '../../app/layouts' & local.act>

You should look into using <cfinvoke> for dynamic method invocation. Try a Google search for "coldfusion dynamic method invocation" - here's one of the top results:
http://www.bennadel.com/blog/1320-ColdFusion-CFInvoke-Eliminates-The-Need-For-Evaluate-When-Dynamically-Executing-User-Defined-Functions.htm

In addition, if you want to do it entirely in script, you can, using this approach:
dynFn = this["foo" & bar];
dynFn(stuff);
This is in a cfc, if you're doing it from outside the cfc or not using a cfc at all, just change "this" to wherever your method is.

Related

Coldfusion opencsv csvWriter - I get writeNext method was not found

I have the following code:
<cfset csvFilename = 'myCSV.csv'>
<cfset fileWriter = createobject("java","java.io.FileWriter").init("#csvFileName#")>
<cfset csvWriter = createObject("java","com.opencsv.CSVWriter").init(fileWriter, ",")>
<cfset csvWriter.writeNext('{"1","2"}', true)>
<cfset csvWriter.flush()>
<cfset fileWriter.close()>
<cfset csvWriter.close()>
When I run the page I get this error message:
The writeNext method was not found.
Either there are no methods with the specified method name and
argument types or the writeNext method is overloaded with argument
types that ColdFusion cannot decipher reliably. ColdFusion found 0
methods that match the provided arguments. If this is a Java object
and you verified that the method exists, use the javacast function to
reduce ambiguity.
I have searched the internet and cannot seem to find any examples of using csvWriter with Coldfusion and I am not sure why it is not working. I have a working example of csvReader and ReadNext, but not WriteNext. Any ideas of what I am doing wrong? I have tried to do a javacast but that didn't work either.
<cfset csvWriter.writeNext(javacast("string",'1,2'))>
I am using Coldfusion 11 with opencsv-3.8.jar
According to the API, that overload of writeNext() expects a String[], or an array of Strings. CF arrays are a little different than Java's, but they are compatible. Either of these would work:
<cfset csvWriter.writeNext( ["1","2"], true)>
<cfset csvWriter.writeNext( javacast("String[]", ["3","4"]), javacast("boolean", true))>
As an aside, skip the call to fileWriter.close(). When you call CSVWriter.close(), it closes the underlying writer for you. Calling both will cause an error.
<cfset csvFilename = 'myCSV.csv'>
Without a full path, I am not sure where that file will end up. Always specifying a full path can save a lot of head scratching later on ;-)

fixing the url from the string using replace

I am doing a cfhttp call using a cfx_http5 tag as it is faster and better than cfhttp. so the links are coming as:
sort A
so i add the following script using the replace
http://mysubdomain.domain.com/http://mysubdomain.domain.com/e9.asp?rpttype=298&sortBy=1&sortOrder=2
<cfset lnk = ReplaceNoCase(objget, 'href="', 'href="http://mysubdomain.domain.com/', 'all')>
in few of the links, it is coming as correct but in few of the links it is coming as above appending one more to the already existing one,
so i want to make it conditional, if it exists, do not append or add or else add if there is no link
any ideas?
You can use regular expressions with negative lookahead like this:
<cfset lnk = reReplaceNoCase(objget, 'href=\"(?!http\:\/\/)','href="http://mysubdomain.domain.com', 'ALL')>
This will work for both type of links.
Simply create a conditional if statement
lnk = 'http://mysubdomain.domain.com/e9.asp?rpttype=298&sortBy=1&sortOrder=2';
if (!findNoCase('mysubdomain.domain.com', lnk)) {
lnk = ReplaceNoCase(objget, 'href="', 'href="http://mysubdomain.domain.com/', 'all');
}

CF10 Twitter4j lookupUsers method was not found or method is overloaded

I am using CFML and Twitter4j to return timelines and lists.
I want to return the data from a call to lookupUsers(java.lang.String[] screenNames)
via Twitter4j.
I have tried the :-
strList = createObject("java", "java.util.ArrayList");
strList.add(strOriginUser);
originUser = t4j.lookupUsers(strList);
And :-
strUserString = JavaCast("String", strOriginUser);
originUser = t4j.lookupUsers(strUserString);
I know the t4j Object is working as I already use it to get timelines etc but here it is for completeness :-
public function init_twitter() {
//CONFIGURE twitter4j
configBuilder = createObject("java", "twitter4j.conf.ConfigurationBuilder");
configBuilder.setOAuthConsumerKey(#application.twitter_consumer_key#);
configBuilder.setOAuthConsumerSecret(#application.twitter_consumer_secret#);
configBuilder.setOAuthAccessToken(#application.twitter_access_token#);
configBuilder.setOAuthAccessTokenSecret(#application.twitter_access_token_secret#);
configBuilder.setIncludeEntitiesEnabled(true);
configBuilder.setJSONStoreEnabled(true);
config = configBuilder.build();
twitterFactory = createObject("java", "twitter4j.TwitterFactory").init(config);
variables.t4j = twitterFactory.getInstance();
return this;
}
The twitter4j documentations is:-
ResponseList<User> lookupUsers(java.lang.String[] screenNames) throws TwitterException
Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two. The author's most recent status (if the authenticating user has permission) will be returned inline.
This method calls http://api.twitter.com/1.1/users/lookup.json
Parameters:
screenNames - Specifies the screen names of the users to return.
Returns:
users
It looks like you are trying to pass an ArrayList object into lookupUsers but that method only accepts String[] (an array of Strings) as an argument. So unless CFML does the conversion, I don't think it's going to work.
From a cursory glance at the ColdFusion docs, it looks like CFML can implicitly convert a CFML Array to a Java array, so perhaps the following would work:
screenNames = arrayNew(1);
screenNames[1] = 'Fry';
originUser = t4j.lookupUsers(screenNames);
Alternatively, if you want to keep on using a list there is an ArrayList#toArray(T[]) which could be useful, although I can't say how useful that would be in the CFML.
N.B. Please excuse my CFML code snippet.

coldfusion 9 dynamically call method

I'm attempting to build a method call from strings that have been passed into an object that refer to another object.
normally when calling an object we write the code like this:
application.stObj.oNewsBusiness.getNews(argumentCollection=local.stArgs);
However what I have done is created an array that contains the object name, the method name and the argument collection.
<cfscript>
local.stArgs = {};
local.stArgs.nNewsID = 19;
local.stArgs.sAuthor = "John";
local.aData = [];
local.aData[1] = local.stArgs;
local.aData[2] = "stObj.oNewsBusiness";
local.aData[3] = "getNews";
</cfscript>
however i am struggling to recombine all this to be a method call.
UPDATE using suggestion but still with issue
While cfinvoke seems to work for:
<cfinvoke component="#application.stObj.oNewsBusiness#" method="#local.sMethod#" argumentcollection="#local.stArgs#" returnvariable="local.qData"></cfinvoke>
it doesn't work when doing something like:
<cfscript>
local.stArgs = local.aData[1];
local.sObject = local.aData[2];
local.sMethod = local.aData[3];
</cfscript>
<cfinvoke component="application.#local.sObject#" method="#local.sMethod#" argumentCollection="#local.stArgs#" returnvariable="local.qData"></cfinvoke>
it generates an error:
Could not find the ColdFusion component or interface application.stObj.oNewsBusiness
CFInvoke is generally used to handle dynamic method calls.
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7e0a.html
CFInvoke has an argumentcollection attribute so you can pass your arguments in the way you are used to.
Dan is correct CFInvoke is the way to go
<cfinvoke component="#mycomponentname#" method="get" arg1="#arg1#" arg2="#arg2#" arg3=..>
<cfinvoke component="application.#local.sObject#" method="#local.sMethod#"argumentCollection="#local.stArgs#" returnvariable="local.qData"></cfinvoke>
from your update won't work because there are no # signs around the component variable.
You could do
<cfset local.componentName = "application." & local.sObject>
<cfinvoke component="#local.componentName#" method="#local.sMethod#"argumentCollection="#local.stArgs#" returnvariable="local.qData"></cfinvoke>
There's probably an inline way of combining application. with the variable on the cfinvoke call, but I don't know off the top of my head.
Edit: Dan Wilson's comment does it better in an inline way.

How do I run a static method on a CFC without using cfinvoke?

How do I invoke a static method on a CFC without using cfinvoke? I know that I can do this:
<cfinvoke component="MyComponent" method="myStaticMethod' arg1="blah" returnvariable=myReturnVar>
I would like to be able to invoke this method the same way I would a UDF:
<cfset myReturnVar = MyComponent.myStaticMethod(blah)>
This, however, does not work. Is there syntax that I am messing up or is this just not possible?
not possible, since there's no "static method" in ColdFusion.
The <cfinvoke> line in your question is the same as:
myReturnVar = CreateObject("component", "MyComponent").myStaticMethod(arg1="blah");
You need to create the object first.
<cfset MyComponent = createObject("component","MyComponent") />
<cfset myReturnVar = MyComponent.myMethod(blah) />
I know this is a really old post but here's an updated answer for more modern CF/Lucee supporting static constructs for anyone who might stumble across this like I did :-)
based off of:
https://modern-cfml.ortusbooks.com/cfml-language/components/static-
component MyComponent{
static {
appendToArgValue : "text"
}
public static function myStaticMethod( arg1 ){
return arg1 & static.appendToArgValue;
};
}
MyComponent::myStaticMethod("blah")
Lucee documentation: https://docs.lucee.org/guides/lucee-5/component-static.html