Hi I have a component that contains getters and setters, which is fed by a structure for session variables.
When I call the component and use cfoutput tag for that getter and setter the output is giving gibberish as results.
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_ADDRESS_ZIP_CODE#6187548c cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_FLAGS#7bbfe559
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_FLAGS#7bbfe559
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_RECORD_NUMBER#736a7587
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_RECORD_NUMBER#736a7587
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_ADDRESS_ZIP_CODE#6187548c
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_ADDRESS_ZIP_CODE#6187548c
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_WEIGHT#524a2d43
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETCUSTOMER_WEIGHT#524a2d43
cffunctions_allDefinedSessnFunct2ecfc3324199482$funcGETVIN#3e1b3ea
When I do a CTRL+F for the variable values passed, I find them below in the ColdFusion Debugging Information.
I want to get the requisite cfoutput values, which i was getting as desired previously .
by all accounts I'd say you're outputting the component itself instead of one of its string properties. Check your output code.
Are you doing this?
<cfset allDSF = createObject("component", cfc.allDefinedSessnFunct") />
<cfoutput>#allDSF.getCUSTOMER_ADDRESS_ZIP_CODE()#</cfoutput>
Some code would help us to help you...
Related
Hopefully this is a "DOH" moment but I can't figure out why this is happening. I am using a service object to get the members of a group in Google's Directory API. After creating the service object I used the following lines to test
<cfset themembers = groupservice.members().list("[My Group Key]").execute()>
<cfdump var="#themembers#">
<cfoutput>
Isnull? #isNull(themembers.etag)#<br />
SKExists? #structKeyExists(themembers,"etag")#<br />
Is Defined? #isDefined("themembers.etag")#
</cfoutput>
The resulting output of the code looks like this
Looking at the dump I can see there is data in the etag field as well as an array of members. However, when I tried to output the key value I was getting an undefined error. I wrote a test output line and it's showing as NULL and not defined while the key DOES exist.
How is this possible when the dump of the variable clearly shows data? What am I missing here?
#Leigh
<cfdump var="#groupservice.members()#">
<cfdump var="#groupservice.members().list('[groupkey]')#">
Here are the dumps from the 2 lines above. The list method simply returns the groupkey name that i'm passing in - it's only after I run the execute method do I actually get the list of members (output in first image) but just like with the etag - it tells me members is undefined.
Short answer:
Apparently this falls under the general rule of "Never trust CFDump. Sometimes it lies." Case in point, the variable themembers is not really a structure. It is an instance of the Members class. Instead of using dot notation, try invoking the relevant methods of the class:
<cfset eTag = themembers.getETag()>
<cfset membersArray = themembers.getMembers()>
..
Longer Answer:
While CFDump is a good debugging tool, it tends to favor "pretty presentation" over accuracy, so you cannot always trust what you see. The reason it displays themembers as a "struct" is because ColdFusion automatically matches Java types to ColdFusion types. If you take a look at the class hierarchy of Members, you can see it implements java.util.Map (via AbstractMap), which is automatically matched to a CF structure. Hence why CFDump (misleadingly) displays it as one.
- com.google.api.services.admin.directory.model.Members
- com.google.api.client.json.GenericJson
- com.google.api.client.util.GenericData
- java.util.AbstractMap
- java.lang.Object
Although java objects are similar to structures, in some respects, they are not the same thing. So the results from certain functions may differ from what you would normally expect for structures, which is what happened here. i.e. You can view some of the property names, like you can with structure keys, but you cannot access the key/property values directly.
That said, technically you should have been able to access the "eTag" and "members" properties with dot notation. The reason being that CF applies a bit of syntactic sugar to certain java objects to allow direct access of properties using dot notation. Just as if they were regular structure keys.
ColdFusion can automatically invoke get_PropertyName_() and
set_PropertyName_(value) methods if a Java class conforms to the
JavaBeans pattern. As a result, you can set or get the property by
referencing it directly, without having to explicitly invoke a method.
However, as the docs note later on, there are some exceptions. This class appears to be one of them. So you will need to call the appropriate getPropertyName() methods explicitly. Ultimately, that is probably the best practice anyway, given that direct access does not always work.
Example:
// Simulate Members object
obj = createObject("java", "com.google.api.services.admin.directory.model.Members").init();
// Initialize property values
obj.setEtag("If you are seeing this text, it worked.");
obj.setMembers( [] );
writeOutput("<br>IsNull? "& isNull(obj.etag));
writeOutput("<br>Key List: "& structKeyList(obj));
writeOutput("<br>Exists? "& structKeyExists(obj, "etag"));
writeOutput("<br>IsDefined? "& IsDefined("obj.etag"));
writeOutput("<br>getETag(): "& obj.getETag());
writeDump(var=obj.getMembers(), label="getMembers()");
Results:
IsNull? YES
Key List: etag,members
Exists? YES
IsDefined? NO
getETag(): If you are seeing this text, it worked.
getMembers(): (empty array)
The way I get around the undefined structure values is to use structKeyArray to make an array of the keys in the struct. Then, loop over the array to check if the struct key exists. Example:
//result is a structure which can have undefined values
myAry = structKeyArray(result);
myLen = arrayLen(myAry);
for (i=1; i <= myLen;i=i+1){
if(!structKeyExists(result, "#myAry[i]#")){
result[myAry[i]] = "";
}
}
Of course, you might not want blank strings, but in my circumstance, that is what I was looking for if it didn't exist.
I have a table with values under a column named:str_condition
values in this column can be : variables.bit_male / application.bit_male / isdefined('session.int_user_id')
The value can be complex as it can be.
I need to use the value of the values in the column.
Currently, what I am doing is
<cfif evaluate(query.str_condition) eq true>
.....code....
</cfif>
Now, I need to omit the evaluate.
TBH, I'd stick with evaluate() for this: you're leveraging one of the few situations it makes sense. Provided what you have in the DB field is just an expression (no tags), then evaluate() will work fine.
As others have suggested... storing expressions in the DB is not ideal, but I can see how sometimes it might be the best approach, However do reconsider it though, in case you can come up with a different approach entirely (this is situation-specific, so we can't really give you guidance on that).
The only other real option for you would be to write the code from the DB to file then include it, but that would be a worse solution than just using evaluate(), I think.
A lot of people get hung up on the dogma that is evaluate() is bad, without really stopping to think about why that's the case... it's unnecessary for most situations people use it, but it's completely fine in situations in which it is needed (such as yours).
This is an edited answer, since I originally misread the question.
In many cases, array notation is your freind
<cfif queryname['fieldname'][rownumber] is true>
code for true
Note that the queryname is not quoted but the fieldname is. If you don't quote the fieldname, ColdFusion will assume it's a variable.
Also pertinent is that if you are storing things in a database, such as code, that you want to select and then execute, you have to select those things, write them to another .cfm file, and then cfinclude that file. That's somewhat inefficient.
In your case, you are storing variable names in your database. If using evaluate is giving you the correct results, anything you change would likely be a change for the worse.
How many unique combinations exist in the database? And do new values show up without developer interaction?
If it's a reasonable number of possible values that don't change then use a switch statement and write the line of code that handles each possible value.
<cfswitch expression="#query.str_condition#">
<cfcase value="variables.bit_male">
<cfset passed = variables.bit_male>
</cfcase>
<cfcase value="application.bit_male">
<cfset passed = application.bit_male>
</cfcase>
<cfcase value="isdefined('session.int_user_id')">
<cfset passed = isdefined('session.int_user_id')>
</cfcase>
<cfdefaultcase>
<cfset passed = false>
</cfdefaultcase>
</cfswitch>
<cfif passed>
.....code....
</cfif>
You don't have to hand write all of them, you can use a sql query to generate the repetitive part of the coldfusion code.
SELECT DISTINCT '<cfcase value="' + replace(table.str_condition,'"','""') + '"><cfset passed = ' + table.str_condition + '></cfcase>' as cfml
FROM table
ORDER BY len(str_condition), str_condition
If I am reading this correctly you are not just storing variable names in the database but actual snippets of code such as [ isDefined(session.it_user_id) ].
If this is what you are doing then you need to stop and rethink what you are trying to achieve. Storing code in your database and using evaluate to execute it is an incredibly bad idea.
It sounds to me like you are trying to create a generic code block that you can copy paste in multiple places and just set your conditional logic in the db.
The short answer is not to find a way around using evaluate but to stop storing code in your database full stop.
We are trying to display a record set in a webform using the cffunction in ColdFusion.
But we are unable to display the ouptut..We are just getting a single value(last value in the record set).The sql function is returning ref cursor.Please help us resolve this issue!
thanks!
<cfset bare_drive_result = functionname('x','y')>
<cffunction name="functionname" hint="Gets all customer from the database" returntype="query">
<cfargument name="sPcwQua" type=any>
<cfargument name="sPcwAcc" type=any>
<cfquery name="getRkBareDrive" datasource= "#PCW_dsn#">
select pacakagename.functionname('#sPcwQua#','#sPcwAcc#') bare_drive_result
from dual
</cfquery>
<cfreturn getRkBareDrive>
</cffunction>
<cfoutput>#getRkBareDrive.bare_drive_result#</cfoutput>
You have a scoping issue. The name of the query inside your method is getRKBareDrive, however, you are setting the result of that function call to another variable name - bare_drive_result.
The code would actually be:
<cfoutput query="bare_drive_result">#bare_drive_result.bare_drive_result</cfoutput>
And inside your function, you need to add this line just after the cfargument tags:
<cfset var getRkBareDrive = "" />
However, that does not solve your immediate problem. Have you tried doing:
<cfdump var="#bare_drive_result#" />
to see what is actually returned to ColdFusion
Everything #Scott Stroz said in his answer is true - 1) you are confusing variable names between the code and the inline function, 2) use a var scope to define the getRKBareDrive variable inside your function (not directly part of the issue being an inline function, but good practice), and 3) try to CFDUMP the result instead of CFOUTPUT it. However I don't believe the core issue is addressed, which lies with this part of your question:
The sql function is returning ref cursor
So one glaring issue is that you are returning a REFCURSOR not a simple value, so you cannot just CFOUTPUT it but instead need to take certain steps so ColdFusion knows it is a query set. REFCURSOR can be returned in calls from Stored Procedures via CFPROCRESULT (or via CFPROCPARAM type="OUT" CFSQLType="CF_SQL_REFCURSOR" if it's a returned parameter not a result).
So... try coverting the CFQUERY call to a CFSTOREDPROC. Here's some sample code that assumes you can call your package/function directly as a stored proc vs through a query. I removed the inline function as it's adding too much complexity here (again see Scott's answer) -- just try bare code as a way to get the call working.
<cfstoredproc procedure="pacakagename.functionname" datasource= "#PCW_dsn#">
<cfprocparam type="IN" CFSQLType="CF_SQL_VARCHAR", value="x">
<cfprocparam type="IN" CFSQLType="CF_SQL_VARCHAR", value="y">
<cfprocresult name="bare_drive_result" >
</cfstoredproc>
<cfdump var="#bare_drive_result#">
If you see results in the dump, you should be able replace the dump and output the fields within the ref cursor just like a normal CFQUERY result within a CFOUTPUT query="bare_drive_result" call.
From CF8 documentation on CFPROCRESULT:
CFML supports Oracle 8 and 9 Reference Cursor type, which passes a
parameter by reference. Parameters that are passed this way can be
allocated and deallocated from memory within the execution of one
application. To use reference cursors in packages or stored
procedures, use the cfprocresult tag. This causes the ColdFusion JDBC
database driver to put Oracle reference cursors into a result set.
(You cannot use this method with Oracle's ThinClient JDBC drivers.)
Try this
<cfoutput query="getRkBareDrive">#getRkBareDrive.bare_drive_result#</cfoutput>
I suspect Scott's solution will help you out, though if you are still having issues you can add a result parameter to your query to help troubleshoot & see exactly what is being passed.
<cfquery name="getRkBareDrive" datasource= "#PCW_dsn#" result="qryname">
then dump that:
<cfdump var="#qryname#" />
The returned structure should show you the query passed in, number of results etc [i suspect it is actually returning only one], see the full description here: http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_p-q_17.html
I have a query that I am calling to update an email service. Most times it will have data in it, but in testing I came across the situation of it not returning any data because there was no data to return. In the case of no data it returns the error "Variable EDITEDACCTS is undefined".
I have tried wrapping the query in a <cftry> but it doesn't "fail" per se so it does not trip the <cfcatch>. I have also tried defining the variable
var EditedAccts = QueryNew("")
as well as simply trying
<cfif NOT isDefined(#EditedAccts#)>
and it always returns "Variable EDITEDACCTS is undefined".
I need a production ready solution to this and I'm hoping somewhere here on SO can help me out.
Thanks in advance for your help.
I have just found the answer. You set the "result" parameter in the query call and then you can check the recordcount field returned.
<cfquery name="EditedAccts" datasource="mydatasource" result="queryResult">
...query goes here...
</cfquery>
When using the "result" parameter you get a struct returned with the sql used, the cached setting, the execution time and the record count.
Now I can check the record count and proceed from there.
Hopefully this will help someone in the future.
I tried using result="queryResult" but when I tried to reference the query name I got something like this error - "The value of the attribute query, which is currently EditedAccts, is invalid". Instead, I used something like IsDefined("#EditedAccts#") - including the value in quotes did the trick for me. I am only new to ColdFusion but I am learning quickly that values in quotes are entirely different to values not in quotes, in terms of how a function will interpret a parameter.
I am unable to retrieve any data from my cfquery. Same query when i run in sql developer i get the result.
Any reason why ?
Hi all, thanks for the responses. Sorry, it was my fault.
It was a data issue. I was retrieving uncommited data from CF.
You can also build the query in CFEclipse, test it and then paste the query in your CFQuery tag.
Also check how you have put the query name in the CFoutput tag, so many times I've put #queryname# instead of queryname in cfoutput.
Is the query actually being ran?
If you can turn debugging on, does the query show as being executed?
Also when you run the same query do you mean you copy/paste the query from the debugger into sql developer?
Perhaps the same values are not being included (if you are using variables in there)