The Rhino Is Coming … to fix CFML

Show of hands, how many people like CFML? Ok, how many like the ColdFusion Platform? What's the difference, you ask? CFML is a markup language that you do most CF Platform development in. You can use CFSCRIPT (which is ECMAScript-like) for certain things, but CFML is the Platform workhorse. The Platform, on the other hand, is all the stuff that your applications (written in CFML, usually) get because they run on the CF server. Things like datasources, PDF generation, easy file access, etc. That's the platform, not the CFML language.

What if I said you could build applications on the CF Platform but weren't required to use the often-cumbersome CFML? What if it were a language that you already new? What it it was JavaScript? And what does that have to do with rhinos?

Rhino is a free JavaScript implementation from Mozilla. It's what drives Firefox, and is also the base implementation of the new Java scripting framework that is available in Java 6 (the javax.script package). It's entirely implemented in Java, and since ColdFusion is as well, that means that CFML within CF and JS within Rhino can execute in the same context, intermingled with each other.

Here's a simple proof-of-concept contact manager that I build over the weekend (running on my underpowered server). You can download the source as a ZIP archive, or via anonymous SVN (with SVN always being current, of course).  Of perhaps more general interest is the class explorer mini-app, which is included in the distribution. As you might imagine, getting everything wired up took some digging around in the Java internals, and this provides a window to the classes that are actually executing inside the JVM. Helpful for both exploration and troubleshooting classpath issues.

The app is in two parts: the integration core within the 'rhino' subdirectory, and the sample app itself. I'll discuss them separately (and very briefly) below.

The basic architecture of the app is to use JS for the business logic and backend processing, and use CFML only for the view layer (where it excels). 'Application.cfm' and 'index.cfm' can be considered "framework" files; there is no application logic in there, just wiring stuff. The views are all in the 'views' subdirectory, and the backend is in the 'scripts' subdirectory.

The architecture of the Rhino integration is centered around 'rhino.cfc' and it's 'runScript' method. You pass that method a JS file to execute, and before evaluation, it will marshal some CF objects into the JS runtime. Following execution, it will unmarshal the top-level 'model' object back to CF for use in rendering your views. More simply, you pass in your parameters and your JS script, it executes, and you get a 'model' structure back to do something with. There is a special global function named 'loadScript' that can be used at runtime to pull in additional scripts, rather like CFINCLUDE.

As you'd expect, JS files are "precompiled" into in-memory script objects and cached until they update on disk, just like CF does with CFM templates. Unlike CF, however, this doesn't seem to offer a particularly significant performance improvement. I don't have a trusted-cache option at the moment, so there is still the filesystem check per-file, per-request, which is probably part of the reason. This actually happens in two places, once to bootstrap the environment (in 'rhino.cfc') and one for the actual runtime (in 'core/bootstrap.js'). The dichotomy annoys me, but such is life.

So why did I spend 15 or 20 hours putting this together? Because I'd love to be able to write my server-side with ECMAScript (though I'd prefer ActionScript 3 to JavaScript 1.6), and wanted to do a little proof of concept for that. I quite like the CF platform, but I'm not a huge fan of CFML itself. How supremely excellent would it be for CF9 to natively support scripting in ActionScript as well as CFML/CFScript, with equal access to the same underlying platform?

