As you begin exploring Spry, or indeed any Ajax solution, there's going to be a point when you'll be stumped with something just not working, and no amount of eyeballing the CFML or HTML source will help...because the problem is between the browser and the server--in the http stream. In this entry, I want to share some common problems and solutions. In the next entry, I'll discuss tools to help solve that problem. This is vital stuff.
(As suggested in the entry's title, this is part of a series I'm doing on Spry. Be sure to check out the other entries.)
Problems Due to CFML Debugging Being Turned On
While most Spry examples show simply opening XML files, most CFML folks will be inclined to try to generate the XML via CFML. Nothing wrong with that. In fact, I'll have a future entry on some tips there.
But if you do decide to try to generate the XML from CFML, you need to be very careful: Spry apps (and indeed many Ajax apps) expect XML--and only XML--to be received in response to their httprequest. A very common problem/mistake is to leave your CFML debugging turned on. You may even look at your page and say "it IS returning XML", but it's not. It's the XML PLUS the debugging output. And what's that written in? HTML!
The simple solution is either to turn off debugging in the requested CFML page or its application.cfm/cfc, using:
or turning it off server-wide in the CF/BD server Admin console.
Problems Due to text/HTML mimetype Being Returned
Another common stumper, depending on how you try to return your XML from CFML, is that while you're trying to send XML, the CFML engine is doing something that you never perhaps noticed. What have we always genereated (for the most part) from CFML pages? Why, HTML, of course.
Well, under the covers, web servers (and app servers like CF/BD) happen to also set what's called the "mime type" for the generated page, and by default they create it to be "text/html". The problem is that a client (like Spry/Ajax) that's expecting XML may balk at that header/mime type.
The solution may be to set the correct mime type in the requested template or its application.cfm/cfc. You can do that with:
. You may even find that it's useful to add the RESET="yes" attribute to that tag, which aborts any previous output generated prior to the tag. I'll share as well that sometimes CFSILENT and CFPROCESSINGDIRECTIVE can be helpful to manage whitespace.
I said above that the problem may depend "on how you try to return your XML from CFML", and that the CFCONTENT "may be" the solution. The thing is that you may also find you can return your XML from CFML in ways that automatically handle that detail, such as using CFFunction's ReturnType="xml", which has changed as of 7.02. More on that later (or in the meantime see other entries in my Spry compendium).
Problems Due to Errors in CFML Page Sending XML
Continuing from the above, think also of what happens if you're requesting a CFML page (that's supposed to be returning XML) and instead there's an error in the page. What does CF (and BD) return? By default, it's the traditional runtime error page. Well, think about it: what's that written in? It's HTML, again! We never think about it in normal CFML coding, because we just see the error in the browser and read the words and go a-debuggin'.
But the code reading the result of the XMLHttpRequest in Spry (and in many Ajax solutions) is not as smart as us. If it's expecting XML, and your error causes it to get HTML, it will be totally stumped.
The reasonable solution would seem to be to setup your server/application to use CFML error handling (CFERROR, CFTRY/CFCATCH) so that you catch the error and send back a message in XML. But that's not as obvious as it may seem. First, your Spry client is going to be witten so that the Spry.Data.XMLDataSet expects not just ANY XML but XML in a specific nested structure of specific element names. It will not be trivial to package up an error in a format useful to the client.
This is an area where the Spry framework itself could help us. Since the focus for now is on developers of simple static HTML, and indeed on reading simple static XML, it's something that I don't expect would be a high priority for the Spry team. I haven't investigated this with them, though, and will welcome any correction of miunderstanding/misstatement.
The problem of generating "spry-client-specific XML" is still more challenging if you try to setup this error handling in your application.cfm/cfc using CFERROR, but you have pages that are both general-purpose CFML templates browsed by browsers, and those meant to serve up XML. You may want to separate the XML files into their own directory, so as to handle them (and the debugging issue above), separately from the traditional CFML pages. Otherwise, you would need to detect whether the client is not a regular browser, but think about it, how will you know if the client is "not a regular browser"?
All these issues above are not really a new problem. We faced the same challenges some years ago in the "old" days of generating WAP/WML pages from CFML (WML was a way of creating web pages for phones, using an XML-compliant language to layout content for phones). I wrote of many of these same issues in a chapter I did in the book, Professional WAP in 2000.
I should add, as well, that the subject of CFML error handling (CFERROR, CFTRY/CFCATCH, and more) is a topic worthy of multiple blog entries. Instead, I'll point you to a series of CFDJ articles I did on the topic:
Problems due to web server error messages
Similar to the issues of CFML error messages above, think also of the implication of general web server messages. Even if your Spry request asks for a static file (really, any file) from the server which, due to some error (like not existing) would would lead the web server to respond with an error. It's likely that, again, the web server will respond with an error message also formatted in HTML.
There are different solutions for web server error message handling, but it's beyond the scope of this discussion. I'll just raise the issue for you to consider. I can even foresee web servers perhaps getting smart about detecting the browser type and trying to return a particular type of error, but as was discussed above, this may always be problematic.
A Better Debugging Tool
With all the problems above, and still more, which can cause the server to respond with something that your Spry/Ajax client didn't expect, the better idea is for you to be armed with a tool to help you observe the communicaitons stream between your browser and the server. That's a very important point, which I will save for a later post.