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?
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
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?
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?
Bruce,
The "problem" is really that CFML is an oft-cumbersome language. It's got a lot of inelegance to it, and its missing some very useful constructs. For example, while CFFUNCTION is very simple to use, it's also very verbose. Consider this:
<cffunction name="doIt" output="false">
<cfargument name="param1" />
<cfargument name="param2" />
</cffunction>
And the contrast it with this:
function doIt(param1, param2) {
}
Quite a bit less "garbage" in the latter example.
Then there's the missing functionality, such as function literals and their extension: closures. These concepts allow for the incredibly elegant solution of certain classes of programming problems, as well as just being generally useful. CFML doesn't have any way of expressing those constructs, and the tag-based nature basically prevents it from ever happening.
There's also some simpler things, such as object and array literals (and don't even try to say CF8 has that, it doesn't), nested functions, and even the shared global scope.
Finally, think about all the JavaScript libraries out there. You can just drop them into a JS-based server application and leverage them. Obviously that doesn't apply to DOM or Ajax centric stuff, but the environment-agnostic stuff is fair game. For example, I've used a few Prototype classes in the sample app.
In short, there are a lot of really nice things about ECMAScript that CFML doesn't (and can't) offer.
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?)
Gary,
See my response to Bruce above (posted a few seconds before your comment). In addition, I don't think people realize the fundamental difference between the CFML Language and the CF Platform. You want a one-stop shop for PDF generation? That's the platform, it's not tied to the CFML Language in any way. If I use .NET + JavaScript, I can't use CFDOCUMENT, but if I use CF + JavaScript, I can (though obviously with different syntax).
And while I didn't mention it above, there is a hook in the framework for including a CFML template from your JavaScript application. That's the way the Query object is implemented.
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.
Bruce,
I don't disagree with your perspective.
To continue your analogy, the Patriots, while undefeated, have allowed almost 100 points this season. So clearly they could be better. Pittsburgh, for example, has allowed about half as many. If something can be made better, doesn't that mean that it could be fixed?
I'm certainly not hoping that all CF developers drop CFML outside of UI templating and switch to JS. But I know that for a certain segment of applications I'll be using JS instead of CFML for the backend, and be happier for it.
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?
Brian,
For packaging external functionality, you have to pick an interface (the JS object(s) you'll deal with), and then implement it. For CFQUERY, I use the Query and QueryParam objects, and the implementation is an include of the 'cfquery.cfm' template. That particular implementation is both representative and massively complicated. The complexity comes from having to translate the parameter substitutions into CFQUERYPARAM tags embedded in the SQL statement, not the nature of the JS-to-CF bridge.
For CFLDAP, which I'm not terribly familiar with, you'd probably create an Ldap object with methods for each action you can perform, and accepting the relevant parameters. With all the optional attributes to the tag, you'd probably be better off defining explicit params for the required attributes and then an 'options' param that accepts a generic object of additional attributes. Keep the method signatures a little cleaner at the expense of some explicitness.
Implementing would be combining the explicit params with the options struct and the action name, and handing off to a 'cfldap.cfm' template which gets called with the new ATTRIBUTECOLLECTION attribute to pass everything in wholesale.
Querying was the only thing implemented in the sample app because that's all that I needed. Doing any sort of "real" development would require other tags, but now that the framework is mostly in place, implementing them should be straightforward.
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.
Clark,
I'm with you, and I don't even do that much AS. I probably spend half my time with Flex and half with HTML (usually JS-heavy), so even getting to JS on the backend is awesome.
If you like the idea, blog it, get your friends to blog it, and submit it to Adobe's wishlist. They do a pretty good job of listening to their users, but you have to make noise to be heard.
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.
Gary,
While I agree that the task of making AS3 a source language for CF is not trivial, I don't think it's as big as it could be. Adobe already has a AS3 compiler written in Java, so it's just a matter of generating bytecode with it, instead of a SWF. Porting the class libraries would be more work, but the core functionality (the hard part) is already done, it's just the interface that needs to be adapted to accept either a tag or a object/method invocation.
Time will tell…
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
Jeff,
Yeah, he's building Rails on top of Rhino. So not really part of Rhino itself, but built with it (much like a browser's environment is built with it). At least that's what I understand it to be. It'd be friggin' awesome if CF9 shipped with AS3 as a source language, though. Oh, how I'd love them forever if they did that.
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.
Mike,
I certainly agree that the "wrapping" nature of a tag-based language is very powerful. I definitely prefer that for querying, though I care for it less so with things like CFHTTP/CFHTTPPARAM (i.e. where there isn't any content, just subtags).
Regarding using AS3 to create server-side objects, if you design them right, you won't have server-side objects. You'll just have objects, and you'll use the same ones client side as you do server side. Obviously in different contexts (no UI on the server, no persistence ops on the client), but the same VO would suffice for both. Oh the possibilities for code reuse…..
Seems that every comment draws attention to another subtle facet that could dramatically improve development if we had this. I sure hope Adobe's listening.
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?
Hmm, the tags did not appear:
[cfcomponent]
[cfscript]
function foo() { }
function bar(a,b) { }
[/cfscript]
[cfcomponent]
Sean,
While the syntax is fairly similar between CFSCRIPT and ECMAScript, that's about as far as the similarity goes. No function literals, no closures, no object prototypes, no nesting, no object and array literals, etc.
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!
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.
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.
Danny,
I haven't really tried much. I never had any real expectation that CFRhino would be a viable platform. I don't have the resources to dedicate, and it's predicated on a number of rather tenuous constructs. With CF being closed source, there's not really a way to hook into it in a good way, I don't think. I.e., you really need to get down into the CF internals a bit to end up with something that's actually useful in the real world.
Interestingly, this same model would worth with any Java scripting language, and since CF's interface is really just shelling out the script as part of a JEE request, it's quite possible that projects centering around other language (Groovy, JRuby, etc.) would provide infrastructure for this model. They wouldn't be wedded to the CF platform, of course.
[...] of you who remember CF Rhino will recognize the name for my latest little project. I whipped up a small proof-of-concept [...]