Grails CRUD
Date: 12/28/07

grails-employee source code

Introduction
This is part 1 in what will hopefully be a series of examples using Grails. Like most of the other lessons on this site, the purpose of these examples are to demonstrate the steps in building working applications. Although I'll often make some brief comments, the lessons aren't meant to provide detailed explanations of the parts that make up Grails. For thorough coverage pick up a book and check out the online documentation. The only book I've read so far is The Definitive Guide to Grails by Graeme Rocher (I found it quite excellent.)

For those familiar with the other tutorials on this site, I'm keeping with the "Employee Maintenance" theme that the others follow.
Before you get started
If this is your very first grails application, you'll need to download grails and set up your GRAILS_HOME environment variable. These initial steps are described well here. (After following the steps described in the previous link, open up a terminal and type grails to make sure you have everything set up correctly. You should see "Welcome to Grails" as part of the first line.)

You could also follow along looking at the source code provided but I suggest not downloading the source and actually follow the steps below instead so that you get a better feel for the ease of development with Grails.
Creating our project skeleton
Using a terminal (command line), navigate to the directory where you work on your projects. Once in this directory type: grails create-app grails-employee. You'll notice a lot of directories and files set up for you in a new directory called "grails-employee." Already this is sort of nice, since there is no need to worry about how to set up your project or worrying about creating your own Ant build file. Grails also comes with a built-in HSQL database and comes using Jetty as an application server. Of course, we could configure our application to use another database and it's one command to create a war file that we can deploy to a different application server. For this demo, however, we'll just use the default setup.
Create our domain objects
We'll assume we don't have an existing database already set up and populated. Grails uses Hibernate by default and as we build domain objects and save and edit them we'll actually be persisting them to the underlying database without touching any SQL. For this simple application we're going to work with two domain objects, an "Employee" and a "Department." We'll start by building a Department domain object.

If you open up your 'grails-employee' project you just created in the last step, you'll find a directory: 'grails-app/domain.' We can simply start by either creating a domain class here by using our IDE or editor and naming it "Department.groovy" or we could go to the terminal and within our grails-employee directory type: grails create-domain-class Department. After entering this command, a "Department.groovy" class will be created automatically in the grails-employee/grails-app/domain directory. Navigate to this class, or edit the one that you created with your editor, and have the class look like:
class Department { 
    String name;
    
    String toString() { 
        return name;
    }
}
Next, let's create our Employee domain object (Employee.groovy) in the same grails-app/domain directory (using the same procedure as you did for the Department domain object.) This domain object will contain a reference to a Department object. Create your Employee.groovy class as such:
class Employee { 
    Department department;
    String firstName;
    String lastName;
    int age;
    
    static constraints = {
        firstName(blank:false, nullable:false, size:1..150) 
        lastName(blank:false, nullable:false, size:1..150)  
        age(min:18,max:120)
    }
   