26 responses to “The Rhino Is Coming … to fix CFML”

  1. Dan Wilson

    Barney,

    This is the coolest thing since the BenTaur image was released. I, like you, would love to write my CF apps in AS3 or a JS Style….

    Bring on the scripting Baby!

    DW

  2. Chris Phillips

    I believe that the answer you are looking for is; It would be very supremely excellent to write server-side AS3 with access to the CF platform.

    So, what do you get when a Rhino and a Centaur mate?… A Rhinotaur?

  3. Bruce

    Barney – I'm not following what "problem" you're trying to solve. Is your thesis "CFML is too difficult for developers to use?" How much simpler could CFML tags like cfquery, cfloop, cfif, cfswitch, cffunction, etc get?

  4. Gary F

    I'm with Bruce. I don't get it? People choose CFML because of the simplistic syntax and the power contained in each single tag. If people prefer a more Javascripty server side language then there's .NET + JavaScript or .NET + C# if they want something more powerful (and verbose).

    Sorry, but Rhino doesn't give me the horn. (Hopefully my moderately funny pun works beyond British shores?)

  5. Bruce

    Barney – as someone who programs in CFML, Java, and AS3 I can understand your desire to make it easier to use the underlying CF platform while not having to USE CFML.

    My point is that the "problem" you're trying to solve (verbose markup and lack of advanced programming concepts) is not a problem or even a concern for the vast majority of CF developers.

    Offering another methodology for being able to leverage the CF platform is a fine idea. But saying Rhino fixes CFML, is like saying a new backup tightend would fix the New England Patriots. The Patriots are not broken and neither is CFML.

  6. Brian Kotek

    Barney, this seems really damn cool. A question: how would you integrate calls to other CF tags into something like this? Say I wanted to run a CFLDAP call, or a CFSEARCH call? Would one need to create files in the tags folder to handle each type of tag?

  7. Clark Slater

    Brilliant idea. I would ***love*** to be able to develop the server side aspects of applications in the same language as I use on the client – AS3.

    Coldfusion has had server side actionscript for a while now, it's a minimal implementation slely intended to support Flash remoting…but now with Flex and all the integration there as far as remoting and webservices go…it would be pure magic to be able to develop all the server components (CFC's) as AS3 classes!!

    On the wishlist this would be top for me and my fellow Flex/Flash pirates.

  8. Gary F

    From a marketing point of view I can see how selling CF9 as a server side AS3/JavaScript engine to Flex developers would work. Adobe could make CF reach out beyond the existing loyal CFML community so other developers who use Flex or want to take their Flash/AS3 skills further (to the server) will find an affinity with CF9. Their existing programming skills will be adequate, they wouldn't have to learn a new language.

    I'm all for that, but I'd worry about the CF team piling too much resource into this probably monster-sized task rather than creating brand new functionality for CF9. (I want VoIP!)

    Maybe they can make the CFML>Java compiler modular so 3rd parties can write plugins to support JavaScript, VBScript, AS3, PHP, etc that allows the CF platform to compile those scripts to Java. I suppose it would be like the .NET platform that understands many types of languages (C#, javascript, CFML (BlueDragon)) and compiles it into its native code.

  9. Jeff Fleitz

    Hey Barney,

    Isn't Steve Yegge writing a JS Rails-like implementation in Rhino?

    I too, would embrace the use of AS3 as a source language for CF. I find myself doing more and more in cfscript and avoiding the tags when I can. I dunno, after 10 years, it is starting to feel cumbersome to me.

    Rob Gonda had kind of a teaser post about this when he blogged from MAX, but then I never heard another word about it, so I don't know if it was a rumour or not.

    http://www.robgonda.com/blog/index.cfm/2007/10/1/Adobe-Max-Day-1

    Jeff

  10. Mike Kelp

    I also think it would be valuable to at least be able to acheive more AS3 like syntax sometimes. I would personally not use it quite as heavily though.

    Personally, I think tags are perfect for cfquery, ldap, document, and many other things. Tags are very elegant for static operations where a lot of content is processed in a wrapper type situation. This extends far beyond the view to me. I have no desire to go back to string concatenation or wrapping all my SQL in quoted messes again.

    I do like the idea of closures to some degree, with the concern that they would get overused as they do with almost any other scripting language. It doesn't take very much logic for a closure to become hard to read in the midst of a statement using it as a parameter to a function call for instance. I have to laugh when someone calls that elegant or even readable for that matter.

    I do love scripting syntax for very straight up logic chunks though, such as algorithm implementation, math heavy looping, etc. I could also see using AS3 to create server side objects.

    On a separate note, I have been amazed at the documented metadata capabilities we have with CFCs in their tag form. I may have to blog about this myself, but I have been playing a lot with adding metadata attributes to some cfc or function calls to add special functionality to my CFCs with very little code. Definitely something to be careful with, probably more so than with closures, but very powerful.

    Thanks for a thought-inspiring post!

    Mike.

  11. Sean Corfield

    I guess I don't see the point either… with cfscript you can already write the function notation your want. You can already write CFCs as (almost) pure cfscript:

    function foo() { }

    function bar(a,b) { }

    With the enhancements to cfscript in CF8 (e.g., ++ and "proper" comparison operators), it's closer to JS / ECMAscript so your Rhino approach seems very kludgy.

    What am I missing here?

  12. Sean Corfield

    Hmm, the tags did not appear:

    [cfcomponent]
    [cfscript]

    function foo() { }

    function bar(a,b) { }

    [/cfscript]
    [cfcomponent]

  13. Andre Charland

    Hey Barney,

    This sounds really cool and would certainly make CF more appealing to a wider class of developer. And for existing CF developers it would make certain types of development a lot more elegant. Also using a more standard and widely used language like JS/ECMA vs CFScript can only be a good thing.

    What do you think this will do for other types of server side developers i.e. PHP, JSP, ASP…do you think they'll take notice? Will people switch, if so why? Or will this only help CF devs?

    Great idea though! Would be really sweet to have great support for the script on the client and server:)

    Cheers!

  14. Joel Cass

    Hey Barney,

    I don't get it either.

    1) Javascript is a badly planned and cumbersome language when compared to the likes of java which can be used directly in coldfusion by using the cfimport tag or creating objects.

    2) You can write flow control statements, function declarations, private / public variables in CFScript. There is no advantage to using JS/AS to cfscript as you will *still* have to write wrappers for cfquery, cfhttp, etc etc.

    3) Although it is getting better, ECMAScript has some conventions that even the creators admit was a mistake (such as colon type declarations). Javascript takes the cake for RLOF (remarkable lack of foresight) when it comes to creating objects – who came up with the crazy idea of creating an object and then injecting properties and methods? Why not follow convention? These guys say "HELL NO" to convention.

  15. Danny Armstrong

    I just ran into this thread while researching a curious limitation in cfml (the fact that getMetaData will return "runtime expression" for dynamic defaults in cfargument).
    Have you had any luck in working out the performance issues associated with disk reads? Any further developments in creating a reliable reusable pattern for implementing apps on the cf platform in this way?
    I'm glad you started a discussion about this. It is troubling to me, however, that many people have a very hard time admitting the deficiencies in cfml. Worse yet are the misunderstandings of JS(ECMAScript), clearly evidenced in Joel Cass' statement "Javascript is a … cumbersome language when compared to the likes of java…" A terrifying statement indeed because it reflects such ignorance on the part of Joel. I'd venture to say that out of everyone who has ever written JS he is the only one who has ever made this observation. Java is easy to use in CF for small things but be able to use JS in CF you will have a much more scalable solution.
    Challenging a convention and finding the convention to be either predicated on outmoded thinking or simply not beneficial enough to warrant harping on is liberation in my opinion.

  16. CF Groovy at BarneyBlog

    [...] of you who remember CF Rhino will recognize the name for my latest little project. I whipped up a small proof-of-concept [...]