Grails Scaffolding In-Depth
Much of Grails power and ability to crank out applications can be accounted to its scaffolding mechanism for creating CRUD interfaces within no time. However, the default scaffolding templates provide only a simple boilerplate and fail to convince for more sophisticated forms. I spent quite some time in the previous weeks writing scaffolding templates. A lot of this process was trial and error, browsing source code and bothering Tomás Lin. I still have to find good documentation on this, so I'm posting my findings here in the hope to help people leveraging Grails even more. If you are just trying to understand how scaffolding works to building something more advanced, this is for you.
Scaffolding in a Nutshell
I assume that you know what Grails and its scaffolding mechanism is about, but I'll just summarize it here.
In a nutshell scaffolding is Grails ability to create controllers and views for domain classes. It analyzes the structure of the domain objects and creates all the files and logic required for simple CRUD functionality. If you have some domain classes all you have to do is type the following from within your project directory:
$ grails generate-all
This will create controllers and views for all domain classes found. Note that there are generate-views and generate-controller commands as well.
However you'll soon find out that the default templates which are used to create all the files may not fit your needs. Grails offers a separate command to copy the default templates into your project directory:
$ grails install-templates
This will create a new folder src/templates in your project, holding an copy of the default templates, all yours to modify and adapt.
Grails Scaffolding Templates
Before we dive into the details of scaffolding, you need to understand the different templates and what they are for. Running the install-templates command will give you the following files withing your project directory:
src/templates
|-- artifacts
| |-- Controller.groovy
| |-- DomainClass.groovy
| |-- Script.groovy
| |-- Service.groovy
| |-- TagLib.groovy
| |-- Tests.groovy
| `-- WebTest.groovy
|-- scaffolding
| |-- Controller.groovy
| |-- create.gsp
| |-- edit.gsp
| |-- list.gsp
| |-- renderEditor.template
| `-- show.gsp
`-- war
`-- web.xml
The files relevant for the scaffolding process are in the scaffolding directory and have been highlighted with bold font. So, what are those files for? Let's examine them one by one.
The first one is Controller.groovy. This file is used to create the controllers for your domain classes. The syntax in this file may appear a bit weird in the beginning but after all it's just a groovy template (I really encourage you to read this!). With this in mind reading the templates gets very easy. In the Controller.groovy you basically will find all the actions you would expect from your scaffolded controllers and some groovy template markup.
Next are the GSP files, create.gsp, edit.gsp, list.gsp and show.gsp. Those are obviously used to render the GSP markup required for your CRUD views. At a first glance lots of magic happen in those files. We'll cover the details in just a minute.
Finally there is the renderEditor.template. This file is used when rendering the HTML forms. Basically what happens in here is a translation of a type like Date or byte[] to their according form elements like a date picker or a file upload button.
The Scaffolding Process
Alright, so what happens when you issue generate-all for a domain class? There are a couple of players involved in this game. As most obvious besides the templates we just saw there are the actual scripts, generate-all, generate-views or generate-controller which reside under $GRAILS_HOME/scripts. These scripts instantiate a DefaultGrailsTemplateGenerator which basically is a wrapper around Groovy's Template and TemplateEngine and binds together all the pieces we've encountered so far. You won't find any Javadocs about this class, so you'll have to browse the Grails sourcecode if you're interested. The DefaultGrailsTemplateGenerator then calls the actual templates.
One key aspect for creating really powerful scaffolding code is to understand what is handed into the templates by the DefaultGrailsTemplateGenerator. It took me quite some time and some source code browsing to figure this out. First there is a variable called propertyName. There isn't anything magical about it, just the name for a variable. However you will encounter this variable all over the templates. For example if scaffolding is run for a class called "User" propertyName would be "user" (note the lower case "u") and all variables of type "User" would be called "user" in the scaffolded output.
Then there is an instance of DefaultGrailsDomainClass which is handed into the template as a variable called domainClass. This class variable plays a major role in scaffolding as it allows you to access all kinds of information about the domain class the scaffolding process is handling. You can get information about the GORM mappings, the associations the class has and even the other side of the associations, which is crucial when building more complex forms and more. And yes, i really encourage you to read the Javadocs for this class.
Depending on whether views or controllers are generated either the create.gsp, list.gsp, edit.gsp and show.gsp or Controller.groovy are used as template.
Generating a Controller
When generating controllers the Controller.groovy file is used as template. What you will end up with is a new file named after your Class containing the usual actions required for CRUD. There is not much magic happening in here; the template is pretty straight forward and just creates calls for the different GORM methods. Read it to get a feeling for this.
Generating Views
However when generating views, things get more interesting. In the views and the renderEditor.template the domainClass property is actually used to determine information about collections.
So let's dive into the details of how the views are generated. If you look at the templates you'll see that all of them create a list of properties available for a domain class by querying the domainClass variable:
props = domainClass.properties.findAll { !excludedProps.contains(it.name) }
All that remains to do now is to iterate over those properties, determine whether they should be visible and call the renderEditor to actually render the required code. The following block of code has been copied from the edit template and has been commented by me to clarify:
props.each { p ->
cp = domainClass.constrainedProperties[p.name]
display = (cp ? cp.display : true) // Determine visibility
if(display) { %>
<tr class="prop">
<td valign="top" class="name">
<label for="${p.name}">${p.naturalName}:</label>
</td>
<td valign="top" class="value \${hasErrors(bean:${domainClass.propertyName},field:'${p.name}','errors')}">
${renderEditor(p)} // Call render editor to render correct form element
</td>
</tr>
This is basically what happens in all the templates. A list of properties is generated and iterated over. One piece is still missing: the renderEditor.template.
As stated earlier, the renderEditor.template translates the type of a property into the appropriate form control. The way this happens is disappointingly simple; open up the file in your favorite editor and you will find a big block of if-statements like this:
<% if(property.type == Boolean.class || property.type == boolean.class) out << renderBooleanEditor(domainClass,property) else if(Number.class.isAssignableFrom(property.type) || (property.type.isPrimitive() && property.type != boolean.class)) out << renderNumberEditor(domainClass,property) else if(property.type == String.class) out << renderStringEditor(domainClass,property) else if(property.type == Date.class || property.type == java.sql.Date.class || property.type == java.sql.Time.class) out << renderDateEditor(domainClass,property) ...
and further below the methods called by the if-statements:
...
private renderByteArrayEditor(domainClass,property) {
return "<input type=\"file\" id=\"${property.name}\" name=\"${property.name}\" />"
}
private renderManyToOne(domainClass,property) {
if(property.association) {
return "<g:select optionKey=\"id\" from=\"\${${property.type.name}.list()}\" name=\"${property.name}.id\" value=\"\${${domainClass.propertyName}?.${property.name}?.id}\" ${renderNoSelection(property)}></g:select>"
}
}
...
So in the rendering process for each property the type will be matched in the if statements and the appropriate function is called to render out some HTML/GSP code.
Conclusion
Creating scaffolding templates is not hard. It requires some knowledge about the involved technologies and concepts but I hope this post gives you a fair understanding of what is going on. If you still have any questions, feel free to comment or drop me an email.
As always, comments are welcome.

January 4th, 2009 - 06:13
Excellent post got me through a big jam
January 8th, 2009 - 07:17
Hello There, nice post.
Do you know if there is a way to generate more views, besides list, show,create, update?
Thanks
January 10th, 2009 - 19:23
Hi,
this was really interesting and useful. I am currently tweaking the Grails scaffolding process and this article has been really helpful. Thanks!
January 11th, 2009 - 01:08
Hey,
with the default Grails scaffolding it’s hard to generate views besides the default ones because the views are hardcoded into the DefaultGrailsTemplateGenerator. If you need more flexible scaffolding you might want to look into the Xtemplates plugin: http://www.grails.org/Xtemplates+Plugin
Cheers,
Jakob
September 20th, 2009 - 23:00
Thanks for writing up your findings. One note is that propertyName is set to domainClass.propertyName + “Instance” rather than just the short name such as “user”.
This is a bit of a problem if you want to share view templates across controllers and use any dynamic controller scaffold code since the controller code will have a controller-specific propertyName. I’m not sure what the scenario is where there could be a name collision on the controller name. I use “instance*” rather than “${shortName}Instance” and its been OK so far…
December 30th, 2009 - 13:07
bevor ich das alles quasi abschreibe, verlinke auch ich lieber zu dir…
top post. wie die anderen auch. grails rockt. n’est pas? schöne grüße. sebastian.
April 7th, 2010 - 23:10
Thank you !!
May 18th, 2010 - 21:42
This is great. This should be added to the Grails documentation! Thank you.