    String toString() {
        return "$firstName $lastName (id: $id)"
    }
}
Populate our database
Since we're running in dev mode, we'll just use the grails-app/conf/BootStrap.groovy class to populate our database. (If you take a look at the grails-app/conf/DataSource.groovy file, you'll notice that in development mode the dbcreate mode is set as dbCreate = "create-drop" which means that the tables will be dropped and recreated on startup.) In the BootStrap init method we'll just create some instances of the domain objects we just created and call "save()" on them which will persist them to the database. The following initialization code will create three Departments then create fifty Employees populated with some random information.
Open up the BootStrap.groovy class and modify to look like:
class BootStrap {

     def init = { servletContext ->
        
         Department a = new Department( name: "HR").save();
         Department b = new Department( name: "Accounting").save();
         Department c = new Department( name: "Sales").save();
         def departments = [a, b, c]
         def firstNames = ["Greg","Fred","Doug","Craig","Dustin","Steve","Kristy","Rick","Wilma"]
         def lastNames = ["Smith","Flinstone","Abbot","Williams","Adams","Goober","Brady","Jones","Heffernen"]
         Random random = new Random()
         1.upto(50) { i ->  
            def first = firstNames[ random.nextInt(9)]
            def last = lastNames[ random.nextInt(9)] + i
            def dep = departments[ random.nextInt(3)]
            def age = random.nextInt(40)+18
            new Employee( firstName: first, lastName: last, age: age, department: dep).save();
         }
         assert( Employee.list().size() == 50 ) 
     }
     def destroy = {
     }
} 
Create Employee controller
From the terminal (still in our grails-employee directory) type: grails create-controller Employee. Grails will create the controller called "EmployeeController.groovy" and it will be placed in the grails-app/controllers directory. Open up that file and you'll see it looks like:
class EmployeeController {
    def index = { }
}
'index' will be the default action executed in this controller which, of course in this case, doesn't do anything. We'll be modifying this controller shortly.
Dynamic Scaffolding
If you want a quick and usable application to now handle all your CRUD operations for an Employee we can do it simply now by using just one line of code! They key is in dynamic scaffolding. I'll quote Graeme Rocher's explanation on scaffolding:
Scaffolding is the name coined by the Rails framework for the generation of the artifacts that make up a usable interface to perform CRUD operations. This term has been fruther extended and generalized to basically mean the generation of an interface to fufill a use case based on the convention within a project (Graeme Rocher 'The Definitive Guide to Grails' p.89)
Let's demonstrate an example of dynamic scaffolding by modifying the "EmployeeController.groovy" file you just created in the previous step. Open up that file and change it to look like:
class EmployeeController {
    def scaffold = Employee
}
Now lets run the application. From the terminal (still in the grails-test directory we created) type:
grails run-app
Open up your browser, and you should be able to navigate to http://localhost:8080/grails-employee.

The screen should look like:


You could then click on the "EmployeeController" link and view the employees...



You can sort the columns by clicking on the column headers and you can show the employee detail and edit the employee after clicking on the employeeId in the left-hand column.

Quite impressive - From one line of code in our EmployeeController we end up with a fully functional CRUD application! (You might notice that if you go to edit an employee and try to edit the department, you'll get a 'page not found' error. This is because we didn't create a controller with a scaffold definition for the Department domain object. You certainly can create that controller if you wish (just like we did for an Employee), which would then allow you to modify the Deaprtments as well.)

This scaffolding is pretty cool, but often times you'll want to modify the views (the GSP pages) and you'll often need to provide some added functionality to the controllers. We'll get to this in the next two sections.
Customizing our controller
In our EmployeeController we have one line: def scaffold = Employee. By convention our views that are created dynmaically will call action methods called "list, show, delete, edit, save, update, create." We can provide our own implementation for any of these we want in the controller we just created, for example:
class EmployeeController {
    def scaffold = Employee
    
    def save = { 
        //handle save how we want
    }
}
Grails comes with another feature which will generate all the default CRUD methods for you in the controller. Surprisingly this grails task is: grails generate-controller. Type grails generate-controller Employee from the terminal. Since we already created an Employee controller, it will ask if you have want to overwrite it - type "y" and enter.

Open up the generated EmployeeController class ( in grails-app/controllers ) and you will now see all the CRUD methods, redirects, flash messages, etc. We can now tweak this class anyway we see fit. Maybe we want to change the message displayed after a successful update. Let's go ahead and modify some of the flash messages.

If you look at our Employe domain object, it contained a toString() method that looked like:
String toString() {
    return "$firstName $lastName (id: $id)"
}
Let's use the toString of this Employee object instead of simply displaying the employee id parameter that the default update and save methods use in the default Employee controller we just created.

You'll see the default update and save methods have the following flash messages:
flash.message = "Employee ${params.id} updated" and
flash.message = "Employee ${employee.id} created"

Let's change them to use the Employee toString in the flash messages. Here is the updated "save" and "update" methods:
def save = {
    def employee = new Employee(params)
    if(!employee.hasErrors() && employee.save()) {
        flash.message = "Employee ${employee} created"
        redirect(action:show,id:employee.id)
    }
    else {
        render(view:'create',model:[employee:employee])
    }
}
def update = {
    def employee = Employee.get( params.id )
    if(employee) {
        employee.properties = params
        if(!employee.hasErrors() && employee.save()) {
            flash.message = "Employee ${employee} updated"     
            redirect(action:show,id:employee.id)
        }
        //...
}
Modifying the views
The dynamically generated views that our scaffolding created are ok, but what if you want to modify them? You could of course create your gsp pages from scratch, which is fine, but there is an easier way by having grails generate the crud gsp pages for you.

To create our Employee gsp files, you can simply type: grails generate-views Employee. You'll then see four gsp files (create, edit, list, and show) in your grails-app/views/employee directory.

Looking at the create.gsp and edit.gsp file that were created, you will notice that they files are almost identical. Since we're smart developers we realize we should reuse where we can, so let's extract the employee form section out into a Grails' equivalent of a JSP include file - called a "template."

Templates are created with an underscore in front of their name and they are rendered using the g:render tag. We're going to make an _editor.gsp template and place it in the same directory where our other employee view files are located ( /grails-app/views/employee). (This '_editor' name is the same name Graeme Rocher used in his bookmark application, described in more detail in The Definitive Guide to Grails. It makes sense to call it 'editor' since it contains the form that lets you edit the details of the domain object.) Our _editor.jsp should look like:
<table>
<tbody> 
    <tr class='prop'>
        <td valign='top' class='name'>
            <label for='firstName'>First Name:</label>
        </td>
        <td valign='top' class='value ${hasErrors(bean:employee,field:'firstName','errors')}'>
            <input type="text" id='firstName' name='firstName' value="${fieldValue(bean:employee,field:'firstName')}" />
        </td>
    </tr>  
    <tr class='prop'>
        <td valign='top' class='name'>
            <label for='lastName'>Last Name:</label>
        </td>
        <td valign='top' class='value ${hasErrors(bean:employee,field:'lastName','errors')}'>
            <input type="text" id='lastName' name='lastName' value="${fieldValue(bean:employee,field:'lastName')}"/>
        </td>
    </tr> 
    <tr class='prop'>
        <td valign='top' class='name'>
        <td valign='top' class='value ${hasErrors(bean:employee,field:'age','errors')}'>
            <input type='text' id='age' name='age' value="${fieldValue(bean:employee,field:'age')}" />
        </td>
    </tr>  
    <tr class='prop'>
        <td valign='top' class='name'>
            <label for='department'>Department:</label>
        </td>
        <td valign='top' class='value ${hasErrors(bean:employee,field:'department','errors')}'>
            <g:select optionKey="id" from="${Department.list()}" name='department.id' value="${employee?.department?.id}" ></g:select>
        </td>
    </tr>  
</tbody>
</table>
Now we can simplify the create.gsp and edit.gsp files. In the create.jsp, around line 23, you'll see:
<g:form action="save" method="post" >
    <div class="dialog">
        <table>
Simply remove the whole form section you see there, starting with the "table" after the section div class="dialog" section, and have it use our template:
<g:form action="save" method="post" >
    <div class="dialog">
        <g:render template="editor" model="[employee:employee]" />
    </div>
Do the same thing in the edit.gsp file. Now both the create.gsp and edit.gsp will use the editor template for rendering the form content.

You also might want to make a template for displaying an employee that you can use in other pages besides just the show.gsp page. (You could of course even combine the create.gsp and edit.gsp into one file and use a bit of logic to determine what title to display. You could even share the same controller "save" action for creating and updating with a bit of logic also, such as looking for an empty employee.id to signal an insert.)

Lastly, lets just change the index.gsp file in the grails-employee/web-app directory so that it does a simple redirect to our controller list method:
<% response.sendRedirect("employee/list"); %>
Refresh your browser at http://localhost:8080/grails-employee/ and you should see the changes. (No need to have to re-run 'grails run-app', grails will pick up our changes automatically.)
Conclusion
Obviously I've only touched the surface with Grails, but this simple lesson should show you how quickly you can be up and running with a decent, functional web-based CRUD application.
Code and Lesson - Rick Reumann