Saturday, March 28, 2009

CF: Unable to perform cfflush in cffunction

OK. This is not an obvious one, so I decided to document this behavior.
Say you have several functions in components processing away happily, and you want to give the user some feedback to keep him/her entertained as well as keep their paws of the back buttons etc..
You think doing couple of flushes during your processing may be a good way until you try and get this error:

Unable to perform cfflush.

You have called cfflush in an invalid location, such as inside a cfquery or cfthread or between a CFML custom tag start and end tag.


What to do? Since none of the hints apply to you. Your code looks like this:

<cffunction name="fFlushIt" hint="flushes current content">
<cfargument name="feedback" default="">

<cfoutput>#Arguments.feedback#</cfoutput>
<cfflush>
</cffunction>

<cffunction name="fProcessing" returntype="numeric"
hint="does processing" output="No">

<cfset var x=10>
<cfset var y=20>
<cfset fFlushIt("Processing Complete")>

<cfreturn x + y>
</cffunction>

<BR>
<cfoutput>The result is: #fProcessing()#</cfoutput>


here comes the digging into the code and making guesses part. It seems that there is one more scenario cfflush won't like and this is if you call in within a call-tree (yes even nested stuff) in a function that has the output attribute declared as "No". Maybe a hint like that could be placed in the error to avoid all that brain scratching and wondering that goes along with this?
Anyways change the function like this and it worked. Yeah !



<cffunction name="fProcessing" returntype="numeric"
hint="does processing" output="Yes">




Cheers,

Thursday, March 26, 2009

Oracle: PLS-00103: Encountered the symbol ""

Triggers, triggers and more triggers.
Thousands of them. Ran the scripts into Oracle using ColdFusion instead of SQLPlus only to find out that I now had thousands of invalid triggers.
A little puzzling, as the same scripts worked like a charm everywhere else. I go use the oracle web enterprise manager to see whehter I can recompile them and make a few valid. Nada!
Everytime the Enterrpise manager tries to compile the trigger I get the error:

PLS-00103: Encountered the symbol ""

Here is a sample trigger with issues:

CREATE OR REPLACE TRIGGER INS_MySuperTrigger BEFORE INSERT ON
MySuperTriggerTable REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
DECLARE
newid NUMBER;
BEGIN
If :new.MySuperTrigger_ID IS NULL THEN
SELECT SEQMySuperTrigger.NextVal INTO newid FROM dual;
:new.MySuperTrigger_ID := newid;
End If;
END;


This is nuts. I use the generate SQL button of Enterprise manager to generate the SQL and copy and paste it into the Oracel SQL Developer UI, run the code without mods, and bingo; the trigger is valid and happy as a peach.

What gives? Long hours wasted with different websites and options, casing, single and double quotes, Egyptian prayer beads..., you name it, I tried it.
Until pulling a protocol sniffer to see what the difference is between Oracle Enterprise Manager and Oracle SQL Developer on the wire.

Come to find out Oracle does not recognize Windows CRLF (Chr(13) + Chr(10)) as blank space, if you replace all the CRLF with LF this works like a charm. Seemingly, web based Oracle Enterprise Manager does not do this translation, while the Oracle SQL Developer tool does. Yack! Lesson learned, I now run the scripts through a parser before running them to Oracle via JDBC and get valid triggers all the time.

Cheers,

Tuesday, March 24, 2009

MySQL: frustration with login at the command prompt or the space character mystery

Many years ago when trying to use MySQL I ran into this, but only get to note it down now because someone else run into this problem. I searched and lo and behold not much info out there, so I thought maybe a couple of pointers would be worth while.
When using the command line mysql tool you can specify the username and password of the user during login.
Many manuals describe the syntax as:

mysql -h hostname -u root -p password
or
mysql --user=user_name --password=your_password db_name

You think wow this is easy, right. I can interpret this very simply.
I go to the command prompt and type:

C:\>mysql --user=root --pasword=mypass

but to my astonishment I would get:

mysql: unknown variable 'pasword=mypass'

