March 2007: Introduction To Grails

Introduction To Grails

By Jeff Brown, OCI Principal Software Engineer

March 2007


Introduction

Grails is a framework for agile web development using Groovy and Java. There are already a lot of frameworks for building web applications in Java so one may ask "Why another web framework for the Java platform?" or "What really sets Grails apart from all of the other choices?". This article aims to help answer those questions and others by demonstrating how simple it can be to build web applications with Grails. By leveraging the power of a "Coding By Convention" paradigm and combining that with a stack of best of breed Java technologies Grails provides a framework and set of tools to greatly simplify the task of building web applications for the Java platform. The technologies that Grails builds upon include Spring, Hibernate, Sitemesh, Quarts and others. The flexible, dynamic nature of Groovy ties all of that together in a way that developers will find refreshingly simple to deal with.

"Coding By Convention" is one of the techniques that Grails uses to help developers build and maintain web applications without a lot of complexity. Coding By Convention results in very little configuration being required in a typical Grails application. This means that more of your effort and more of your code is directly related to the application requirements and less is related to configuring the framework. For example, in a Grails application a typical HTTP request will be handled by some controller and the controller will then render some view back to the client. There is no configuration file necessary to map a request to a specific controller and no configuration file is involved in deciding which view corresponds to that particular request. All of that can be managed by following some basic conventions. Several examples of this will be shown later in this article.

This article is designed to provide an introduction to Grails including coverage of the basics needed to get started developing applications with Grails. References to texts providing comprehensive coverage of Grails are included at the end of this article.

Installing Grails

Getting a development environment in place to support building web applications with Grails is made very simple by the fact that Grails bundles almost everything needed in one neat package. Grails does not require a lot of dependencies that need to be installed and configured. There is no need to download and install Hibernate or Spring or any of the other libraries that Grails is built on. You will need a JDK (1.4 or later). No special editor is required. Your favorite Java IDE will work. NetBeans, IntelliJ IDEA and Eclipse are all fine IDEs for Grails development. You might find that lighter weight development tools are often all that are required to maintain Grails applications.

Grails may be downloaded from http://grails.org/download. At that site you will find the latest stable release as well as development snapshots. Note that the development snapshots are not necessarily stable and may contain partially implemented features. The snapshot releases posted to that page are the result of the latest successful build from the Cruise Control build machine. At the time of this writing, 0.4.2 is the latest stable release and all of the code described in this article will work fine in that release.

Once you have downloaded a release in either zip or tar.gz format, extract the archive to some place on your file system where you choose to store development tools. You will need to set an environment variable called GRAILS_HOME to point to the Grails installation directory and modify your PATH environment variable to include $GRAILS_HOME/bin.

Getting Started

Very quickly you should be able to get a simple Grails application up and running with support for basic create, read, update and delete (CRUD) operations for a simple domain class. The steps here will take you through creating your first Grails application very quickly. Later we will cover more details. The goal with this first application is to get the most basic application up and running.

The first step is to create an empty application. Like most development tasks in Grails, creating the application is a simple task. Grails provides a number of command line actions that may be invoked as arguments to the "grails" command. The command to create a new application is called create-app. The create-app command accepts an argument that is the name of the application to be created. The command shown below creates an application called testapp.

$ grails create-app testapp
 
Welcome to Grails 0.4.2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/jeffbrown/Tools/grails
 
Base Directory: /Users/jeffbrown/article
Environment set to production
Note: No plugin scripts found
Running script /Users/jeffbrown/Tools/grails/scripts/CreateApp.groovy
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/src
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/src/java
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/src/groovy
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/src/test
 
( ... )

The create-app command has created a shell Grails application in the testapp/ directory. Once the application is created, all other Grails commands should be executed from within the project directory.

The next command to execute is the create-domain-class command to create our first domain class. Create a Person domain class.

$ grails create-domain-class Person
 
Welcome to Grails 0.4.2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/jeffbrown/Tools/grails
 
Base Directory: /Users/jeffbrown/article/testapp
Environment set to production
Running script /Users/jeffbrown/Tools/grails/scripts/CreateDomainClass.groovy
     [copy] Copying 1 file to /Users/jeffbrown/article/testapp/grails-app/domain
Created  at /Users/jeffbrown/article/testapp/grails-app/domain/Person.groovy
     [copy] Copying 1 file to /Users/jeffbrown/article/testapp/grails-tests
