Archive for the 'bluedragon' Category

CFUNITED Day One

As is typically the case, CFUNITED has a pair of themes.  There's the conference theme, which, as always, is helping CF coders become more empowered by learning about new things (OO, using CFCs, learning frameworks, etc.), and then there's the "backtheme".  This year it's all don't use only CF.  Adobe's integrating Hibernate into CF9, Railo is preaching the benefits of the JBoss platform (clustering, caching, Hibernate, etc.), Groovy has a lot of lovers, and Grails (which is Spring and Hibernate for Groovy) does to.

The integration of Hibernate all over the place is very exciting.  CF-based ORM tools suck, frankly.  Which isn't to belittle Mark or Doug in any way, they've done a fantastic job, it's problems with CF itself that are the issue.  With Railo's "CFC is a class" implementation, Hibernate is directly applicable.  With CF's crazy "a CFC is a bunch of classes in a Map" implementation, I'm not sure how Adobe's going to get it to work.  I'm very much hoping they fix the core issue (which would almost certainly give some nice performance benefits as well) instead of bastardizing Hibernate to get it to work, but we'll see.

CF Groovy

Those of you who remember CF Rhino will recognize the name for my latest little project. I whipped up a small proof-of-concept integration for Groovy into CF apps tonight while playing with some classloading issues within Groovy itself.

Groovy has a number of advantages for this type of integration of JavaScript, the biggest one being that Groovy IS Java, and carries Java's semantics almost perfectly. So unlike with Rhino, no major conversions are needed moving in and out of Groovy, which makes things enormously easier. CF still brings it's special blend of "insane" to the party, but it works quite well overall. Definitely has more real-world potential than CF Rhino ever did.

CF Groovy is not a whole framework like CF Rhino was, it's really just a proof of concept for integrating the two together and sharing resources. You can get the demo (which includes the engine via svn:externals) from Subversion at https://ssl.barneyb.com/svn/barneyb/cfgroovy/trunk/demo/. Just check it out to a directory named 'cfgroovy' in your webroot, drop the groovy JAR from the 'groovyEngine' subdirectory into your /WEB-INF/lib folder, and you should be done.  You can see it in action at the demo page, though without source to browse, it's not very interesting.

Also, unlike CF Rhino, there's no dependencies on the internals of ColdFusion (the Adobe product). To do some of the bridging to JavaScript, I had to invoke internal APIs of ColdFusion, so it wouldn't run on BlueDragon, Railo, etc. I built CF Groovy with Open BlueDragon and Railo 3 on Tomcat simply because I didn't have a CFML runtime on my box, and CF is like 400MB while oBD is 11MB and Railo is 25MB.

Unfortunately, all three runtimes have bugs that prevent them from working as expected.

Railo was the worst: it has some recursion issue with the JEE.include() call. It also doesn't seem to implement java.util.Map with it's struct implementation, and throws on missing keys rather than returning null.

Open BlueDragon initializes ResultSets from manually assembled queries (and possibly "real" queries) with the row pointer pointed at the first row, rather than before the first row as the spec says it should be.

ColdFusion doesn't create java.util.Date objects with the createDate built in, so trying to call ResultSet.getDate() throws a ClassCastException. Using ResultSet.getObject() and letting the ducks work their magic fixes this issue. It's also 15-35 times larger than the others.

Except for the download size issue, I've got conditionals to cover all the cases in the app, so it should be checkout and run on all three platforms. I haven't tested NA BD, CF7-, or Railo 2. I don't know why they wouldn't work, though, since I'm just doing standard Java stuff. I'm not doing any version conditionals, only platform ones, just in case.

Revenge of the Dragon, pt II

Couple more little glitches as the app has continued to be tested:

1)
I mistyped 'reqeustTimeout' [sic] in a CFSETTING tag.  BD didn't
complain, and I didn't catch it, because the extra time for the request
never happened to be needed, but CF threw a syntax error immediately.

2)
BD 6.2 puts the CFFILE result struct from uploads into local variable
(if declared), inside functions. I was never quite sure what CFMX 6 did
regarding this.  CF7, however, puts it in some unknown place
(presumably variables scope) that is shadowed by the local variable
scope.  Just a matter of adding the new CF7 'result' attribute to
name the value you want the result placed in.  I think this is
actually a bug in CF7 (breaking backwards compatibility), but I'm not
sure about that.  Either way, it is a difference between BD and CF
that you should watch out for.

