Its JSON, I swear

I am mostly bogging this so I don't forget this stupid mistake I made. I am using jQuery to make an ajax call to a CFC. The CFC returns json data that I am using to populate a form.

The call worked just find and data was returned. However, for some reason, in JavaScript the JSON data was not being treated as JSON. I spent ages searching for solutions and doing trial and error.

This is the JavaScript call I was making:

view plain print about
1function getDetail(item){
2 $.ajax({
3 url: '/components/packages.cfc?method=getPackageByID',
4 cache: false,
5 type: "get",
6 data: {
7 packageid: item
8 },
9 success: function(data){
10 console.log(data.DATA);
11 }
12 });
13 }

This is the CFC that returned JSON.

view plain print about
1<cffunction name="getPackageByID" access="remote" returnformat="JSON" >
2        <cfargument name="packageid" required="true" type="numeric" >
3        
4        <cfset var getdata = "">
5        
6        <cfquery name="getdata" datasource="#request.dsn#" >
7            select * from package
8            where packageid = <cfqueryparam value="#arguments.packageid#" cfsqltype="cf_sql_integer" >
9        </cfquery>
10    
11        <cfreturn getData>
12    </cffunction>

Knowing what I know (which I started to question) I should have been able to use "data.DATA" to get to the JSON data in the result. However, when I output it to the console I would get "undefined". I also tried, among other things, "data[0]" which got me "{".

The lovely kicker was that the Chrome debugger network tab showed the call return as JSON.

I continued to try anything I could think of to get JavaScript to understand the return as JSON. All I ended up doing was finding a ton of ways to not process JSON.

Finally, I figured something out. It finally dawned on me that JavaScript was processing the data as a string not JSON. The "Intelligent Guess" feature of $.ajax() in jQuery was apparently failing to see the data as JSON.

I then added " dataType: 'json' " to the ajax call. Once I did that everything started working as expected.

If there is a moral here I would say it is to not expect data types to be auto assigned correctly. If you can, define what the data types will be. this will save you pain and anguish later.

Till next time...

--Dave

ColdFusion Developer Week

Time to get your learning on.. for FREE. Check out Adobe ColdFusion Developer Week for a weeks full of great sessions for the new and old alike.

I am especially excited about this as I am one of the speakers. I will be talking about ColdFusion and Mobile.

Check it out and sign up. http://www.adobe.com/cfusion/event/index.cfm?event=detail&id=1489920&loc=en_us

Till next time,

--Dave

CFLocation and hash based navigation

I was working to correct a bug in BlogCFC mobile. The bug happened when a user clicked on a link in an email notification they would get redirected to a blank screen. This would only happen when clicking on a link that was to a specific comment. My initial thought that the redirect link was being generated wrong because of the hash. This was not true, it was generated correctly.

For example, if this was the link to the post

http://blog.dkferguson.com/index.cfm/2011/6/3/BlogCFC-renderer-article

it would be redirected to the following if a user was on a mobile device

http://blog.dkferguson.com/mobile/index.cfm#./postDetail.cfm?post=5E2708D6-A21B-65AC-2232595C693D293D

This worked just fine. User would be taken to the correct post as expected. However, if the link was to a comment it would look like this:

http://blog.dkferguson.com/index.cfm/2011/4/5/jQuery-Mobile-Feed-Viewer#c843D1743-0227-884E-B34C31C282C6B66F

Then redirect to this:

http://blog.dkferguson.com/mobile/#postDetail.cfm?post=82608F56-B34A-2BEB-ECBC47375279E7E2#c843D1743-0227-884E-B34C31C282C6B66F

This redirect is where it was broke. First off, as you can see, there are two hash tags in the url. Secondly, nowhere in the redirect code is there anything to add the original hash to the comment. I know that because of how the mobile version works; linking directly to the comment won't work.

view plain print about
1<cfif isClientMobile()>
2    <!---Mobile Redirect--->
3    <cfset urlVars= listFirst(reReplaceNoCase(trim(cgi.path_info), '.+\.cfm/? *', ''), "##")>
4    
5    <cfif listlen(urlVars, '/') LTE 1> <!---NOT AN SES URL--->
6        <cfset urlVars = ''>
7    </cfif>    
8    <cfset path = cgi.http_host & ListDeleteAt(cgi.script_name, listLen(cgi.script_name, "/"), "/")>
9    <cfif NOT right(path, 6) EQ "mobile">
10        <cflocation url="http://#path#/mobile/index.cfm#urlVars#" addToken="false">
11    </cfif>
12</cfif>

