Wednesday, 25 September 2013

CFML: Things I do like: contrasts

G'day:
This is a follow-up from yesterday's article "Things I dislike: jobsworths". In this article we see the constrast between how Adobe conduct themselves, and how Railo do in a similar (well, hey, identical) situation. The very same situation.

Yesterday I observed that the blameshifting and general work-avoidance tactics from elements of the Adobe ColdFusion Team is very bloody slack, and really not acceptable. This is in the context of an - admittedly minor / edge case - issue with how some methods within the ServletRequest implementation (or usage, not sure) seem to work. The issue itself is - as I say - inconsequential, but Adobe's antics of excusing themselves from doing anything about it were lamentable.

In the course of troubleshooting / reproducing / investigating this issue, I noticed the same behaviour seemed to be occurring on Railo. In the spirit of fair play, I hit Railo up about it as well to see how they'd deal with it (and expecting some technical guidance which I was unlikely to get from Adobe).

The contrast in reaction could not be more profound. Just to give the executive summary before I start copying and pasting material you could have already read elsewhere: Railo technical support rocks. And in particular Micha goes above and beyond what I'd expect from any vendor's engineers. At this really really puts to shame how Adobe's team conduct themselves.

Below is a reproduction of the updates Micha gave me on this topic, as comments against yesterday's articles. This is just in case you missed them the first time. Comments are coded green for Micha, and blue for me.

First of all a comment to this
"we don't have the implementation for PageContext or servletRequest.That comes from the underlying application server. You can see it for yourself by checking the cfdump of GetPageContext().getRequest()"

That is not true, Railo and ACF are both "jsp engines", mean both implement the jsp interfaces, of course they do not follow the jsp syntax, but both use the "hooks" for jsp.
PageContext or better the abstract class javax.servlet.jsp.Pagecontext
http://docs.oracle.com/javaee/... has to be extended by the "jsp engine", in fact the abstract class PageContext has no working code ad all.
So pageContext has to be implemented by Railo and from ACF, in ACF you can see that very easy by doing this dump
<cfdump var="#getPagecontext().getClass().getName()#">
You get something like NeoPagecontext (hello cf6 beta), in Railo you get railo.runtime.PageContext.

The Httpservletrequest object on the the other side comes from the servlet engine and Railo is not touching or using the parameter methods in any way. So Railo is not using this methods to get the form and post data, because this method does not work as you expect the form and URL scope, getting the form scope is not easy btw,because we support 3 differents format for it (multipart form data,urlencoded format and text plain).
Like you can see here http://docs.oracle.com/javaee/... this methods returning the query string OR the form data, so it is really up to the servlet engine how they work.
So that's interesting. Seems like Rupesh was simply misrepresenting the truth in that statement.
That makes sense, Micha, cheers.

But calling getParameter() on the HttpServletRequest (implementation) object returned from getRequest() *should* work, yes? I mean for form variables. It obviously works fine for URL variables on both Railo and CF10 already.

just a small addition, Tomcat is the Servlet Engine Reference implementation, so if Tomcat acts different than Jrun, Jrun is in most cases wrong (if not in all cases), jrun is far away to follow the Servlet engine specification and is extremely outdated.

I'm sure this parameter functions work correct in Tomcat, they simply not return what you expect, i will do some testing to give some light on it.
So Micha's not simply doing a knowledge share, he's gonna do his own investigations too. This is outside business hours, btw, so he's doing this in his own time.
Out of interest i did some digging and i have find out that Tomcat return form data with the parameter methods outside Railo, so why not with Railo when Railo is not using this methods?
some data provided by the Request object are provided only once, for example you can get only once a InputStream when you call the method getInputStream.

That is the reason Railo wraps the given Request object with a object of the class HTTPServletRequestWrap, to make the InputStream available more than once by storing the stream the first time.

when Railo initialize the form scope, it looks like Railo is using data from the Request object that are available only once, so after initialize the form scope the data are no longer available to the parameter methods.

So my first assumption that you expect something wrong was wrong, sorry for that.

we will look into this to improve that behavior, can you please raise a jira ticket.
I hasten to add I never got around to raising the Jira ticket (see why... read on...)
i should rtfm ;-)

http://docs.oracle.com/javaee/...

"If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via getInputStream() or getReader() can interfere with the execution of this method." that is exactly what is happening

Or even RMFA ("Read my f***ing article" ;-), as I quoted that bit!

Cheers for the clarification in this and the previous comment though. So basically Railo & ColdFusion 10's behaviour is "predictable" given this situation. Although I have to say it all sounds a bit flaky as a way of going about things (even if it was documented more emphatically, it still seems a bit shit).

Or is it a case - I'm inferring from the wording here - that one *should not* be "reading the body directly from the getInputStream() or getReader()" (instead using some other approach to extract the data?), because doing so can render other operations erratic?

And it also seems - and I know you can't answer this necessarily - that earlier versions of CF in which one can reliably recall getParameter() as much as one likes and get results every time, had some sort of work-around in the underlying implementation that made this work. And this seems to be what's missing from CF10? IE: there is no work around to make it work any more.

So if that's a case... CF10's change in behaviour can legitimately be seen as a regression, I think.

And Micha, seriously thanks for looking into this!

i solved that issue for the next patch release
https://issues.jboss.org/browse/RAILO-2622
you get now the data as expected, see testcase for details.

some comments:

"Or is it a case - I'm inferring from the wording here - that one *should not* be "reading the body directly from the getInputStream() or getReader()" (instead using some other approach to extract the data?), because doing so can render other operations erratic?"

you only get the data needed the proper way from getRender, getInputstream, the parameter methods are not a option.
First they mix url and form scope and second they are using the encoding defined with the request, so the BIF setEncoding does not work with this methods.
--------------

"So if that's a case... CF10's change in behaviour can legitimately be seen as a regression, I think."

I THINK the change has nothing to do with ACF itself, it looks like Jrun simply does not consume the data like tomcat,resin or jetty does (yes i have tested on all of them).

so this text:

"If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via getInputStream() or getReader() can interfere with the execution of this method."

for Jrun it must be "DOES NOT interfere", means when you run ACF9 on a tomcat you will see the same problem.
Now I did raise all this on the Railo Google Group too, but I am absolutely astounded that Micha put all this effort into following up something mentioned on a blog article. Also bear in mind the initial bug raised was one in ColdFusion, that I simply tangentially noticed also seemed to possibly impact Railo; whilst being unsure if there was actually an issue or not, based on Adobe's - as it turns out - misguidance.

And take note: Micha's fixed it already in Railo!

I was going to say that this is "model" technical support, but it's really a long way beyond that.

Micha, I think you should be bought beer by everyone in the CFML community for setting the precedent as to how CFML should be supported.

And Adobe... you seriously need to pay attention to how this sort of thing should be done. You have no excuse not to deport yourself in a fashion similar to Micha / Railo here.

Thanks Micha. You rock.

--
Adam