Revenge of the Dragon

I know what you're saying: "please, not more whining."  Well
rest assured that this isn't that kind of a post.  Yes, I ran into
some more problems with BD's compatibility with CFMX last night, but
I'm not bitter, I swear.  I took an app that I'd written for BD
and was moving it to CF7 this evening and found four distinct bugs in
BD that gave me grief.  It's worth mentioning that I'm running BD
6,2,0,226.2.28, which I believe to be a 6.2 release candidate, not the
final version, but I'm not 100% sure of that.

1) BD doesn't care if your 'var' declared local variables are at the top of a function or not, while CFMX does.

2) BD considers assignment to be an expression, while CFMX doesn't.  In BD <cfreturn s = s & "text" /> is legal.

3)
BD processes CFLOGIN-based security stuff (at least when the
loginstorage is set to session) for all requests in a session that have
be logged in with CFLOGINUSER, regardless of whether CFLOGIN is
actually on every page.  In other words, on CFMX you have to have
CFLOGIN run on every page to use the cflogin framework, while on BD you
just have to have it run once per session.  Personally, I like
BD's interpretation, but all it takes is adding a self-closed CFLOGIN
tag right after your CFAPPLICATION tag to make it work on CFMX.

4)
BD doesn't seem to validate return types on CFFUNCTION quite all the
way.  I had a function with a numeric returnttype that returned
the result of a SELECT MAX(...) ... query, and when no rows were found,
the result of the MAX call is obviously null, which isn't numeric (and
yes, I'm going to restrain myself from that rant ;).  BD happily
let me return null from the method, but CFMX errored.  Perhaps
because BD actually recognized the null for what it is, and let it pass
the test?

I also ran into
some issues using JS remoting (via Neuromancer) against a CFC-based web
service.  I had a lot of issues with getting that all working on
BD when I first wrote the app, so I suspect I ended up implementing
some stuff that wasn't quite CFMX-compatible, but I can't say that with
conviction, so I left it off the list of definite bugs.  The fix
was simple to make, so I'm not going to worry about it.

So there they are, four (and a half) points to watch out for when
moving from BD to CFMX.  As I said above, I'm not bitter, because
in every case the issue arose because I made an honest mistake in
coding, and BD did what I meant without
throwing an error.  Of course, in every case, BD was incompatible
with CFMX, but I'm going to put that behind me.  So if you're
developing on BD and planning to deploy to CFMX, watch out for these
gotchas.  Catching them as you code isn't a big deal, but having
to sweep an app for this type of stuff at deploy-time would be a bear,
especially if it's large.  The first two are compile-time errors,
so they'll be caught easily, the third will be apparent as soon as you
try to log in, but the fourth will require careful unit testing to
catch, because it's a data-dependant runtime bug.

BD 6.2 Update

Vince from NA just provided some clarification on the 6.2 release and
RC expiration on the BD mailing list.  BD.NET is the only edition
that is set to expire on the 31st, and it doesn't expire, it just
reverts to developer edition.  The Java editions don't expire
based on dates, they expire based on the trial licenses (never for
free, 30 days for JX, and based on the eval license for the J2EE
edition).  So unless you're running BD.NET, the March 31st
deadline isn't a concern.

Of course, after the final 6.2 release, NA is dropping all support for
the RC, so you're better off upgrading sooner than later, but there
isn't the hard deadline to do so.

BlueDragon 6.2 is Coming

The final release of BlueDragon 6.2 is due out "very, very soon,"
according to Vince from New Atlanta.  Perhaps more important to
those that have been using 6.2 RC is that the RC is set to expire on
March 31st, so you'll have to upgrade any systems to 6.2 before that
date.

I'm excited to see what tweaks and fixes NA has made from the RC to the
final release (since this site and several others are running on the
pre-release version), but I'm a little concerned that the timeframe is
so tight to get the upgrade in.  Hopefully no code will break with
the new version, because there isn't going to be much time to fix it.

BlueDragon: Still Breathing Fire

BlueDragon continues to give me fits. CFEXECUTE (which I'm not sure - there is conflicting evidence - is supported on the Server edition) refuses to work correctly. No big deal, since launching a Process direct from the Runtime class is straightforward (I didn't need the IO streams, in this case). However, the waitFor() method of Process refuses to do anything except throw exceptions when called, which basically means no syncronized subprocesses. So what's the solution? Write a JSP page that does the exact same thing (except it works) and then call it with CFHTTP. Hardly elegant, but it worked well enough.