I was using cflocation to perform the redirect so the extra hash puzzled me even further. I would not have expected the original hash to be there. After a ton of digging, I stumbled across something. The hash was being maintained and added to the redirect by the browser. A quick search on the net produced a few articles that discussed this very issue. The hash is never passed to the server. So, looking at the cgi scope or any other scope would never produce the hash or even elude to the fact that there was one there.

Now, after reading all this I understood what was happening. The extra hash was tripping up jQuery Mobile. It was trying to load a non-existent page. So, what I had to do was remove the hash to the comment from the url.

I tried a bunch of different things. But, as long as I was using cflocation I would never get around it. I had to do the redirect client side. Normally, I am not opposed to this. However, mobile is different. I now have to rely on a mobile browser. Something that can be unreliable for many reasons.

I first tried to do the redirect with JavaScript. This worked just fine. I just did a window.location and the user was redirected to mobile and the original hash was gone. I also tried doing with a meta tag. This also produced the same result. Now, to choose what to do.

In the end I went with the meta tag. Mostly because it ended up to be less data transfer and faster. I also didn't have to worry about the client processing JavaScript for the redirect.

So, what did I learn? Hash navigation is appended to a cflocation by the browser if relocating to the same domain. A relocation to another domain won't append the hash to the url. A client location change via JS or meta tag will remove the hash.

I hope you learned something from this as well.

Till next time...

--Dave

Hashing files and Java heap space

So, for those that did not know. The hash() function in ColdFusion can do a cool trick. It can generate a md5 hash of a file. Why would you want to do this? Well, if you want to compare 2 files at the byte level a hash is the best way. IF the files are identical byte for byte the hash will be the same. if one byte in the file changed the hash changes. The change could be something as simple as changing a file attribute or an update to its last modified date.

Here is the code to do it. It is very simple.

view plain print about
1<cfset fileHash = hash(FileRead(myfullFilePath), 'MD5')>
This code would result in something that looks like this: 6168f305888c3d795e67c6de17bf8a21

This works perfectly in about 90+% of all cases. However, in what I was doing it worked in about 5% of all cases. The simple fact is that I was trying to hash files that were in the 250mb+ range. When doing this my server would start generating this lovely error:

view plain print about
1"Error","Thread-26","12/29/09","15:27:48",,"Error invoking CFC for gateway ProcessFile: Java heap space."
2java.lang.OutOfMemoryError: Java heap space
3    at java.util.Arrays.copyOfRange(Arrays.java:3209)
4    at java.lang.String.<init>(String.java:216)
5    at java.lang.StringBuffer.toString(StringBuffer.java:585)
6    at coldfusion.tagext.io.FileUtils.readFile(FileUtils.java:174)

I have not been able to determine the exact file size that causes this. I have seen it with files as small at 50mb. But, I do see it very regularly with files over 100mb. I have also not found a way around it yet. I currently just wrap the code inside a cftry to suppress the error.

Till next time...

--Dave

Ugh.. not again.. More technology on death's door

