As Barney Boisvert has demonstrated with his CFGroovy custom tags, scripting in Java is surprisingly easy. As he explains in the CFGroovy project, any scripting language that is JSR-223 compliant can be executed inside of a Java-based context with mostly-seamless communication between the Java context and the scripting context. The CFGroovy project was designed originally (I think) to work with Groovy; but, it can now be used run code through any JSR-223 compliant script engine implementation in your Java classpaths.
Because the set of available script engine implementations depends on your JRE, we need to ask Java to see what's available. We can get this information from the Javax script engine manager:
<!--- Get the script manager class. ---> <cfset scriptManager = createObject( "java", "javax.script.ScriptEngineManager" ) /> <!--- Get the factories that are natively available. ---> <cfset scriptFactories = scriptManager.getEngineFactories() /> <!--- Loop over the factories and output the names that each can build. ---> <cfloop index="scriptFactory" array="#scriptFactories#"> <!--- Output factory name and version. ---> <cfoutput> [ #scriptFactory.getEngineName()# - #scriptFactory.getEngineVersion()# ] <br /> <!--- Output the names that this factory will respond to (the names for which it can create valid script engines). ---> <cfloop index="alias" array="#scriptFactory.getNames()#"> - #alias#<br /> </cfloop> </cfoutput> </cfloop>
Here, we are asking the script engine manager for its factories, and then, from each factory, we ask it for the list of "names" for which it can create script engines. When we run the above code (on my personal JRE), we get the following output:
[ Mozilla Rhino - 1.6 release 2 ]
When we run the above code, we get the following output:
Message: Katie is hilarious!
Nice article, Ben. It's worth mentioning that you can run the non-DOM pieces of standard JS frameworks on the server-side without any fuss. I was doing this with the Prototype core back in the CFRhino days. So you can very easily use some of the tooling you use client side on the server.
Also, the Rhino implementation that ships with the JRE is not the full Rhino implementation. They've removed E4X support, specifically, along with a few other changes. Sun has published a list of things they've changed, but I'm not sure where that's available. However, if you want to use a different version of Rhino, you just have to drop the JAR on your classpath and you'll be set. And in fact, chances are good you're not using the Sun-packaged Rhino anyway; ColdFusion ships with at least two different versions of Rhino inside.
In my next post, I am going to cover what is needed to run full jQuery using John Resig's env.js project.... significantly more complicated than the above example. Ironically, it still uses CFGroovy since Groovy just makes it so much easier to create class loaders and other Java-like constructs.
You can get the OpenBD plugin here:
@Peter thank you so much for that link! I had no idea there were others with my CFJS desire let alone one building it. I added a request for it to Railo's user voice site and not a single user other than a guy I work with voted for it!
Now if only it can be done on Railo too then there would be a clear reason for Adobe to build it into CF10 and then CFJS can take over the world! :)
(at least in my day dreams)
I tried to vote for it - but I can't find it?
I had forgotten how ambiguous I had made it, I have added one a bit easier to find:
Have voted - thanks
A follow up to this post, this time executing jQuery on the ColdFusion server:
That is absolutely sweetness man. I love JS.
I am having trouble with a super simple example:
- <cfimport prefix="g" taglib="/../lfcomponents/customtags/cfgroovy2/">
- <cfset variables.message = 'original'>
I get the error "Java class "coldfusion.runtime.PageScope" has no public instance field or method named "message". (#1)"
Are there any docs for groovy? How do I get variables in and out of Groovy?
Most importantly, can I create a variable within the Groovy context, without first defining it in CF, and have it available to CF after Groovy has completed its execution?
Do I have to reference all CF variables like:
After looking at some more examples, one of Ben's examples, that I tried (and that works):
But, when I lang="js":
- <g:script lang="js">
The same code throws an error:
"Java class "coldfusion.runtime.PageScope" has no public instance field or method named "myString". (#1)
So, are there some rules or docs for using the JS engine? I can't seem to create variables within Groovy and get them back to CF. Any ideas?
Guess I should have read a little bit closer as the way to get CF vars in and out is described above: