Showing posts with label Railo. Show all posts
Showing posts with label Railo. Show all posts

Monday 17 February 2014

Railo bug? Or ColdFusion bug...

G'day:
I've had a bit of a break, as you will have noticed. I'm now sitting in my folks' place in Auckland, watching the cricket with me dad. New Zealand are desperately trying to salvage the match against India from certain loss. Currently NZ is on 363/5, with McCullum (183*) and Watling (92*) being the last real line of defence against India. NZ only lead by 118. We kinda need a lead of 250 to not lose (India have another innings yet, and there's still a day and a half to go). We're definitely not gonna win, but we might be able to eke out a draw.

I know hardly any of that will mean anything to most of my readers. However cricket represents "summer" to me.

But enough of the waffle.

Segue alert. One of the most noted wafflers in the CFML community - Scott Stroz - discovered some interesting behaviour when we was migrating some code from ColdFusion to Railo, and initially suspected a bug in Railo. I've had a closer look, and I think it's more likely a bug in ColdFusion, with the behavioural difference with Railo being that it doesn't have the bug. However I'm only 90% convinced of this. Here's the deal...

Thursday 30 January 2014

Underlying Java methods of CFML objects

G'day:
A week or so ago, I wrote an article 'Using "undocumented" methods'. This got mention on CFHour last week: "Show #206 - Mucho Happy Box", and one observation I think Scott made was that it'd be useful to know what methods were available, even if one might not necessarily want to use 'em (see the earlier article and its comments as to why one might not want to use 'em).

Anyway, ages ago I came across a handy Java class, ClassViewer, which enables one to inspect the underlying methods of CFML objects using Java reflection. I wrote an article about it "ClassViewer.java", and posted the source code. I hasten to add it is not my own work, but it is jolly handy code. I also knocked together a CFML version of it: "ClassViewer.cfc" (Gist). I've gone through a pumped a bunch of CFML objects through this, and saved the output on my CFMLDeveloper account. Here's links to 'em all:


Friday 24 January 2014

CFML: where Railo is better than ColdFusion

G'day:
I regularly find myself making comment about or mentioning in bug reports where Railo handles CFML functionality better than ColdFusion does. Railo undersells this stuff, so here's a list of points where Railo demonstrates itself to be better that Adobe at their own game.

The engineers are responsive

Just have a look at the posts on the Railo Google Group: those fellas Micha (Michael Offner) and Igal that regularly (and I mean multiple times daily) answer people's questions? They're the lead engineers from Railo. Now search the Adobe ColdFusion Forums for mention of Rupesh's name. Not a single post. Ever. Some first-line support dudes (who often don't know WTF they're talking about) answer occasionally. And some of the other ColdFusion team member participate once in a blue moon. But on the whole the Adobe ColdFusion Team do not help their community.

Railo is just easier to use

Ages back I wrote this "Comparing installations: CF10, Railo and OpenBD". To even install ColdFusion one needs an Adobe login (and you know where your password will end up...), perform a 347MB download (thanks to Andrew, Marcin & Richard for digging that info out for me), and an arcane install process which requires over a dozen steps. To install Railo, it's a 64MB download, unzip, run. This is a significant reduction in "barrier to entry" for people wanting to try CFML. Of course if one does want to "Try CFML", Abram's got a site for that: TryCF.com (and Russ has cflive.net too). But this does not detract from the main point: Railo's easier to get hold of, and up and running.

Wednesday 22 January 2014

Where Railo is smart and ColdFusion is dumb

G'day:
This line of investigation stemmed from this ticket in the bug tracker: SerializeJSON turns strings that look like scientific notation into floats. The contention from Adobe as to why this can't be fixed is:

At the time of serialization , datatype information of an object is not available (cause CF is typeless) and hence knowing the original datatype and convert it according is not possible sometimes and this is one of those cases.

Tuesday 31 December 2013

(4/4) CFRETRY for ColdFusion

G'day:
I had had this article in draft for over a year, but never got around to writing it. Then Matt Bourke offered an idle challenge to me to write four blog articles before year-end (it's not 8pm in the UK yet, so plenty of time), and I found myself trawling through my draft-backlog for inspiration. I came across this article (well: an earlier version of it), but decided "nah, screw that... I missed the boat on that one, Railo's already done it".

But now I read on Twitter that Steven Neiland is suggesting an enhancement to it... and it's something I had a discussion about the last time I floated this idea for CFML (back in 2010: "<cfretry> / retry")...

Friday 20 December 2013

CFML: Using TestBox to find bugs... but not in a way I expected

G'day:
I've been off work today because I need to use up my annual leave before the end of the year, and have basically been parked in front of the computer all day. A bit of a busman's holiday, really.

So I started using TestBox today ("Unit Testing / TDD - switching off MXUnit, switching on TestBox"), and quickly found (what seems to be ~) a bug once I finished the article and started writing the code for my next article.

The details for the TestBox bug are on the the ColdBox Google group: "[Testbox v1.0.0] "Variable ISEXPECTEDEXCEPTION is undefined" on erroring test". I've got no idea what's going on: as far as I can tell their code is fine, but I've not had a chance to investigate, because since I raised that, I've been trying to work out why the hell my code doesn't run on Railo.

However I've just isolated this "bug" in Railo, and here's the details.

Tuesday 17 December 2013

Not really news: Railo does grouped looping in CFScript

G'day:
I've recently been trying to be more positive about CFML... I get a bit of shit from people who think being honest about my impressions of ColdFusion equates to being negative. Bleak, perhaps, but I don't think it's negative. Anyway, Brad started a Twitter tag #favoriteCFML (I'll forgive the US-EN spelling this once ;-), and I've been popping the odd positive thought up on Twitter when it occurs to me. Join in if you like.

Anyway... this one deserves more than 140 chars.

Micha offers Railo-centric feedback on Adobe's CFSummit ColdFusion 2016 promises

G'day:
I meant to post this ages ago when it was more relevant, but it got buried in my in box.

Back when I posted the article "CFSummit: interesting ColdFusion 2016 stuff " (whilst CFSummit was actually on!), Micha from Railo responded with his own thoughts on what Adobe had said.

I really appreciate how much time Micha puts over to helping me on this blog by following up various things I raise or wonder about. His community approach is definitely something the guys from Adobe could take note of.

In this case I think it's pretty interesting stuff, so I'm going to reproduce his comment here, in case people missed it the first time.

Again, sorry to not do this straight away when it was more fresh.

I've adjusted this slightly for formatting, but otherwise it's the same copy as per Micha's original comment:

Monday 16 December 2013

CFML: A rare mishit from Railo: function caching

G'day:
Railo are pretty much where it's at as far as enhancing CFML goes. Adobe - due to a criminally long dev cycle, and seemingly complete ignorance of web development trends & practices - just drag the chain as far as keeping CFML competetive with other web dev options goes; and I believe Adobe are singularly responsible for diluting the relevance of CFML as a language ("I've come to a conclusion"). Railo's increased confidence with leading CFML enhancement - rather than just following in Adobe's shadow - gives me faith than CFML isn't "dead" as far as being an option for new projects and new developer interest goes.

However Railo is not a panacea, and sometimes they balls things up. Here's a situation in which I think they have let themselves down.

A while back Railo added function-result-caching to CFML. This was - I think - due to a suggestion that bubbled out from the community. It's good to listen to the community, but I think this is an example where there's a difference between "hearing" and "listening". They should have heard what the community said, but they shouldn't necessarily have listened. The issue is here - and obviously this is just my own opinion - the suggestion from the community was a bloody stupid one. But Railo implemented it.

Now I am not suggesting function-result-caching is not a desirable feature, but the way Railo chose to implement was basically to take exactly what the community discussion suggested, didn't sanity check it or assess how best a solution might be implemented in a programming language (rather than... for example... an application, or basically some implementation code), and built a very situation-specific solution into CFML.

Saturday 7 December 2013

CFML weirdness with chr(0)

G'day:
I was trying to help someone on Stack Overflow y/day with their question "How to pad a string with null/zero-bytes in ColdFusion & difference between CF on MacOS and Windows". The question is actually shorten than the title: how to add null characters to a string in CFML.

I thought the answer was a simple "use chr(0)", but this turned out to not be a viable answer on ColdFusion (or Railo for that matter).

In response to my suggestion, Stack Overflow veteran Leigh made the observation "Unfortunately no. The character just disappears. But URLDecode("%00") will generate a single null byte". I've not known Leigh to be wrong so I didn't doubt him, but that sounded really odd, so I decided to check it out.

<!--- baseline.cfm --->
<cfset s = "test" & chr(0)>
<cfoutput>
string: [#s#]<br>
length: [#len(s)#]<br>
</cfoutput>

And the - surprising to me - output:

string: [test]
length: [4]


Um... where gone?

I tried this on Railo... thinking Railo's more likely to get it right than CF is, and it had the same output. Testing on OpenBD got what I'd consider to be the correct results:

string: [test]
length: [5]


The NULL isn't printable, so doesn't render anything, but it should still actually be there, and that string should consist of five bytes: 0, 116, 101, 115, 116. That's a length of five. As per OpenBD's output.

That said, I know that NULLs do have special meaning in some strings, for example C has the concept of a null-terminated string, in which the null signifies the end of the string, not a character in the string. I wasn't aware of this being a "thing" in Java, but maybe it was.

I refined my code somewhat to not be simply end-padding the string:

<!--- outputStringContainingChr0.cfm --->
<cfset s = chr(0) & "foo#chr(0)#">
<cfoutput>#s#:#len(s)#:#asc(left(s,1))#</cfoutput>

So I'm sticking a NULL at the beginning and end of the string. If it was acting as a terminator, s would simply be an empty string afterwards. But I get this (CF and Railo both):

foo:3:102

102 is indeed the ASCII code for f.


So what's the story here? I still had a suspicion that something "non-stupid" was happening here, and I just didn't get it. Maybe there's something about a NULL char's standard handling that means it's not added to strings. Although this seems far-fetched as obviously there's use-cases for it (see the Stack Overflow question), and indeed Leigh came up with the fudged way to do it:

Wednesday 4 December 2013

Railo supports array types

G'day:
This might be old news, but it's something I didn't know until today. Railo supports function return values and arguments of type array-of-something, eg:

function acceptArrayOfSamples(required Sample[] samples){
    // etc
}

Sample[] function returnArrayOfSamples(){
    return [new Sample(), new Sample()];
}

Where sample is a CFC, eg:


//Sample.cfc
component {

}

It also works (kinda) for inbuilt types too, like strings and numerics.

I had a look at how well this stuff works, writing these test functions:

// functionsToTest.cfm
private any function acceptArrayOfSamples(required Sample[] samples){
    return samples;
}

private Sample[] function returnArrayOfSamples(required array samples){
    return samples;
}

private any function acceptArrayOfStrings(required string[] strings){
    return strings;
}

private string[] function returnArrayOfStrings(required array strings){
    return strings;
}

private any function acceptArrayOfNumerics(required numeric[] numerics){
    return numerics;
}

private numeric[] function returnArrayOfNumerics(required array numerics){
    return numerics;
}

private any function acceptArrayOfStructs(required struct[] structs){
    return structs;
}

private struct[] function returnArrayOfStructs(required array structs){
    return structs;
}

These functions either accept an array of various types (Samples, strings, numerics, structs), or return same.

I've written some unit tests to see how well this lot works:

// TestArraysOfObjects.cfc
component extends="mxunit.framework.TestCase" {


    public void function beforeTests(){
        variables.arrayOfSamples    = [new Sample(), new Sample()];
        variables.arrayofSubSamples    = [new SubSample(), new SubSample()];
        variables.arrayofNotSamples    = [new NotSample(), new NotSample()];
        variables.arrayOfStrings    = ["array", "of", "strings"];
        variables.arrayOfNumerics    = [-1, 2.2, pi()];
        variables.arrayOfStructs    = [{one="tahi"}, {two="rua"}, {three="toru"}, {four="wha"}];

        include "./functionsToTest.cfm";
    }


    public void function testAcceptArrayOfSamples(){
        acceptArrayOfSamples(arrayOfSamples);
    }

    public void function testReturnArrayOfSamples(){
        returnArrayOfSamples(arrayOfSamples);
    }

    /**
    * @mxunit:expectedexception expression
    */ 
    public void function testAcceptArrayOfSamples_withStrings(){
        acceptArrayOfSamples(arrayOfStrings);
    }

    /**
    * @mxunit:expectedexception expression
    */ 
    public void function testReturnArrayOfSamples_withStrings(){
        returnArrayOfSamples(arrayOfStrings);
    }

    public void function testAcceptArrayOfSamples_withSubSamples(){
        acceptArrayOfSamples(arrayOfSubSamples);
    }

    public void function testReturnArrayOfSamples_withSubSamples(){
        returnArrayOfSamples(arrayOfSubSamples);
    }
    
    /**
    * @mxunit:expectedexception expression
    */ 
    public void function acceptArrayOfSamples_withNotSamples(){
        acceptArrayOfSamples(arrayOfNotSamples);
    }

    /**
    * @mxunit:expectedexception expression
    */ 
    public void function testReturnArrayOfSamples_withNotSamples(){
        returnArrayOfSamples(arrayOfNotSamples);
    }

    public void function testAcceptArrayOfStrings(){
        acceptArrayOfStrings(arrayOfStrings);
    }

    public void function testReturnArrayOfStrings(){
        returnArrayOfStrings(arrayOfStrings);
    }

    public void function testAcceptArrayOfNumerics(){
        acceptArrayOfNumerics(arrayOfNumerics);
    }

    public void function testReturnArrayOfNumerics(){
        returnArrayOfNumerics(arrayOfNumerics);
    }

    /**
    * @mxunit:expectedexception expression
    */ 
    public void function testAcceptArrayOfNumerics_withStrings(){
        acceptArrayOfNumerics(arrayOfStrings);
    }

    /**
    * @mxunit:expectedexception expression
    */ 
    public void function testReturnArrayOfNumerics_withStrings(){
        returnArrayOfNumerics(arrayOfStrings);
    }

    public void function testAcceptArrayOfStructs(){
        acceptArrayOfStructs(arrayOfStructs);
    }

    public void function testReturnArrayOfStructs(){
        returnArrayOfStructs(arrayOfStructs);
    }

}

Where Sample.cfc is as per above, and SubSample.cfc and NotSample.cfc are as follows:

// SubSample.cfc
component extends="Sample" {

}

// NotSample.cfc
component {
    
}

To summarise the tests, what I've done is:
  • for the functions expecting/returning a Sample array, passed in arrays of Samples, SubSamples, NotSamples, strings. The latter two are expected to error, and do;
  • for the functions expecting a string array, just tested with a string array
  • for the functions expecting a numeric array, tested with both a numeric array and a string array (the latter ones - correctly - error)
  • for the functions expecting a struct array, tested just with a struct array
The results were as follows:


So the following tests fail:
  • passing an array of strings to a function expecting... an array of strings;
  • same with the function expecting a numeric array, it fails when it correctly receives an array of numerics;
  • same with structs.
Oddly, it's only when passing 'em in that there's a problem: it sees the arrays as the correct types when returning them.

Update:

As Rory observes in his comment below: this has all been fixed in Lucee. Nice one.

This is a handy feature, but it's incomplete. I've gotta go do some work now, but I'll check if there's a bug report for this, and raise one if not. And I will cross-reference back here either way. I'll also check to see if there's a ticket to implement this in ColdFusion, and raise / cross-reference accordingly.

That's it.

--
Adam

Saturday 23 November 2013

How to see the Java that your CFML compiles down to

G'day:
This is in response to a question Upendra asked on my earlier article "CFCamp: <cfprocessingdirective> and how not to use it". Within that article I said this:

This results in being compiled to:


this.MSG.set("??, ?????, ????? ???? ??? ???? (????) – ??????!");

Upendra's question is: "how do I know what it compiles to?". Good question.

First some history. Back when ColdFusion ported onto Java in CFMX 6.0, it went from being an interpreted language to being a compiled one. Not compiled to a native executable like C code would be, but compiled into Java bytecode that is then executed by the JVM. Your CFML itself is not executed, it's just an intermediary language between you and the JVM. Note: OpebBD is still interpreted, but ColdFusion and Railo CFML are both compiled.

Initially on CFMX 6.0 the CFML was translated into Java source code, then that was compiled. If one looked in the cfclasses dir (C:\apps\adobe\ColdFusion\10\cfusion\wwwroot\WEB-INF\cfclasses for me), one could see the .java files appearing as you browsed to a .cfm URL, and then being replaced by .class files shortly afterwards. This process was as slow as a dog, and by the time 6.1 (or perhaps even update 3 of 6.0?), the intermediary step to Java source had been scrapped, and the CFML was compiled straight to bytecode. Much quicker.

Friday 15 November 2013

London Railo Meetup, Weds Nov 27

G'day:
I'd just like to encourage people in the London / SE part of the UK to come along to the next London Railo Meetup: "Debugging Railo and general Railo discussion". It's - again - being held at the Pixl8 offices in Clapham / Wandsworth (very accessible via various transport links).

The topic for this meeting is summarised thus (from the page linked-to above):
We are going to get the opportunity to review how to debug Railo.

Mark Drew from Railo has agreed to run through the layout of the code, working with eclipse and debugging.

Time permitting we could select some bugs or features from the Jira tracker and talk about how we could approach them.

Monday 14 October 2013

CFCamp: Loop labels in Railo

G'day:
Here's another one that I already knew about, but hadn't looked at it before. Gert brought it up in his keynote today, so I thought I'd have a look. Railo has added labels to <cfloop> and <cfbreak> / <cfcontinue>. But the implementation is either incomplete or non-intuitve (at least to me).

CFCamp: new (to me) function in Railo/CFML: serialize()

G'day:
Gert gave typically bloody interesting keynote presentation this morning on what's been happening in Railo over the last year or so, where it's at now, and where it's headed for its next version. I might write up that part of it at some stage, but that sort of thing takes a while to write up and requires more concentration than I feel like dedicating at the moment, so I'm just gonna focus on some of the code stuff he showed us.

First thing... take note, Rakshith: Gert showed us code. Not smoke and mirrors and marketing spiel, but code.

There was a bunch of stuff that was new to me, and I'll write that up separately, but here's a quick examination of Railo's serialize() function. The docs are here: serialize(), but there's not really any useful information there. What serialize() does is to... serialise data, which can later be evaluated (using, yes, evaluate()) back to CFML data again. Here's an example using an array:

rainbow                    = ["Whero","Karaka","Kowhai","Kakariki","Kikorangi","Tawatawa","Mawhero"];
serialisedViaFunction    = serialize(rainbow);
deserialised            = evaluate(serialisedViaFunction);

writeDump([rainbow,serialisedViaFunction,deserialised]);  

Here we get the output:

Friday 11 October 2013

Server.cfc and onServerStart()

G'day:
Another interesting thread cropped up on the Railo Google Group today: Micha was asking about Server.cfc, and how people use it (if at all).

This is not very widely used code, so I'll link to the docs for onServerStart() and quote a para from it:
ColdFusion now supports a CFC with an onServerStart method that runs only when the server starts. The onServerStart method takes no parameters, and is the only function in the CFC. The function is useful for application-independent tasks, such as instantiating the applications, configuring logging, or setting up the scheduler.
By default, ColdFusion looks for the onServerStart method in cf_webroot/Server.cfc.
Apparently Railo does not offer this functionality. But also have never had anyone notice this.

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.

Tuesday 24 September 2013

Things I dislike: jobsworths

G'day:

Update:
For non-UK-English-speakers, from Wikipedia:
A jobsworth is a person who uses their job description in a deliberately uncooperative way, or who seemingly delights in acting in an obstructive or unhelpful manner.


I started to have a quick look at ColdFusion 10's new ESAPI functions this morning...  I'd give you a link for those, but they don't seem to be categorised in the docs (and I can't annotate the docs accordingly, cos the site is still broken since it was "upgraded" to use the new wiki)... and quickly got deviated onto the bug tracker.

Friday 20 September 2013

Expectations management: date casting in QoQ

G'day:
Just a quick one today. I camne across some unexpected (to me) and pretty unhelpful behaviour in QoQ yesterday, with the cast() function.

Monday 16 September 2013

How sausages are made

G'day:
Today I pulled back the curtain on some of ColdFusion's inner workings... and hastily closed the curtain and declared "nothing to see here. Move along".