Next problem was doing some simple image manipulation with the ImageIO class (from javax.imageio). Nothing complex, just a simple read-scale-write operation to generate a thumbnail. However, BD pukes on the write part. From the stack trace on the NPE, it appeared that it was having trouble selecting which of the method versions (write is overloaded) to call, even though it was pretty clear cut (the one with a RenderedImage, a String, and a File). What's the solution for this case? You guessed it. Write a JSP page that does the exact same thing (except it works), and then call it with CFHTTP. Ooof.

I do tire of such hacks, and so once again, my pursuit of the CF license is in full swing. I just finished up some more work for Fusium (awaiting the check), and lined up another little project that should just about round out the two grand I need. Now if only I could be done and have the license today….

BlueDragon Live!

Well, I'm happy to say that I just deployed my first BlueDragon app to production this evening. It's not much (couple hundred KB), but it's up and running on BD 6.2 Beta. I discovered a whole slew of bugs as I put it together (it was a ~5 day sprint of late nights), but nothing really stood squarely in the way.

The app in question is the backend for this blog (along with The Boisvert Life, for the personal side of me). For various reasons, I'm still using Movable Type as the engine, but I needed an admin interface that I could manipulate, so I rolled my own. Now that it's functional, I can extend it in various ways, which was the whole point of the exercise.

As part of the update, I also installed MySQL 4.1, upgraded the MySQL connector, and a few other things, so I should be golden for a while. This largely meatless post, as you've not doubt guessed, was the maiden post from the new interface, and all seems to have gone well.

Will It Never End?

So, BD 6.1 Beta solved most of my problems with CFCs. I'm on cloud nine, and I'm finally getting some work done. It's not perfect, but none of the other bugs were really more than inconveniences (for instance, it gets grumpy when you mix full CFC paths with pathless references to CFCs in the same package). No big deal, just figure out what the issue is, and work around it (always full-path everything, in this case). Plugging away, and I've got the backend of my app finally put together.

Now it's time for the front end. Throw the Fusebox 4.1 skeleton app in there and run it. Error about indexing 'attributes' as an array, trying to set the default fuseaction. Refresh. No issue. WTF? Refresh, fine. Refresh, fine. Touch the code, refresh, error. An hour later I've isolated the problem. Scope leak on a CFLOOP tag iterating over a query.

We all love the fact that CFML lets you reference the fields of the current record of a recordset you're looping over with just the column name. Once you stop the loop, that stops functioning, and you have to again fully scope the field you want (queryname.columnname[row]). BD was doing that, but if you raised an exception inside the loop, it never bothered to turn off that special psuedo-scope. Which meant that for the remainder of your request, variables in the VARIABLES scope that happen to have the same name as a column in the query you were iterating over are shadowed, just as they were inside the CFLOOP.

And of course, 'attributes', that wonderfully versatile, utterly indispensible Fusebox scope is the problem in this case. The loader runs a CFDIRECTORY tag and loops the result, potentially throwing an exception. And guess what, there's a column called "attributes" on queries returned from CFDIRECTORY, so any time it throws that exception, the request fails. (As an aside, the exception in question is an internal exception that the core files use for their internal functioning. It never sees the light of day, except in the CFMX debugging output, if you have the exception list turned on.)

Fortunately, that exception will never be raised in production environments, it's part of a development-mode-only feature (the conditional loader), so no apps are going to break. But it makes development rather difficult, as you might imagine.

User Error!!!

So my problem from last night where CFCs wouldn't work on the URL turned out to be a conflict between CFMX and BlueDragon. I don't have CFMX installed on my box any more, but when I uninstalled it, it left a couple Axis config files in a WEB-INF directory. BD, being the well-behaved J2EE application that it is, was trying to use them, rather than it's own, because it assumed they were placed there intentionally to override it's internal ones. Just a simple matter of deleting those files and problem gone. Yay!

I do have to give NewAtlanta props for being on the ball getting issues like this resolved. One of their engineers figured out exactly what the problem was for me, with no input from me except a copy of the error message (and that routed through a couple other people), and within a matter of hours, I had a description of the problem, how it happened, and how to solve it. This is the shining example, but for pretty much every problem I've had, I've gotten a personal response back with either help to resolve it, or at least confirmation that it's a bug, and that it's now known and will be fixed.