Created Tests at /Users/jeffbrown/article/testapp/grails-tests/PersonTests.groovy

The create-domain-class command has created an empty domain class in grails-app/domain/Person.groovy and has created a unit test class at grails-tests/PersonTests.groovy. Open the Person.groovy file in your favorite text editor and add a few simple attributes.

  1. class Person {
  2. String firstName
  3. String lastName
  4. Integer age
  5. }

Next, create a controller for the Person class by executing the create-controller command.

$ grails create-controller Person
 
Welcome to Grails 0.4.2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/jeffbrown/Tools/grails
 
Base Directory: /Users/jeffbrown/article/testapp
Environment set to production
Running script /Users/jeffbrown/Tools/grails/scripts/CreateController.groovy
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/grails-app/views/person
     [copy] Copying 1 file to /Users/jeffbrown/article/testapp/grails-app/controllers
Created Controller at /Users/jeffbrown/article/testapp/grails-app/controllers/PersonController.groovy
     [copy] Copying 1 file to /Users/jeffbrown/article/testapp/grails-tests
Created ControllerTests at /Users/jeffbrown/article/testapp/grails-tests/PersonControllerTests.groovy

Edit PersonController.groovy and add a property called scaffold and assign that property a value of true for now to enable dynamic scaffolding for the Person class.

  1. class PersonController {
  2.  
  3. def scaffold = true
  4.  
  5. }

That is it. Everything is in place to run a basic CRUD application. Execute the run-app command to start the application.

$ grails run-app
 
Welcome to Grails 0.4.2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/jeffbrown/Tools/grails
 
Base Directory: /Users/jeffbrown/article/testapp
Environment set to development
Running script /Users/jeffbrown/Tools/grails/scripts/RunApp.groovy
Compiling sources...
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/web-app/WEB-INF/lib
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/web-app/WEB-INF/spring
     [copy] Copying 33 files to /Users/jeffbrown/article/testapp/web-app/WEB-INF/lib
 
( ... )
 
FrameworkServlet 'grails': initialization completed in 87 ms
Servlet 'grails' configured successfully

That last line of output there is your sign that the application has started successfully. Access the application by pointing your web browser at http://localhost:8080/testapp/ where the standard Grails application welcome page should be displayed including a link to the Person controller. Following that link you can navigate around using the dynamically generated scaffolding code which provides CRUD capabilities to manage Person objects. The interface is very intuitive and simple to interact with.

Grails Welcome

Note that while running in development mode, by default your grails app will be saving data to an in memory HSQL database. The configuration for the application's data source may be found in grails-app/conf/DevelopmentDataSource.groovy which looks like this:

  1. class DevelopmentDataSource {
  2. boolean pooling = true
  3. String dbCreate = "create-drop" // one of 'create', 'create-drop','update'
  4. String url = "jdbc:hsqldb:mem:devDB"
  5. String driverClassName = "org.hsqldb.jdbcDriver"
  6. String username = "sa"
  7. String password = ""
  8. }

The data source configuration file may be modified to suit your development needs. The default in memory database is very nice for doing iterative development while your domain model may be changing frequently.

MVC In Grails

Grails takes advantage of the Model-View-Controller (MVC) design pattern to partition responsibilities within the application and to simplify the application architecture. Model classes should represent the domain objects in your system. Controller classes should control the flow of the application. View artifacts should focus on presentation. Following conventions recommended by Grails will keep your application clean and will help make the application flow easier to follow.

In the simple example above a single domain class was defined in grails-app/domain/Person.groovy. A controller was defined in grails-app/controllers/PersonController.groovy that was configured to use dynamic scaffolding. Since the dynamic scaffolding was enabled all of the view resources were created at runtime. For a simple admin interface the dynamic scaffolding may be fine but for most real applications view artifacts will need to be created.

Grails Controllers

In order to get a better understanding of how Grails controllers work we will extend the testapp to use generated scaffolding instead of dynamic scaffolding. Generated scaffolding is similar to dynamic scaffolding except that generated scaffolding is created before runtime and may be modified to suit your application needs. The generated scaffolding in Grails is often a good starting point and can serve as a way to learn 'The Grails Way'. Looking at the generated code is a great way to get started. To generate scaffolding for the Person class run the generate-all command. Note that since we already have a PersonController class Grails will ask us to confirm that we want to overwrite that class. Alternatively you may choose to delete the controller before running generate-all.

