Significant Productivity Gains with Grails?

DZone 's Guide to

Significant Productivity Gains with Grails?

· Java Zone ·
Free Resource

A colleague asked me today: "Would you argue that using Groovy / Grails can make you significantly more productive for smaller projects as compared to something like JSF? If yes, why?" 

In response, I created a very small application. At that point, when the small application was complete, I imagined I had shipped it to the customer. I then imagined that, much later, someone else had been given my sources with the instruction to add a new feature. Below, in two parts, are some general conclusions I drew as a result. Feel free to argue!

Creating the Initial Project

Here's the small application, i.e., an on-line pet cemetery. Everything below was generated by the Grails commands, following the Introduction to the Grails Web Framework, a document that also introduces you to the related NetBeans IDE tools.

There is one addition to what is outlined in the above document, in the context of the page shown below—I used the "grails generate-all" command in order to have Grails generate the controller and views for the domain class I had created. I then had 4 GSP files (i.e., Grails JSP files) which I tweaked slightly to change the texts.

The content above is some test data that I included in the application within the "BootStrap.groovy" file, which is one of several configuration placeholders that every Grails application provides:

class BootStrap {

     def init = { servletContext ->
         new Pet (type: "Cat", name: "Weebles", story: "Run over by tractor.").save()
         new Pet (type: "Cat", name: "Humphrey", story: "Attacked by rabid hamster.").save()
         new Pet (type: "Dog", name: "Mister Sox", story: "Flushed down toilet.").save()
         new Pet (type: "Cat", name: "Lucky Lambkins", story: "Hit in face by newspaper.").save()
         new Pet (type: "Dog", name: "Quincy", story: "Unforeseen avalanche.").save()
     def destroy = {

Secondly, this is how I created my domain:

class Pet {

String type
String name
String story

static constraints = {
type(blank: false)
name(blank: false)
story(maxSize: 1000)


Simply by defining a 'maxSize' larger than 255, I end up with a text area for the "story" item, while the "type" and "name" are both represented by text fields:

That's also great because it means... Grails gives me "domain-driven development". That's very powerful, since my domain is where all the knowledge of the application resides. Its structure and relationships, as well as a high-level encapsulation of user requirements, is also held by an application's domain. Really powerful feature of Grails that everything throughout the application is generated from the domain... right up to whether a domain item is represented by a text field or a text area! 

Also, to get the drop-down list containing the types of pets supported, I replaced the input element in the generated "create.gsp" class with the following element:

<g:select from="['Dog', 'Cat']" id="type" name="type"/>

Grails has a number of these special tags that provide out-of-the-box functionality, such as "g:countrySelect", for example, which gives you a drop-down list of country names.

Best of all, whenever I made a change in my application, I only needed to refresh the browser (i.e., no redeploy of the app was necessary) to see my changes.

Adding the New Feature

Next, I imagined I had shipped the above application to my end user. After some time, many dead pets having been registered, the end user wants to have some search functionality added. For whatever reason, someone else ends up tasked with the request. No problem, especially if they already know Grails, since everything in my project is in the same place as every other project that uses Grails (convention over configuration):

So first I create a new GSP file called "search.gsp" (for which I use a file template in NetBeans IDE). Once I had my new GSP page, I looked inside the "list.gsp" page for the place where the link to "New Dead Pet" is defined. (Remember, that list.gsp page, together with all its content, was generated by Grails, hence I didn't do anything in there except tweak some labels.) Having found that element, I simply copied it and then modified it, as follows:

Now, when I refreshed the browser, I saw this:

I clicked the new link and saw this:

Since all actions are defined in the related controller, I added a dummy search action there:

def search = {}

Refreshing the browser, I saw the "search.gsp" page that I had created earlier. The time had come to add some content. I called one of the predefined (i.e., not by me, but by Grails) methods on my domain object, using the IDE's code completion to search for the method I needed:

I ended up with ${Pet.count()} in my GSP page.

Refreshing the browser (i.e., again without doing a redeploy) I saw the result:

Now it was time to get serious! 

In almost no time at all, I created this simple search form...

...which, when the button is clicked, results in the following page being shown:

How to do it?

  1. Create two new GSP pages, one named "search.gsp" and the other "results.gsp".

  2. Copy the header from one of the generated GSP files, so that the look and feel of your pages is the same.

  3. Define the body of "search.gsp" like this:

    <g:form action="results">

    <g:textField name="type"/>
      <g:submitButton name="search" value="Search"/>


    <p>Searching ${Pet.count()} pets...

    Take note of the "name" attribute of the textField. Here it is called "type". Also take note of the "action" attribute of the GSP form. Here it is called "results". As a result of the "results" name, when the user clicks the button the "results" action in the controller is called, the "results.gsp" page opens, and the content of the textField is passed in as a parameter accessed via "params.type".

  4. However, the "results" action doesn't exist. Add it as follows to the controller, where ALL the actions are found, which is very convenient of course.
    def results = {
    def pets = Pet.findAllByType(params.type)
    return [ pets: pets, term: params.type ]

    Since we never created the "findAllByType" method on the Pet domain object, we need to spend some time creating that. But, wait a minute! We DON'T need to spend any time creating that because this is one of the many brilliant "dynamic finders" provided by Grails. Based on the definition of our domain object, Grails makes available a set of methods that can be called on our database, simply by passing in the search string received from the user! Here's the list of dynamic finders available to the pet cemetery application, created automatically by Grails for the domain object defined earlier:

    At this point, the "results" action makes two pieces of data available to its matching "results.gsp" page. Firstly, a search term and secondly a list of pets retrieved from the database. And here's the definition of the body of the results page shown earlier:

    <h1>Results for "${term}"</h1>

      <g:each var="pet" in="${pets}">
        <li><b>${pet.name}</b> (${pet.story})

    Then simply refresh the browser again and you have fully functioning search functionality! It gets a lot more powerful, i.e., this whole "dynamic finder" story, and a lot more complex, but for that you'll need to read "Grails in Action" by Glen Smith and Peter Ledbrooke.


At this point, I can go quite some way in answering the original question: "Would you argue that using Groovy / Grails can make you significantly more productive for smaller projects as compared to something like JSF? If yes, why?"

My answer in the affirmative is based on the following, resulting from the above experiments:

  • Grails creates a project structure and forces everything to be in a specific place, so that I don't have to worry about that and so that whoever ends up extending the application later will immediately know where to find everything.

  • Domain-driven development is great and it's wonderful that Grails forces me to work in that way. All the rules and requirements of my application can be defined and then I can generate the whole application framework around that. When the domain needs to change, I can regenerate the main files again and tweak them where necessary.

  • Built-in validation. Since the fields "type" and "name" are prevented from being blank, via the constraints closure in the domain class, the end user sees red error messages (which can be customized) and is prevented from storing such entries in the database, if either of these fields is blank.

  • Since so many files are generated, I can reuse a lot of the formatting and styles, simply by looking at how Grails did it for me in the other files. For example, the "search.gsp" and "results.gsp" took almost no time to make, since I copied so much from the "create.gsp" and the other generated GSP files.

  • All the actions are in the same place (the controller) and they are tightly connected to specific GSP files.

  • The GSP files have some very powerful tags, so that you can, for example, include a drop-down containing a list of countries or a date/time selector, coupled to your controllers and domain objects, without very much work at all.

  • Database access is handled for you so that, without knowing anything about either Hibernate or Spring, you're using them under the hood. It's also very easy to hook your own database into the application, replacing the in-memory system that Grails applications automatically have access to.

  • The "dynamic finders" are brilliant. I have no idea how they work, but I have no need to know either. They just work and my IDE supports me by showing what's available.

  • Groovy is the icing on the cake or, better put, the cement between the crevices, letting me code far more quickly and intuitively than I would be forced to do in Java.

  • No redeployment necessary during development. Tweak a file, change a controller, whatever, then save and refresh the browser and there's your change.

Anyway, that's what I'll be telling my colleague based on my personal experiences with Grails! Anything else I should be telling him about in this context? Probably quite a lot. For example, I haven't even touched on the built-in testing features yet! But, specifically for smaller projects, what else could be included in my list?



Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}