Well, it happened again, someone went and published a list of the top 10 dying IT skills (http://www.globalknowledge.com/training/generic.asp?pageid=2347&country=United+States. I bet you can't guess what was on the list. Yep, you guessed it, NetWare. However, to be fair, NetWare has been on every dying list for years. Beyond NetWare, the other item to make the list was our beloved ColdFusion. However, this does not surprise me. ColdFusion gets added to every dying list for the past few years. However, it is still going strong and getting stronger.

Now, this list got me to thinking. Who generated this list and what qualified them to make it. Also, what qualifications did they use to generate the list. Based on the article, the writer apparently used a job search count from a site I had never heard of (Indeed.com).

Ok, so this seems like a lame reason to say it is dying. Based on the article alone, I don't think the writer did very much research.

Then the list went on to name HTML as dying skill. Apparently the writer did not know that HTML is the language that browsers use to render a web site. Granted, with today's editors it is easier to write but it is still the corner stone of web browsing.

[More]

Thanks for your opinion but...

Normally I use my blog as a vehicle to share what I have learned. I typically put things in my blog that are intended to help other developers. Today is a little different; this blog post is mostly for those that don't use ColdFusion. I am not sure that people who don't use ColdFusion will read my blog but hey, this is what I got.

I have had a twitter account (www.twitter.com/dfgrumpy) for a long time. I never really used it until recently. Thanks to applications like TweetDeck it makes it much easier to use. I setup a search for "ColdFusion" to see what is going on out there. During the past couple weeks I have seen some things that seriously tick me off. I am generally a pretty calm person. It takes a lot to push me over the edge. I, as a general rule, try not to comment on the bantering of others. I find it very time consuming and tiresome.

[More]

Block Firebug on your site

So, you want to stop people from using Firebug when visiting your site? Well, it is just about as easy as you think. All you have to do is basically just see if the firebug console is active. If so display a warning and relocate. The one thing to remember is that you want to prevent this from running when doing cfc calls. This is also true for any other call that does a non standard return.

view plain print about
1<cfsavecontent variable="firebugTxt">
2<cfoutput><script>
3    if( window.console && window.console.firebug ){
4        alert("Sorry! This system does not support Firebug.\nClick OK to log out.");
5        window.location='/login_out';
6    }
7</script></cfoutput>
8</cfsavecontent>
9<cfhtmlhead text="#firebugTxt#">

till next time...

--Dave

Unicode data and queries

I have been working on a part of an application that stores translation data. How it works is very simple. A user would go in and translate text from one language to another and save the translation. Sounds very simple right? Yea, that is what I thought too. That was actually until I tried to save the data.

What was happening was this. The data being saved in the database was showing up as "?????? ???????" when querying the data through SQL Management Studio. I then double checked to see if I was going crazy. I ran a select query via ColdFusion and the data came back in the same way. I found this quite strange considering the cfstoredproc debug output of the insert looked good.

After doing some digging I made some alterations. The alterations were based on the fact that I was using the wrong data type. First I changed the parameter data type in the stored procedure from varchar to nvarchar. I also changed the table data type to nvarchar. This should now allow me to insert and store the data correctly.

I then reran the inserts and I was still at the same place. The data was still getting inserted wrong but the debugging of the insert looked accurate.

I then did some more digging and found something else I needed to change. This next change was to alter the datasource in ColdFusion to enable Unicode data. Once this was done I reran my tests.

BINGO! JACKPOT! YOU WIN! The data was now saved and retrieved as expected. Finally I was done with this part of the app. It was then, in the beginning moments of when I was reveling in my victory, that my world came crashing down around me.

[More]

CFIMAGE generates java error

While doing some image work this morning with watermarking I came across this strange error:

Error Occurred While Processing Request
General CMM error517

Here is part of the stack trace:

view plain print about
1java.awt.color.CMMException: General CMM error517
2    at sun.awt.color.CMM.checkStatus(CMM.java:127)
3    at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
4    at java.awt.color.ICC_ColorSpace.fromRGB(ICC_ColorSpace.java:197)
5    at java.awt.image.ComponentColorModel.getDataElements(ComponentColorModel.java:1560)

After doing a quick search (the internet is cool huh?), I was able to find this: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6444360. This issue that I ran into is apparently a recorded bug in JAVA. The bug was reported 2 years ago and it apparently has not been corrected.

The issue is with the jpg file I was trying to use. It apparently has a corrupt color profile and java can't handle it. I did check the properties of the file and noticed that the color representation property was set to uncalibrated. I was able to open the file in Fireworks and saved it as a new file and the new file works fine.

I have not found a way around it yet. The error happened when I tried to paste a one image onto another using ImagePaste.

Till next time...

--Dave

CFSAVECONTENT generates JAVA heap space error

I found this little gem while working on some code for my upcoming presentation to the CF online user group. I was working to crate a text file that contained a million lines of text. The code ran perfectly while doing test runs generating only 10 lines. When I ran it to create the million lines it failed out.

Here is the code I wrote:

view plain print about
1<CFPROCESSINGDIRECTIVE SUPPRESSWHITESPACE="YES">
2<CFSAVECONTENT VARIABLE="theRes">
3<CFLOOP INDEX="i" FROM="1" TO="1000000"><CFOUTPUT>#i#</CFOUTPUT>: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec libero. Suspendisse bibendum. Cras id urna. Morbi tincidunt, orci ac convallis aliquam, lectus turpis varius lorem, eu posuere nunc justo tempus leo. Donec mattis, purus nec placerat bibendum, dui pede condimentum odio, ac blandit ante orci ut diam.
4</CFLOOP>
5</CFSAVECONTENT>
6</CFPROCESSINGDIRECTIVE>
7
8<CFFILE ACTION="WRITE" FILE="#expandPath('.')#\textfile.txt" OUTPUT="#theRes#" NAMECONFLICT="OVERWRITE">

The error was not even a CF error message but a JRun servlet error.

view plain print about
1ROOT CAUSE:
2java.lang.OutOfMemoryError: Java heap space
3
4
5javax.servlet.ServletException: ROOT CAUSE:
6java.lang.OutOfMemoryError: Java heap space

It appears that there may be a memory max to CFSAVECONTENT. So, I got curious and starting playing with the code. After a bunch of trial and error I was able to figure out the max loop count I could run without error was 294712. This generated a 92mb text file. So, without figuring it out to the byte I would assume that the max is in that area.

Till next time...

--Dave

More Entries