$ grails generate-all Person
 
Welcome to Grails 0.4.2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/jeffbrown/Tools/grails
 
Base Directory: /Users/jeffbrown/article/testapp
Environment set to production
Running script /Users/jeffbrown/Tools/grails/scripts/GenerateAll.groovy
Compiling sources...
   [delete] Deleting directory /Users/jeffbrown/article/testapp/web-app/WEB-INF/grails-app
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/web-app/WEB-INF/grails-app/views
    [mkdir] Created dir: /Users/jeffbrown/article/testapp/web-app/WEB-INF/grails-app/i18n
 
( ... )
 
Generating controller for domain class [Person]
Controller PersonController.groovy already exists. Overwrite?y,n
y
Controller generated at ./grails-app/controllers/PersonController.groovy

After the scaffolding is generated take a look at grails-app/controllers/PersonController.groovy. You will see that the controller defines a number of closure properties including list, show, delete, edit, update, create and save. These closure properties are mapped to URLs by convention so that a URL like http://localhost:8080/testapp/person/list/ will invoke the list closure in the PersonController class.

The default scaffolded list closure property should look something like this:

  1. def list = {
  2. if(!params.max)params.max = 10
  3. [ personList: Person.list( params ) ]
  4. }

This closure is returning a Map that has 1 entry in it. The key for that entry is personList and the value associated with that key is a list of Person objects returned from the Person.list(params) call. You may notice that our Person class did not define a List method. The method being invoked here is one of the many dynamic methods that Grails adds to all domain classes. The Groovy Object Relational Mapping tool known as GORM provides very powerful and flexible query mechanisms like this. At the end of this article is a reference to the documentation where all of the dynamic methods added to domain classes are described in detail.

This particular controller action doesn't specify a view to be rendered so Grails will assume convention and render the List view. If a controller action doesn't explicitly call for a view to be rendered then the view matching the controller action name will be rendered.

To demonstrate how a controller might request a specific view be rendered, add a new controller action to the PersonController. The List property shown above is designed to show all Person objects. Define a new controller action that is designed to show all young people. Consider that a young person is anyone under the age of 16. Add a controller action to the PersonController class that looks like this:

  1. def listYoungPeople = {
  2. render(view:'list', model:[personList: Person.findAllByAgeLessThan( 16 ) ])
  3. }

The listYoungPeople controller action is invoking the "render" method to render a specific view. A Map is being passed to the render method that includes the view to be rendered and the data being passed to that view. In this case the view to render is the List view. The data being passed to the view is similar to the data rendered from the List action but instead of invoking Person.list() this controller is invoking another dynamic method called Person.findAllByAgeLessThan( 16 ). Here you should get a sense for the power and flexibility of the GORM dynamic methods that are added to Grails domain classes. That method name is very easy to read and clearly expresses the intent of the method.

Create several Person objects in your system, some with ages greater than or equal to 16 and several younger than 16. With that data in place take a look at the differences you see when you visit http://localhost:8080/testapp/person/listYoungPeople vs. http://localhost:8080/testapp/person/list.

Grails Views

The PersonController class now has 2 separate controller actions that each render the list view. The code associated with this view may be found in grails-app/views/person/list.gsp. JSP developers will find the syntax in a Groovy Server Page (GSP) to be familiar. The main difference between JSPs and GSPs is that GSPs may contain embedded Groovy code where JSPs may contain embedded Java code.

Grails bundles a rich set of tag libraries that simplify the code in GSPs. The process of creating your own custom tag libraries for Grails could not be more simple. Like most Grails application artifacts, Grails tag libraries are plain Groovy classes. To create a new tag library simply create a Groovy class in grails-app/taglib/ with any name that ends in TagLib. The file may be created by hand or may be created with the create-tag-lib command.

$ grails create-tag-lib TestApp
 
Welcome to Grails 0.4.2 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Users/jeffbrown/Tools/grails
 
Base Directory: /Users/jeffbrown/article/testapp
Environment set to production
Running script /Users/jeffbrown/Tools/grails/scripts/CreateTagLib.groovy
     [copy] Copying 1 file to /Users/jeffbrown/article/testapp/grails-app/taglib
