Grails Controllers
Let’s first create a stand-alone controller. grails create-controller MostPopular generates grails-app/controllers/MostPopularController.groovy. This isn’t tied to any model, but delivers the FAQ page and the “most popular songs” page.
import Song
class MostPopularController {
def index = {
params.max = Math.min( params.max ? params.max.toInteger() : 30, 100)
params.sort = ‘numDownloads’
params.order = ‘desc’
[
songList: Song.list(params),
songInstanceTotal: Song.count(),
albumList: [
Album.findByPublicID(‘hipcitycruz’),
Album.findByPublicID(‘namelyus’),
Album.findByPublicID(‘markgrowden’)
]
]
}
def faq = { }
}
The faq action does not need to do any extra work. Like the Rails controller, the existence of the method is enough by itself to tie in the relevant view. The index action is a little more complex. It specifies how many songs to display and how the songs are ordered. The same action can also be re-used to build a list of featured albums along the left rail.
So far, there’s little different between the Rails and Grails controllers. Things get a little more interesting with scaffolding.
Dynamic Scaffolding and Authentication
Grails allows you to generate scaffolding, if you desire. This can be useful as a form of tutorial; in contrast to the Rails generated pages, the generated Grails code is easy to follow and a good guide of how things should generally be done for a Grails action. (In fairness to Rails, its approach is somewhat more flexible, in that its generated scaffolding can respond to multiple formats. With the recent popularity of RESTful architectures, being able to easily generate XML or HTML pages from the same action is undeniably cool). Unlike Rails, however, Grails still has both pagination and dynamic scaffolding built-in. Also unlike Rails, Grails dynamic scaffolding actually, well, does the job.
To illustrate, let’s generate a scaffold for comments. If you already generated the model and added in the relationships, your Comment domain class may look something like this:
class Comment {
static belongsTo = [album:Album,user:User]
String title
String body
Date postDate
}
Given the model, the corresponding controller can be created with grails create-controller Comment. Once you have the controller, adding the logic for the admin tools takes a single line of code:
class CommentController {
def scaffold = Comment
}
This results in the following looking admin page for comments:

That does not look too bad, but it might be nicer to make the Album and User fields a little more usable. As it turns out, this can be easily done by giving these two domain classes a toString method. Use the publicID field for Album and username for users:
class Album {
…
double price
String blurb
String toString() { publicID }
}
class User {
…
static hasMany = [comment: Comment]
String username
String password
String email
boolean admin
String toString() { username }
}
But there are a few more issues. For one, if you click on “new comment”, a text field appears for the comment body. A text area seems like a better choice. Also, the order of fields might be better if the user and album were first and the comment body last.
You can solve all of these issues by using constraints. The order of constraints determines the order of the fields. Further, if you specify the widget property, you can change the body to be a text area. Here is the updated grails-app/domain/Comment.groovy:
class Comment {
static constraints = {
user()
album()
postDate(blank:false)
title(maxLength:100)
body(maxLength:10000, widget:‘textarea’)
}
static belongsTo = [album:Album,user:User]
String title
String body
Date postDate
}
The updated version looks much better:

