Yes, I know it's Lent, but I'm not talking about that Grail – I'm talking about Grails, the web framework for Groovy (the dynamic layer for Java).
I've been looking for a way to ditch CFML for a while now, but nothing has really hit the mark. I keep hoping that Adobe is going to release CF8.1 with Flex 3 and allow all your server-side scripting to be in ActionScript 3, but I'm not holding my breath. The CF platform is pretty nice (excepting the massive bloat), but the CFML language itself just blows ass. So I shop…
I liked SpringMVC/Spring/Hibernate when I was using it, but it's definitely enterprise-y. I've looked at Rails, but I really dislike Ruby's syntax, and ActiveRecord leaves something to be desired (like a query language). Django and Pylons (for Python) are slick seeming, but Python's whitespace-is-semantic paradigm is a big turnoff. My CFRhino "project" actually has some promise, I think, but not something I want to get into maintaining for real application development, and it's JavaScript, which means no real classes and classloading (among other things).
Enter Grails. Like it's counterparts in other languages, it's all about speed of development, but unlike the others, it's all Java. It's built on Hibernate, Spring, and SpringMVC. It compiles to bytecode. It seamlessly integrates with existing Java apps and tools (Quartz, Acegi, DWR, etc.). The paradigms it leverages were incredibly easy to jump into (granted, I've used it's backing tools before), and within a couple hours of seeing both Grails and Groovy for the first time, I had a quasi-functional blog platform.
The past week of developing a first "real" app has borne out my initial impressions to the nth degree. Groovy is a really slick layer that augments Java in just the right ways, without getting the way. Closure are a big deal, vastly superior to simple functions or Java's inner classes. You also get dynamic methods, iterators, native regular expressions, multi-line strings, ranges, a ternary operator (c'mon CF, it's not the 60's), the "elvis" operator which is the ternary operator with the middle clause omitted and the first clause used as it's value, and null-safe dot operator.
But Grails is where it's at.
class User { String username String password String email static constraints = { username(blank: false, unique: true, size: 4..16) password(blank: false, password: true, size: 4..32) email(email: true, blank: false) } }
That whopping 11 lines of code is sufficient to create a domain entity with three fields, create validation for the fields, create a Hibernate mapping, and set up all the SpringMVC goodies for binding, form generation/population, error messages, etc.
Request processing, you ask? You have a collection of controllers (think circuits, if you know Fusebox), each of which is a collection of actions (i.e. named closures) corresponding to requests (think fuseactions). So the URL "/login/doLogout" would map to the "doLogout" closure of the "login" controller. Each action closer can redirect, render directly, or return an arbitrary data structre to be passed to a view. By default, the view is a file named to match the action, in a folder to match the controller (you can override, of course), which is written in Groovy Server Pages (GSP). Think JSP, except without the heavy dose of suck. For example, you can define taglibs using Groovy, and then use them in both your views and your controllers, as either tags or as functions.
Grails (thanks to Spring) also provides all-encompassing dependency injection for not only your services and controllers, but for your domain objects as well, which is fantastic. That was one of the larger problems I had with using Spring and Hibernate directly, and one that I never was able to solve in a very satisfactory way. It also provides controller filters which are exceptionally handy (enforcing logins, adding model data for your layouts, etc.).
And the last big piece is SiteMesh, which is the [optional] layout toolkit. You can certainly use GSP for everything; simply include your header/footer as needed and go. But SiteMesh provides basic page wrapping functionality to ease the task, along with a very powerful content dissection/assembly framework (think Fusebox's contentvariables, except managed by the view as they should be).
Finally, yes, there is pretty comprehensive scaffolding support. It doesn't blow my skirt up as much as the other stuff though, but that's probably more a reflection on the type of apps I'm usually building rather than the general utility of the feature.
In case you can't tell, I'm impressed. The Grails guys have done a fantastic job at taking some incredibly flexible and powerful tools and making them ridiculously easy to use.
Great post. After my first look at Grails I thought it was so similar to Rails that I didn't need to look further in. This post, coupled with Sean Corfield's two recent posts about Groovy and Grails has made me rethink that position.
I'll be digging deeper into it at some point.
Barney, thanks for the comprehensive post GRAILS-GROOVY certainly seem worthy of a closer look and I will do so, time permitting. Do you have any thoughts on how easy or hard debugging is? I spend much of my time troubleshooting and fixing applications and ColdFusion has always had great debugging information?
Mike,
Since Grails is all Java-backed, you can use all your standard Java tools (e.g. Eclipse debugger) to debug your apps. The runtime error template is part of your project (generated for you, of course), so you can customize to your heart's content which is handy as well.
More important, I think, is that you get far better tool support with Groovy/Grails. That lets you catch a lot of potential errors in the IDE rather than at runtime, especially if you leverage static typing where appropriate. Regardless of how good the debugging tools are, not having to do it at all is always better.
Thank you sir.
This is just what the doctor ordered. I had a similar experience with rails and python. Java is great but it has a huge learning curve and I am still very much a beginner. But I was able to dig right in with Grails and felt comfortable right off the bat.
Having support for Eclipse and Netbeans is huge.
Interesting to see you post such a glowing review of Grails after I'd posted two similarly enthusiastic pieces. I only investigated it because of a comment by Dave Ross – after Derek Perez had been bugging me about Groovy. Coincidence or critical mass? :)
Sean,
I'm not going to call it either way, but Grails definitely provides a lot of stuff that a certain set of CF developers have been crying out for, and does it without requiring as large a shift as other alternatives. I haven't done it, but I see no reason that you couldn't easily build a hybrid CF/Groovy/Grails app, and with enormously less pain than CF/Java hybrids.
I know I'm going to be doing CF for a good while since Mentor's heavily entrenched. CF's relevance is definitely waning (regardless of Adobe's sales figures). Perhaps an influx of good ideas could buoy it.
I hate to drag out a discussion Barney but why do you believe that CF's relevance is waning? This is a genuine question because from my end of things in the server tuning business I see large entities that were not CF users needing help. Also I don't see any of the associated companies pulling back or financially in trouble (New Atlanta for instance). None of the companies which were spawned from the Macromedia Consulting division have gone. Webapper, Universal Mind etc, in fact Universal Mind were recently listed in the Fortune 500.
I have no doubt that Groovy and/on Grails is an exciting track to go down but I am not sure that relates to CF being less relevant; just my opinion from indicators that I see. Thanks again.
Mike,
Eight years ago, CF was awesome. It blew the pants off other languages available for developing web apps quickly and easily. These days, it's a far less compelling choice. I doubt it's market share has diminished, but I feel that it's relevance has.
I wasn't referring specifically to Grails as the reason for it; I've had that opinion for quite a while. There are a whole pile of web toolkits out there now, and they're breaking some cool new ground. I wouldn't care to use a number of them, but I do appreciate what they're doing. CF, on the other hand, has done little. CFC's were a step in the right direction, but the implementation is poor in many ways. Other than that, almost all improvements have just been reinventing the wheel with CFML syntax, and often in a very limited way (consider the mess that is CFTHREAD, or the breaking of CFMAIL when CFMAILPARAM was added).
I just wanted to comment on something you said about Rails ActiveRecord. Like you, I've switched away from CF for a variety of reasons; unlike you, I'm currently using Rails, and I very much like Ruby's syntax — it's certainly different from a lot of other languages, but I think it's extremely well designed.
Anyway, you said that ActiveRecord doesn't have a query language. If I understand correctly what you're getting at, that's not quite true, at least in the sense that you can pass native SQL code to ActiveRecord.find_by_sql . There's certainly nothing in Rails like EJBQL, but to my mind that's OK — who needs to learn yet another dialect of SQL?
How does Groovy deal with this? I've never worked with it, although my last job was with a company that created what as far as they knew was the largest Groovy project to date. But I wasn't working on that project.
Marnen,
Groovy doesn't have any sort of ORM framework itself, though it does have a slick-seeming SQL interface. I haven't actually used it, so I can't say for sure though.
Grails uses Hibernate under the hood, so you have access to the full Hibernate stack, including HQL. I suppose picking up the dialect is a bit of work, but it's never been an issue for me, even when starting. More troubling is thinking in terms of querying objects, rather than tables. That's a conceptual hurdle that took me a while to get my head around (and I still sometimes butt up against). However it does allow a far more business-model-centric way of querying which is quite nice, as well as providing an abstraction layer that allows you to extend the query language in an application-specific (and DB neutral) way.
When I said ActiveRecord didn't have a query language, I was referring specifically to querying the conceptual object store to select instances. find_by_sql doesn't even come close to that: it's nothing more than a way to do raw SQL queries against the DB connection configured for ActiveRecord. It's really more analogous to getting a Connection object from Hibernate and doing SQL against it (using Groovy's SQL stuff, or plain JDBC).
As far as I can tell, you're right that Rails ActiveRecord doesn't really support queries of the conceptual object store *as distinct from the database*, but I'm not convinced that that's a problem. I'm not really sure how this feature would be useful in Rails in actual practice. I think there's a feeling that the database *is* the conceptual object store, for all practical purposes. Besides, the ORM is complete enough that it's trivial to add objects to and remove objects from the database as necessary, and this way there's no issue of persistence.
If I understand correctly what you mean by "business-model-centric way of querying", it should be possible to add that to your Rails models quite easily.
Also remember that Ruby classes are always open. It probably wouldn't be *that* difficult to extend Rails ActiveRecord to do Hibernate-style queries, although no one has done it so far as I can tell.
Or am I misunderstanding?
Marnen,
The distiction is that with SQL you have to understand the tables and columns, while with HQL (for example) you have to understand your classes and properties. Maybe I've got some nasty mappings to a legacy schema, or I need to segment a single entity into three tables for performance, or my DBA's are crazy and insist that all tables start with "TBL_" and columns use Hungarian Notation. All of these things should be transparent to the application: that's the point of ORM. But by using SQL I'm forced to deal with them. Using HQL, which is above the ORM layer, ensures that all that garbage stays hidden from the application. This is a hugely powerful distinction that often doesn't make much of a case for itself in simple applications, particularly top-to-bottom one.
You also save yourself from any database-specific stuff, which I've found incredibly useful because I can use Hypersonic (a crazy fast, in-JVM, memory-only DB) for unit tests, but deploy to a real DB without having to care about dialect differences.
OK, now I see your point. There are two issues here, then: query syntax and decoupling entity names from the database.
Query syntax is less problematic then you seem to suppose. Even without using find_by_sql, Rails has dynamic finder methods that will cover even fairly complex cases (you can do things like find_by_first_name_and_zip_code if you really need to, for example).
As far as entity names go, it's easy to use set_table_name and set_primary_key to tell Rails that the names of the table and primary key field are not what you'd think from the class name, so the only stumbling block is the attribute names. It's not well known, but a little digging unearthed the alias_attribute method, which allows you to easily create an alias for any attribute, so that you can do
class Customer < ActiveRecord::Base
set_table_name 'tbl_Customrz'
set_primary_key 'int_cust_id'
alias_attribute :name, :varchar_firstname_lastname
end
This will let you read and write to Customer#name. That leaves dynamic finder methods as the only real issue — in the current version (2.1.0), they don't appear to work with aliased attributes, but there's a patch at http://dev.rubyonrails.org/ticket/11354 that apparently fixes that problem (although I haven't tried it).
For one model made up of multiple tables, I would probably just create a DB view, or an abstraction layer of mediating objects. composed_of might come in handy here.
My point, then, is that Rails ActiveRecord does indeed have a suitable query language that can be uncoupled from the database. You don't hear much about it because Rails developers don't tend to use it that way, but it *does* exist.
Hi Barney,
Just wondering if you still play around with Grails these days?
Peter
Haven't in a long while. It's hard to dive heavily into tech that I can't use at work, ya know? And now with CFGroovy providing seamless inline Groovy scripting and Hibernate support to CFML apps, the benefits are even less.