Here are couple of other beauties that are in the manuals and don't work at all like expected:

C:\>mysql -u root -p mypass
Enter password: ******
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

This could be very frustrating to someone new to MySQL on windows. Can't even login to get the client program started.

The approach I found working for windows based installation is to ignore the manual and avoid space between parameters.
Thus rather than using -u root, you will need to use -uroot. This will magically work. E.g.:
C:\>mysql -uroot -pmypass
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19Server version: 5.0.67-community-nt
MySQL Community Edition (GPL)
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>


Hope this will avoid some frustration out there.
Cheers,

Thursday, March 19, 2009

CF: ColdFusion functions and the case of the mysterious space

Spent lots of time trying to find out why a space was returned from a function call to a function in a component. We would place the output directly into a html form text control, but a space would always be added to the front of the expected return string.
Broke out the old Hex editor to save and check file contents. Output each character at a time, just could not see why this would happen.
Many hours later, a headache started to kick in. Time for a break. Then, a hunch started knocking at the back of my scull and got louder and louder.
To prove it to myself, I created an intermediate variable into which I stored the function result. When this scheme was used, no space. If I used the function output in place, space! It turned out to be the Output attribute of the function definition. You will need to set it to 'No'. If you leave it off and attempt to use the function in place, Coldfusion will introduce a space in the return. Very, very annoying.

Here is sample code to reproduce the problem, two function that are identical except one has the output attribute specified; if you use the function 2 inline CF will produce a space in front of the output; see the output for f2 below:


<cffunction name="fFunction1" output="No">

<cfset var strReturn ="Hello World">
<cfreturn strReturn>
</cffunction>

<cffunction name="fFunction2" >
<cfset var strReturn ="Hello World">
<cfreturn strReturn>
</cffunction>

<cfset sOutput1=fFunction1()>
<cfset sOutput2=fFunction2()>

<cfoutput>
f1:--#fFunction1()#--
<BR>
o1:--#sOutput1#--
<BR>
f2:--#fFunction2()#--
<BR>
o2:--#sOutput2#--
<BR>
</cfoutput>

Output:

f1:--Hello World--
o1:--Hello World--
f2:-- Hello World--
o2:--Hello World--

Monday, March 9, 2009

CF: ColdFusion Impact of Content Type Declaration on the HTTP header with application/octet-stream

So, I encountered this little problem with XML transmissions for a customer. They would receive regular XML streams to update their data and all was working dandy, until one it didn't ;o)
To CF it looked like all of a sudden the content of the HTTP traffic vanished, in other words we did not seem to have anything in GetHttpRequestData().content except for empty string.
Of course, no one fessed up to having changed anything at all, so here I go digging through code and cannot find anything obvious and, then, I turn out the big guns: Protocol Sniffers and packet capture.
Hah, I think, now I can show them that they are not sending any content, but instead I can see the content clearly in the packet capture which starts heavy head scratching and coffee sipping.
More looking into code and I find that the only time we bypass GetHttpRequestData().content is if we are running a binary check, e.g. we have this condition:
IsBinary(GetHttpRequestData().content)
From the protocol packets I can clearly see that the content is not binary so, at first, I cannot imagine how this condition would be even trigger and bypass the remainder of the processing until, seing the light, I remove the condition.
Bingo, now I can see content but it is all wrong. It looks like CF has processed the content of the transmission to numeric values instead of XML strings.
Dang!
So in the end, more digging to see that the http content type declaration of the originating transmission had changed from text/xml to application/octet-stream; it looks like whenever CF received this it automatically converted the perfectly fine XML into an octet stream, which, then, turned the content to be binary data instead of leaving it as simple string. A simple misdeclaration by the customer which caused this hoopla.
So after much searching I wish I could have been able to tell the RAW data in the transmission from the interpreted data. This would have made the diagnosis much simpler. So Adobe, in the future please consider adding the raw information to the GetHttpRequestData function, so we don’t have to guess what parts are being interpreted and what the transmission contained.
For now, I went back to the customer and asked them to correct their content declaration.