At this point, however, the form is still publicly viewable. Like Rails, Grails offers some good tools to restrict or limit access. One final adjustment to the controller restricts these pages. And for good measure, let’s add another action to post a comment. This latter action is public, and needs an exception for authentication.
class CommentController {
def beforeInterceptor = [
action: this.&auth,
except: [ ‘addComment’ ]
]
private auth() {
if (!session.user) {
flash.message = "Please log in to view that page"
redirect(controller:‘user’, action:‘login’)
return false
}
else if (!session.user.admin) {
flash.message = "Sorry, but you do not have permission to view that page"
redirect(controller:‘mostPopular’, action:‘index’)
return false
}
}
def scaffold = Comment
def addComment = {
if (!session.user) {
flash.message = "Please login to post a comment"
redirect(controller:‘user’, action:‘login’)
}
def comment = new Comment(params)
comment.user = session.user
comment.postDate = new Date()
if(!comment.hasErrors() && comment.save()) {
flash.message = "Your comment has been added"
}
redirect(controller:‘album’, action:‘display’, id:comment.album.id)
}
}
Forms
With an admin tool for managing comments and a new action to allow users to post comments, the application now needs a new form to author a comment. A comment is associated with an album, so an album controller and view must be generated. Run grails create-controller Album and add a new action to grails-app/controllers/AlbumController.groovy:
class AlbumController {
def display = {
def album = Album.get( params.id )
if(!album) {
flash.message = "Album not found with id ${params.id}"
redirect(action:list)
}
else {
def tracks = Song.findAllByAlbum(album)
return [ album: album, tracks: tracks ]
}
}
}
Next is the corresponding view. Here is the excerpt related to posting and displaying comments:
...
<div id="add-comment">
<h3>Post a comment for ${album.title}</h3>
<g:form method="post" controller="comment" action="addComment">
<input type="hidden" name="album.id" value="${album.id}" />
<label>Title</label>
<input type="text" name="title" />
<br />
<label>Comment</label>
<textarea name="body"></textarea>
<br />
<br />
<label> </label>
<input type="submit" value="Add Comment" />
</g:form>
</div>
<div id="comments">
<h3>Comments</h3>
<g:each in="${album.comment}" var="${comment}">
<div class=‘comment’>
<strong>${comment.title}</strong><br />
<em class=‘byline’>posted by ${comment.user.username}</em><br />
<hr />
<p>${comment.body}</p>
</div>
</g:each>
</div>
</div>
…
Grails’s approach relies on proper use of the name attribute for input fields, but this does not seem onerous and it is better to not have to differentiate between fields that are related to the model and those that are not.
Static Scaffolding
While dynamic scaffolding is useful, there are times when the defaults do not work.
To store the passwords in hashed form, the default scaffold controller must be modified. grails generate-all User creates the controller and views. (Replacing the second argument with generate-controller or generate-views would instead generate only the specified part, leaving the other to be generated dynamically.)
Let’s change the save action. (You also need similar, new methods for registering users and logging in.)
...
def save = {
params.password = Utils.md5sum(params.username + params.password)
def userInstance = new User(params)
if(!userInstance.hasErrors() && userInstance.save()) {
flash.message = "User ${userInstance.id} created"
redirect(action:show,id:userInstance.id)
}
else {
render(view:‘create’,model:[userInstance:userInstance])
}
}
…
Now the passwords are saved in hashed form, salted with the username. Of course, the md5sum() method must also be defined. Once again, turn to Java for this function.
Integration with Java
More than the other frameworks, Grails is designed to integrate smoothly with Java. This is one of the core reasons that Groovy was chosen as its scripting language. Groovy syntax is a superset of Java 1.4 syntax.
As with the Rails implementation, code must generate MD5 hashes of users’ passwords. This code is saved under grails-app/utils/Utils.groovy:
import java.security.*;
import java.math.*;
class Utils {
public static String md5sum(String s) throws Exception {
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(s.getBytes(), 0, s.length());
return String.format("%32s", new BigInteger(1, m.digest()).toString(16)).replace(‘ ‘, ‘0′);
}
}
You may remark that this looks suspiciously like Java code, and in fact it is both valid Java and Groovy. This is likely to be the version that you would get back from a reluctant Java-turned-Groovy developer. It may be verbose, but it gets the job done.
Grails actually allows for a much greater degree of interaction. You can write portions of your application in Java or in JSPs. You can also shift your application to use Hibernate or Spring configuration files. Grails offers ways to de-Groovy the application to the point where you have a standard Java stack.
Testing
Once again, you can test this utility. Save this as test/unit/UtilsTests.groovy:
import grails.test.*
class UtilsTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
}
protected void tearDown() {
super.tearDown()
}
void testMd5sum() {
assert "fe01d67a002dfa0f3ac084298142eccd" == Utils.md5sum("orange")
assert "72b302bf297a228a75730123efef7c41" == Utils.md5sum("banana")
assert "c7a4476fc64b75ead800da9ea2b7d072" == Utils.md5sum("cherry")
assert "9dee45a24efffc78483a02cfcfd83433" == Utils.md5sum("pineapple")
assert "3f24e567591e9cbab2a7d2f1f748a1d4" == Utils.md5sum("lemon")
assert "67c0ecaf5a1b782b11146e9fbe80f016" == Utils.md5sum("lime")
assert "aa00faf97d042c13a59da4d27eb32358" == Utils.md5sum("mango")
assert "027086dff18471311f7816dba7f92909" == Utils.md5sum("artichoke")
}
}
grails test-app runs this unit test, which passes with flying colors. You might notice the use of assert instead of assertEquals or something similar. It turns out that there is no equivalent for Grails. As a result, with no leading zeroes, the error message is far less informative:
...
Running test UserTests...PASSED
Running test UtilsTests...
testMd5sum...FAILED
Tests Completed in 1338ms ...
With Grails, you are wiser to limit your test cases to a single assert per method. Some maintain that this is good style regardless, though others find it cumbersome.
Grails includes unit tests and integration tests. It does not, however, come with tools for performance testing, nor does it have any built-in equivalent to Rails’s fixtures. Grails does not generate functional test cases the way that Rails does. While testing for Grails is perhaps adequate, it is one area where it is still playing catch-up to Rails.
A Couple of Negative Points
For the most part, Grails seems to offer most of the advantages of Rails and layers nice extras on top. Unfortunately, there are a couple of areas where Grails does not fare so well.
Groovy is slow. The stock response from the Groovy community is, “Use Java for the performance-critical parts.” And in Grails’s defense, it is arguably the framework best suited to mixing in Java code and libraries. However, it seems likely that Grails must resort to Java sooner and more frequently than with the others.
Also, Grails seems to be the buggiest of the frameworks in development mode and required frequent restarts to pick up code modifications. This would be only a minor gripe, except that Grails launches very slowly.
Is Grails the Holy Grail?
Despite some complaints, Grails was a delight to work with. It is a feature-rich framework, and integrates more tightly with Java than the others. Installation was a breeze. Like with JRoR, you can deploy your application as a WAR file (and unlike JRoR, this is a built-in feature). All in all, Grails may be the best option for Java web development shops looking to achieve some of the nimbleness of Rails on the JVM.
The Good
- Flexibility and strong organization you expect of Rails
- Best integration with existing Java tools
- Good tag libraries and excellent support for internationalization
The Bad
- Slow startup
- Need to restart frequently during development
- Might be a little more problematic to update database