Created TagLib at /Users/jeffbrown/article/testapp/grails-app/taglib/TestAppTagLib.groovy
     [copy] Copying 1 file to /Users/jeffbrown/article/testapp/grails-tests
Created TagLibTests at /Users/jeffbrown/article/testapp/grails-tests/TestAppTagLibTests.groovy

The newly created grails-app/taglib/TestAppTagLib.groovy file may be edited to contain any number of custom tags. To create a new tag add a new closure property to the TestAppTagLib class that accepts a single argument. The argument will contain any attributes passed to the tag. Here is an example tag:

  1. class TestAppTagLib {
  2.  
  3. def myTestTag = { attrs ->
  4. out << "This Is My First Custom Tag"
  5. }
  6.  
  7. }

That new custom tag may be invoked from any GSP in the application. Modify grails-app/views/person/list.gsp to execute this tag. Immediately after the openingtag add the following:

  <g:myTestTag></g:myTestTag>

The next time you point your browser at http://localhost:8080/testapp/person/list you should see the output of the myTestTag rendered in the browser.

Grails myTestTag

The tag shown above does not do anything special with any parameters passed to the tag. Change the myTestTag closure property to look like this:

  1. def myTestTag = { attrs ->
  2. def numberOfOccurrences = Integer.valueOf(attrs[ 'occurrences' ])
  3. numberOfOccurrences.times {
  4. out << "This Is My First Custom Tag"
  5. }
  6. }

This version of the tag expects an attribute named "occurrences" that represents the number of times that the message should be output. Change the list GSP to invoke that tag like this:

       <g:myTestTag occurrences="3"></g:myTestTag>

Point your browser at http://localhost:8080/testapp/person/list and notice that the message now appears 3 times.

This trivial example only begins to demonstrate the power and flexibility provided by Grails' custom tag lib support.

Grails Domain Classes

In many ways a Grails application revolves around the domain classes (also known as model classes). Example domain classes are Car, Person, Appointment, Note, Ticket, etc. These are the things that are typically stored in the database. In the examples above the Person class is a domain class.

The Person class shown above is a simple class that declares 3 properties. The properties are FirstName, LastName and Age. A Grails domain class may also declare validation constraints to help impose business rules. Validation constraints may be added to a domain class in the form of a static closure property named Constraints. For example if you have business rules that say a Person's age must be greater than 21 and the FirstName and LastName properties must contain at least 2 characters and no more than 35 characters, Grails provides a simple way to express that.

  1. class Person {
  2. String firstName
  3. String lastName
  4. Integer age
  5.  
  6. static constraints = {
  7. age(min:21)
  8. lastName(length:2..35)
  9. firstName(length:2..35)
  10. }
  11. }

Now if an attempt is made to save a Person with data that violates any of those rules, the save will fail. The default scaffolding views provide feedback to inform the user that validation has failed. Your application may do with this information whatever is most appropriate.

Grails Failed Validation Feedback

What Next?

The trivial application described above only begins to demonstrate the powerful capabilities of Grails. A great next step is to build a simple application of your own and start extending the application to explore the framework. Aside from spending time side-by-side with a seasoned expert, there may not be a better way to develop expertise than to jump in and start using the tool. See the References section at the end of this article for links to several sources that should provide a lot of help.

The Grails Community

Grails has a very active user community. The mailing lists referenced at the end of this article are a great resource to tap in to. The development team is working hard to implement new features every week. The user community have contributed a whole lot to Grails in the form of patches, plugins and ideas. An active user community is a key component for an open source project to thrive and Grails has a very active user community.

The Future For Grails

The Grails development team has laid out a roadmap leading up to the release of Grails 1.0 later this year. Defining the criteria for a 1.0 release is not an especially simple task. What makes a 1.0 release? While Grails is currently at 0.4.2 there are already Grails applications in production using releases earlier than the current release including several public facing sites.

Summary

This article has provided a broad stroke overview of some of the core capabilities provided by Grails. There is much more detail to be covered. Grails is a remarkably flexible framework while maintaining an ease of use that is unparalleled by other web application frameworks targeted for the JVM. Use the exercises in this article as a jump start with Grails and have fun exploring the possibilities.

References

 

The Software Engineering Tech Trends is a monthly publication featuring emerging trends in software engineering.

Subscribe

© Copyright Object Computing, Inc. 1993, 2018. All rights reserved

secret