Chapter 11. GORM and Grails

GORM is the end result of the synergistic combination of Spring, Hibernate, and Groovy. Built as one of the core components of Grailsā€”a rapid development web framework influenced by Ruby on Railsā€”GORM is a different kind of ORM layer that leverages the dynamic capabilities of the Groovy language to simplify querying and persisting an application's domain model.

At the foundation of GORM lies the same strategy responsible for Ruby on Rails' success: convention over configuration. GORM drastically simplifies the amount of coding and effort required to define your application's persistence logic. With GORM and Grails, there is no need to define a DAO layer. Instead, the Active Record design pattern is employed, consolidating persistence functionality into the domain class itself without requiring up-front development to add these features. This may seem a bit like magic, but this chapter will help you understand how GORM works under the hood, by tapping into the dynamic features of Groovy.

Although GORM is the core persistence component within the Grails web framework, it can also be used outside Grails. By embedding GORM within a Spring application, you can benefit from the efficiency and terseness of Grails within a more standard architecture.

Note

Some may argue that Grails does not quite fit into a book about Spring and Hibernate. However, the Grails framework and GORM rely heavily on both Spring and Hibernate for much of the flexibility and persistence they afford. The benefits of this partnership are the longevity, enterprise strength, efficiency, and flexibility offered by Spring and Hibernate. Furthermore, SpringSource, the company behind the Spring Framework, recently acquired G2One, the company behind much of the Grails and Groovy development, demonstrating a clear alignment and dedication to Spring and Grails.

A Crash Course in Groovy

Grails and GORM came onto the scene as a result of the attention brought about by the success of the Ruby on Rails framework. Ruby on Rails took the mantras of "convention over configuration" and "don't repeat yourself (DRY)" to a new level, significantly simplifying the effort required to create a new web application. Some of Ruby on Rails' success stems from the fact that Ruby is a dynamic language, which brings a level of flexibility that is not easily attainable in the Java world. For instance, the capability to dynamically generate new behavior at runtime, in order to provide customized persistence and querying functionality tailored to the specific properties of the domain model, can't be easily replicated in Java because the language doesn't natively support the dynamic creation of new methods. Luckily, Groovy came onto the scene to bring this flexibility to the Java world.

The most fundamental difference between Grails persistence and the other approaches we've discussed in this book is that Grails is the only strategy that doesn't use Java. However, Groovy code runs in the JVM and so is bytecode-compatible with Java code. This also means that Groovy can utilize Java libraries, making the myriad of open source Java libraries accessible to this new language.

Groovy is a dynamic language, which implies some significant differences from Java both syntactically and in the way Groovy can be used. Here, we'll provide a brief introduction to Groovy, to help Java developers wrap their heads around some of the core differences between the two languages.

One of the basic features of Groovy is its ability to dynamically add or modify behavior at runtime. As a brief, cursory example, let's say we want to add a new method called sayHello() to our Person instance at runtime. This could be accomplished as follows:

Person.metaClass.sayHello = {
    println("Hello")
}

Or we can make this a static method that takes a single parameter:

Person.metaClass.static.sayHello = {def name ->
    println("hello ${name}")
}

In Groovy, every class holds a reference to a corresponding metaClass instance. Method calls to a particular class or instance are delegated to that class's metaClass, which then calls a method named invokeMethod, passing along the name of the method to invoke and any corresponding parameters. So you can think of metaClass as an intermediary, or proxy of sorts, allowing more of a class's behavior to be determined at runtime.

By defining a new property on a particular class's metaClass, we are effectively implementing new behavior at runtime. Once we have defined our sayHello property to reference a closure block, future calls to Person.sayHello() will end up being delegated to the functionality specified in our closure block.

Note

For a given method, constructor, or property, the Groovy compiler actually generates a call to MetaClass.invokeMethod(), passing along the object, method name, and corresponding parameters. A Groovy object's metaClass can then decide which code to invoke at runtime.

But what is a closure? A closure is an assignable block of code, similar in function to an anonymous inner class in Java. Although closures are often used in a similar context to methods, a key difference is that closures can be assigned to variables and even passed around. We will discuss closures in a bit more detail shortly.

Letting Your Types Loose

Groovy variables and references don't need to be statically typed. For instance, you can define a variable in the following way:

def myName = "Sam"

The variable myName can contain a String or can later change to an int. def defines a variable or property without delineating a specific type. It is similar to using a type of Object in Java, but the emphasis when using def is that the type isn't important and may change from one context to another.

GStringsā€”Strings on Steroids

Groovy supports a concept called GString, which is basically a Java String on steroids. In the earlier example, notice that we were able to create a dynamic String by writing "hello ${name}". This strategy integrates a variable directly within a String without requiring concatenation. You can even invoke methods directly within a ${} block.

Default Constructors in Groovy

Another key concept is that Groovy classes can take named parameters with just a default constructor. For instance, you can instantiate a Groovy class using the following approach:

Class GroovyBean {
    String name
    String favoriteColor
}
def myBean = new GroovyBean([name: 'Joe', color: 'blue']);

There are a few important details in the preceding example. First, notice that we defined a Groovy bean without actually defining corresponding getters and setters (and without using any semicolons!). Groovy defines these for us behind the scenes at runtime. We could reference the name property of the myBean instance with myBean.getName(), but myBean.name is more concise.

Also notice the shortcut we used for passing in a java.util.Map of bean properties. Maps can be defined using the following syntax: [key: value]. A common idiom is to define an empty map as [:]. Similarly, a java.util.List can be defined using the [] notation.

Closures in Groovy

One of Groovy's most significant features is its excellent support for closures. Closures are like methods but can also be referenced by variables or passed as parameters into methods. For instance, you can create a closure and store it in a variable called myClosure using the following code:

def myClosure = {def param ->
  println("The param is ${param}")
}

Notice that closure parameters appear after the first curly brace and are then followed by ->. Closures can be used to dramatically simplify code. For example, you can iterate through a list in Groovy this way:

List myList = ["a","b","c"]
myList.each {curItem ->
    println(curItem);
}

This closure will be passed to the each method for every element in the list. Contrast this approach with using a Java Iterator:

List myList<String> = new java.util.ArrayList();
myList.add("a"); myList.add("b"); myList.add("c");
Iterator<String> myIterator = myList.iterator();
while (myIterator.hasNext()) {
    String curItem = myIterator.next();
    System.out.print(curItem);
}

This is impressive, but it gets better. Imagine we wanted to iterate through a list of Strings, returning only those items that contain the sequence cat. In Groovy, this can be accomplished quite simply:

def stringList = ["I like dogs",
         "I like cats", "I like to scat sing",
         "What is a category", "I have gas"]
def matchingStrings = stringList.findAll {curString ->
    curString.contains("cat")
}

Invoking a closure works in a similar way to invoking a method. You simply reference the closure property, followed by (). You can also call a closure explicitly by referencing the closure and invoking call().

Now that we've covered a few basic Groovy concepts, let's move on to building our Grails persistence tier.

Note

There is a lot more to learn about Groovy. We recommend you check out Beginning Groovy and Grails by Christopher M. Judd, Joseph Faisal Nusairat, and Jim Shingler (Apress, 2008).

Getting Grails Running

The Grails persistence solution is so dramatically different from the other DAO-based persistence solutions that we've explored so far in this book that we can't effectively build on our existing application code base, which we have been able to do up until now. Instead, we need to start over and architect our gallery application using the Grails approach. This may seem like a daunting task at first, but Grails comes with many shortcut templates and scripts designed to start stubbing out code for you. This stub code is known as scaffolding, in Grails speak.

Installing Grails

The first step is to install Grails. Head over to http://www.grails.org, and download the latest release. Unzip the downloaded archive and copy everything to a logical location on your hard drive. Next, make sure that everything under the bin directory is executable. If you're using a Unix-based operating system, you can run chmod ug+x ./* from within the bin directory.

Finally, make sure the GRAILS_HOME environment variable is set up. GRAILS_HOME should point to the location where you installed Grails. Also, make sure that you've added the GRAILS_HOME/bin directory to your PATH, so that you don't need to specify the full path to the Grails executables each time you want to invoke a Grails script.

If you are using a Unix-based operating system, we recommend updating your Ėœ/.bashrc script within your home directory so that you don't need to do this configuration more than once. On a Mac, you can append the following lines to your Ėœ/.bashrc:

export GRAILS_HOME=/opt/local/share/java/grails/
export PATH=$PATH:$GRAILS_HOME/bin

After you have Grails installed, the next step is to create our gallery application.

Creating a Grails Application

Grails ships with scripts that take care of generating boilerplate code to get your application started. The first of these scripts that we will introduce is create-app:

grails create-app grailsGallery

Here, we pass grailsGallery as the only argument. Grails will churn for a few seconds, and voilĆ ! You now have a new Grails application set up and ready to go.

Part of the convention-over-configuration concept is organizing and naming key parts of your application in a standardized way. The create-app script makes this easy by setting up the Grails directory structure for you. After the create-app script completes, you will end up with the following directory structure:

gallery ->
    grails-app
        conf
            spring
                resources.groovy
            Bootstrap.groovy
Datasource.groovy
            Urlmappings.groovy
        controllers
        domain
        i18n
        services
        taglib
        utils
        views

    scripts
    src
        java
        groovy
    test
        integration
        unit
    web-app
        css
        js
        images
        WEB-INF
        index.gsp

Most of our coding effort will be focused on the grails-app directory, which is where the majority of our Groovy code will live. Before we start getting our hands dirty, let's take a brief tour of the Grails application layout.

Not surprisingly, the grails-app/conf directory holds the application's configuration. Grails was designed to be very modular in nature, so it isn't always necessary to explicitly configure each one of your dependencies. However, since Grails is really a Spring application at its core, the grails-app/conf/spring/resources.groovy file can be used to configure your dependencies. Although this is a Spring configuration file, you'll notice that it isn't in XML format. Grails provides a custom domain-specific language (DSL) to configure your Spring beans, and since this file is essentially executable Groovy code, it can be a lot more flexible than a standard XML-based configuration.

Note

The Groovy default application configuration approach uses a resources.groovy file. You can instead create a resources.xml file, which allows the use of the more standard XML-based Spring configuration.

Using the Spring DSL is fairly straightforward. As an example, suppose we want to create an e-mail service, so that we can notify end users via e-mail when new images are added to the gallery. We want to configure the Spring e-mail component within our resources.groovy file so that user can send e-mail from within our application. Here is how this configuration might look:

beans = {
    javaMailSender(org.springframework.mail.javamail.JavaMailSenderImpl) {
       host = 'smtp.prospringhibernate.com'
    }
}

The pattern is fairly intuitive. The bean name is defined first, followed by the class name within parentheses. Properties within the bean are then configured within a closure block, which is the part of the code within curly braces ({}).

If we want to inject our javaMailSender bean into a Grails service or controller, we can simply rely on default autowiring by name, by declaring a property named javaMailSender within the appropriate Grails service or controller class:

class EmailService {
    def javaMailSender
}

Similarly, if we want to reference our Grails EmailService within another bean configured within our resources.groovy file, we use its implicit bean nameā€”in this case, emailService. For instance, we might define a NotificationComponent bean within our resources.groovy file as follows:

beans = {
    notificationComponent(com.prospringhibernate.NotificationComponent) {bean ->
        emailService = ref("emailService")
        bean.factoryMethod = "getInstance"
        bean.singleton = "false"
        defaultNotificationMethods = ["email", "sms"]
    }
}

Notice that we've declared a bean parameter at the top of the block using bean ->. By declaring a bean parameter, we are able to specify more explicit details related to the type of bean we are configuring. In this case, we specified a factoryMethod of getInstance, which ensures that new instances of this bean will be instantiated by calling getInstance(). We have also specified that this is not a singleton bean.

Also notice that we have injected a reference to our EmailService by using the convention ref(" BEANNAME"), where BEANNAME is the name of our EmailService bean. We are able to apply most of our Spring configuration knowledge to this Groovy-based DSL. However, notice the flexibility advantage over XML in the following example:

beans = {
  javaMailSender(org.springframework.mail.javamail.JavaMailSenderImpl) {
    if (Environment.getCurrent() == "production") {
      host = "smtp.prospringhibernate.com"
    } else {
      host = "smtp.dev.prospringhibernate.com"
    }
  }
}

Clearly, interpretable code has its benefits over static XML.

This overview only touches on some of the configuration options for Grails. It is also possible to configure dynamic bean names, as well as specify property placeholders and override configuration.

Note

The grails-app/conf/Bootstrap.groovy file provides simple hooks (init() and destroy()) for handling application startup and shutdown events. During development, Bootstrap.groovy is an effective means for seeding your application's database with default data.

Configuring Your Application

The grails-app/conf/Config.groovy file is a centralized location for specifying key configuration details about your Grails application. This file contains information about the character encoding your application should use, as well as logging details (using log4j).

Grails leverages the innate concept of environments to facilitate the creation and separation of different development and deployment scenarios. For instance, you will likely need to use a different database (requiring variant configuration details) for development or testing than you would for your production deployment. These concepts are built into the Grails core, making it easy to test with a development database and then deploy your application to production for use with the live database, without needing to remember to swap out the configuration. Environment-specific details are present in several key configuration files.

The Config.groovy file contains an initial block of code to specify the default server URL for production:

environments {
  production {
    grails.serverURL = "http://www.changeme.com"
  }
}

If you want to specify a different URL for development, you can modify the configuration snippet accordingly:

environments {
  production {
    grails.serverURL = "http://www.prospringhibernate.com""
  }
  development {
    grails.serverURL = "http://www.prospringhibernate.com"
  }
}

There are no constraints on the kinds of environments your application defines or uses. You can add as many environments as you see fit. This can come in handy for your organization's development process, build cycle, or testing strategy.

Configuring Your Datasource

Since most web applications require a database, Grails defines a file specifically for configuring datasource-related details: grails-app/conf/DataSource.groovy. This file also uses a custom Groovy-based DSL, making this configuration clear and concise. The environment concept is built into this file as well. Properties can be configured at a global level if they apply to all environments. Environment-specific configuration, however, should be nested within the appropriate environment block.

In the case of our gallery application, here's what our DataSource.groovy file might look like (keep in mind that most of this file is already created for you, so you need to configure only the details that are specific to your application):

dataSource {
    pooled = true
    driverClassName = "org.hsqldb.jdbcDriver"
    username = "sa"
    password = ""
}
hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = true
    cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
}
// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "create-drop"
              // one of 'create', 'create-drop','update'
            url = "jdbc:hsqldb:mem:devDB"
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:hsqldb:mem:testDb"
        }
    }
    production {
        dataSource {
            dbCreate = "update"
            url = "jdbc:hsqldb:file:prodDb;shutdown=true"
        }
    }
}

Notice that the dataSource property is specified at the top of the file as well as within the environments block. Global details, such as database connection pooling settings and the JDBC driver, are configured globally by placing these details within a top-level dataSource block. Environment-specific details, such as the database URL for the development, test, and production environments, are configured in the dataSource blocks within their respective environments. If you need to use a different JDBC driver for production, you could either move these details within the appropriate environment blocks or simply override the globally configured details within the appropriate environment. Again, the types of environments you can configure are not restricted: development, test, and production are just default environments created by the Grails templates.

Mapping URLs

The last file we need to cover in the grails-app/conf directory is UrlMappings.groovy. This file provides an amazingly flexible construct for associating URL patterns with a particular controller and action. For example, here's how we might relate the pretty URL /category/panoramas with the CategoryController, specifying that the panaromas category be displayed:

class UrlMappings {
  static mappings = {
      "/$controller/$action?/$id?"{
          constraints {
          }
      }
      "/category/$categoryName"(controller: CategoryController, action: "displayCategory")

      "/"(view:"/index")

      "500"(view:'/error')
  }
}

The mapping we described is actually the second block in this example. The first component of the mapping is the part in quotes. We are essentially defining a regular expression that starts with /category/. The $categoryName defines a parameter name that will be passed to your controller automatically, using the specified chunk of the URL where the parameter name resides. In our example, the part of the URL after /category/ will be extracted and then stored in the parameter named categoryName.

If you look at the first block in the example, you will notice the default URLMapping. In this scenario, we are defining $controller and $action parameters. These are special keywords; instead of denoting a particular parameter, they define the controller to which the matching request should be directed, as well as the corresponding action. In our category listing page example, we haven't defined a $controller within our mapping expression, so we instead specify this explicitly, as follows:

(controller: CategoryController,action: " displayCategory")

Now that we've looked at the Grails application directory structure, let's move on to defining our Grails domain model.

Defining the Grails Domain Model

By default, Grails generates three core layers, which resemble the tiers we've discussed earlier in this book: domain, controller, and service. To provide consistency and better enforce convention, Grails enforces a directory structure to help organize and sequester classes from each respective layer. The domain model typically serves as the foundation for a Grails application, so it is usually the first layer to be defined.

As you probably already guessed, the domain model classes all go into the grails-app/domain directory. By default, all domain classes will live in the default Grails package. However, you are free to define your own package structure, and for larger applications, this is recommended. Additionally, if you will need to access any of your Grails code from Java, you must keep your Grails classes within a package, or it will be difficult to access them outside the Grails/Groovy world. You can also have your Groovy classes implement an interface that is accessible to Java, as a means to better integrate your Grails code with Java.

Let's begin our Grails-based gallery application by defining our Person domain entity. Grails provides scripts to help create most of the core Grails archetypes, each corresponding to a particular template. You can edit these templates if you want to change the way your default views or domain and service classes are created. To do this, you will need to run grails install-templates. You will then be able to access (and modify) the templates from within the src/templates directory. For most Grails development, the default templates are just fine.

To create our Person domain class, run the following:

grails create-domain-class Person

Once this script completes, you will find a Person.groovy class within the grails-app/domain directory. Grails uses Hibernate behind the scenes to persist Person instances to, and retrieve them from, the database. Unlike Hibernate, Grails does not require any mapping files or annotations, since convention helps Grails infer most of what it needs to handle persistence for your domain model.

Now that we've created our stub for our Person domain entity, let's define the rest of the properties:

class Person {
    String firstName;
    String lastName;
    String username;
    String password;
    String email;

    Integer roleLevel;

    public static final USER_ROLE = 1;
    public static final ADMIN_ROLE = 2;
    public static final SUPERUSER_ROLE = 4;
    public static final CONTACT_USER = 16;
    public static final COMMENT_USER = 64;

    static constrants = {
        firstName(maxSize:255, unique: false, blank: false)
lastName(maxSize:255, unique: false, blank: false)
        username(maxSize:255, unique: true, blank: false)
        password(maxSize:25, unique: false, blank: false)
        email(email:true, blank: false, unique: false)
        roleLevel()
    }

    static mapping = {
        cache true
    }

}

The first thing you will probably notice in this class is just how concise this code is. Most of the properties should be self-explanatory. Since we are using Groovy, there is no need to define getters or setters (these are implicit within Groovy). Also notice that there are no properties specified for id or version; these fields are created by Grails automatically.

Adding Constraints and Validation

Let's now look at the constraints block. Constraints allow you to better define each field within your domain model, providing clues and requirements to Grails as to how your database schema should be modeled. A number of constraint options are available, but here are some of the most useful:

  • blank

  • minSize

  • maxSize

  • range

  • unique

  • size

  • range

  • inList

  • email

  • creditCard

  • matches

  • nullable

Some of these constraints can be extremely powerful. For example, the matches constraint allows you to specify a regular expression that will be used to validate the value in the specified field, ensuring it matches the specified regular expression.

The domain-specific constraints, such as email and creditCard, will help to ensure that a field conforms to a valid e-mail address or credit card number, respectively.

If you need a custom constraint, Groovy includes a construct that allows you to define your own. You specify the property, followed by a mapping of constraint types and their corresponding values.

Here is an example:

username(blank: false, maxSize: 255, unique: true)

This will ensure that the username value cannot be left blank and that the database field has a maximum size of 255 characters. Additionally, a unique constraint will also be added to the username database field.

Constraints come into play when you attempt to save a domain entity to the database. If a particular field is not validated, an error will be attached to a dynamic errors property on your domain instance.

Additionally, the constraints defined for each property, coupled with a consistent naming convention, are assembled into error message codes that are automatically used within the default Grails Groovy Server Pages (GSP) templates. For example, if you attempt to save a Person entity without specifying a username, a validation error will be raised and associated within the instance's errors property. Afterward, this error will be properly rendered within the default GSP template, using an error code that is defined in the application's messages.properties resource bundle.

When a validation error code is found, Grails will attempt to look for the appropriate code within the messages.properties file, starting with the most specific naming convention and moving toward the more generic conventions until a match is found. This ensures that if you don't bother adding a specific error code in your messages.properties file, users will still see a sensible error (something to the effect that the blank constraint for the username field has been violated). However, you can easily override this default message by specifying a blank constraint error code that's specific to the Person class.

Defining Associations and Properties

The Person domain entity is a fairly simplistic example, as it doesn't really contain any associations or customized mappings. Let's take a look at a more complex entity to see how Grails addresses a typical scenario. Update your domain model, and then we'll dive deeper. Use the grails create-domain-class script to stub out the ArtEntity, Category, and Comment classes, respectively. The Comment class would then be modified as follows:

class Comment {

  String comment;
  Date commentDate;
  Person person;

  static belongsTo = [commentedArt: ArtEntity]

  static constraints = {
    comment(maxSize: 2000, blank: false)
    commentDate(nullable: false)
  }

  static mapping = {
    cache true
  }

}

This class is similar to the Person entity we defined earlier. We've defined a few properties, as well as a constraints block. One addition is the belongsTo field, which provides clues to Grails about the relationship between two entities. In this example, we are defining a parent-child relationship between a Comment and an ArtEntity. We are also defining a property called commentedArt and declaring that this property is of type ArtEntity. We could specify additional belongsTo relationships by appending them to this map. In each case, the key represents the property name, and the value represents the type.

Note

The belongsTo property defines the owning side of an association. When a domain class specifies a belongsTo property, it is not the owner of the association. The association owner is the class referenced by the belongsTo property.

The use of belongsTo also asserts cascading rules. In the previous example, we are declaring that ArtEntity is the parent in this relationship, meaning save and delete operations (on ArtEntity) will cascade appropriately to related Comment instances. This relationship will become clearer after we examine the opposing side, which is the ArtEntity domain class.

class ArtEntity {

    String title;
    String subTitle;
    Date uploadedDate;
    Date displayDate;
    int width;
    int height;
    String media;
    String description;
    String caption;
    ArtData_Gallery galleryPicture;
    ArtData_Storage storagePicture;
    ArtData_Thumbnail thumbnailPicture;
    boolean isGeneralViewable;
    boolean isPrivilegeViewable;

    static hasMany = [categories: Categories, comments: Comment]
    static belongsTo = Category

    static constraints = {
        title(blank:false, maxSize: 255)
        subTitle(blank:true, maxSize: 255)
        uploadedDate(nullable: true)
        displayDate(nullable: false)
        width(nullable: true)
        height(nullable: true)
        media(nullable: true, maxSize: 255)
        description(nullable: false, blank: false, maxSize: 2000)
caption(nullable: true, maxSize: 2000)

    }

    static mappings = {
        cache true
    }

}

This class follows a similar pattern, but uses the hasMany property, which defines a one-to-many association to another class. It can also be used to declare a many-to-many association, as long as one side of the relationship is deemed the owner of the association (through the use of belongsTo).

The hasMany relationship works in a similar fashion to the belongsTo convention. You are defining a map in which the keys correspond to the property (that is, collection) names and the values correspond to the domain class. In our example, we are defining two associations: comments and categories. When Grails deciphers this property, it will create corresponding collections to be used to hold these associations. We can define the type of collection we would like to use by explicitly declaring the collection as a property. For instance, we define our categories association (in our ArtEntity domain class) as a java.util.Set by explicitly defining this property:

Set categories = new HashSet();

Tip

If you need to ensure that a collection is logically ordered, you can define a property of type SortedSet, and then have your collection class implement the Comparable interface, in which the ordering logic is specified. For instance, if we wanted our categories to be ordered alphabetically, we would have our Category class implement Comparable and define a compareTo(def obj1, def ob2) method in which the ordering is based on the category name.

Customizing Domain Class Hibernate Mappings

You probably noticed the static mappings property defined in each of our example domain classes. This field can be used to enhance the Hibernate mapping that Grails creates and manages behind the scenes. In our example, we just assert that the domain entity be cached, using the CacheManager specified in the Config.groovy file. However, the mapping construct is extremely flexible and can be used to modify many areas of the default Hibernate mapping for a particular domain class. For instance, if you need to override the table name or the default column name or type, the mapping DSL provides a means for this to be accomplished. It is also possible to add caching rules for collections or override the default fetching policy for a collection, specifying whether a particular collection will be lazily or eagerly fetched. You can even specify that one or more columns map to a particular Hibernate UserType.

In our earlier Hibernate example, we defined a hierarchy of ArtData classes (each extended from the ArtData base class). In Grails, implementing polymorphic domain classes is even simpler. Here is our ArtData class:

class ArtData {

  byte[] picture;

  static mapping = {
    cache true
  }

}

And here is the ArtData_Storage class (which extends ArtData):

class ArtData_Storage extends ArtData {

}

That's really all there is to it. By default, Grails uses the table-per-hierarchy strategy, meaning it persists the sum of all the properties across the entire hierarchy into a single table.

Unlike with Hibernate, there is no need to explicitly define a discriminator (to help differentiate between types), as Grails will take care of this. However, Grails is flexible enough to allow you to use a different polymorphic strategy. For example, you could use the custom mapping DSL described earlier like so:

static mapping = {
  tablePerHierarchy false
}

Now that we've defined our Grails domain model, let's move on to persisting and retrieving this data.

Using Active Record As an Alternative to DAOs

Throughout this book, you've learned how Spring simplifies the development of a persistence tier by enforcing several key design patterns, most notably the DAO, Template, and Facade patterns. Although Grails is built on the foundations of Spring and Hibernate, it provides an alternative to the DAO pattern typical of most Spring applications. Following the lead of other rapid development frameworks, such as Ruby on Rails, Grails utilizes the Active Record design pattern as the approach for handling database persistence operations.

In keeping with the Active Record pattern, a table in the database is represented directly by a domain class. For instance, in our gallery example, we have already defined a Person class that describes a corresponding Person table in our database, meaning table fields and associations are represented by properties within our Person class.

This approach doesn't seem too different from the domain models we've used throughout this book. However, the key distinction is that the domain class also serves as the wrapper around database operations. Dynamic static methods are injected into each domain class, providing a means for querying for instances of that class's type. As in Hibernate, each row in our database is represented by a corresponding instance of the appropriate domain class. However, save() and update() methods are injected into each domain class instance, allowing newly created or retrieved instances to be persisted by invoking save() or update() directly on that instance.

For example, if we want to create or update a particular row in the Person table, we just call person.save() directly on the person instance we wish to save. If we want to load a particular Person record from the database, we simply call the static method Person.get(id), passing in the primary key for the record we wish to retrieve.

Contrast this approach with the DAO pattern, in which we need to create a separate abstraction layer for all database operations related to a particular domain entity. The Active Record pattern dramatically simplifies our effort for retrieving and persisting data, since there is no need to define any DAO classes or methods. Instead, this functionality is implicit within our domain model through dynamic behavior that is injected into each domain class.

If we don't need to define a DAO implementation, where do the implementations for methods like Person.get(id) and Person.save() come from? The Active Record pattern states that we should simply be able to define a domain model and begin calling methods on these classes to achieve the persistence logic we are trying to build. The question remains, however: if we can simply call save() on our Person instance, where do we define the behavior for this method? Let's take a look under the hood of GORM to get a better sense of how this works.

Looking Under the Hood of GORM

One of the key advantages to languages like Groovy is that they are dynamic, which means, among other things, that you are able to define new behavior for your classes at any time. In the case of Grails and the Active Record pattern, the framework is able to enhance your domain model with new functionality related to persistence. This strategy is a key Groovy concept and is enabled through the use of Groovy's metaClass construct, as discussed earlier in this chapter.

Working with Dynamic Finder Methods

Grails injects new functionality into every domain model class to facilitate the Active Record pattern. Unlike with the DAO approach, no methods need to be defined up front. Instead, Grails uses naming conventions to interpret how to interact with the database. Using the name of the method invoked, Grails intuits what type of operation to perform. This is best explained through a few examples.

Getting back to our gallery application, let's define a simple unit test that illustrates saving and loading our Person domain class. Since we want to demonstrate how Grails behaves within a running application, we need to create an integration test, which actually bootstraps a Spring ApplicationContext, so we can test functionality that relies on core Grails features such as persistence. Grails ships with a script that creates the integration test scaffolding for us:

grails create-integration-test Person

After running this command, you will find an integration test stub under test/integration/grailsGallery/PersonTests.groovy. In our test, we are going to verify that we can instantiate, save, and load a Person domain entity:

class PersonTests extends GroovyTestCase {

  ...

  void testSavePerson() {
    Person person = new Person(
        [firstName: "Sam", lastName: "Smith",
         username: "ssmith", password: "1234",
         email: "[email protected]",
         roleLevel: Person.ADMIN_ROLE])

    assertTrue("Person entity is valid and can be saved",
        (person.validate() && person.save()))

    assertNotNull ("person id is null", person.id)

    def loadedPerson = Person.get(person.id)

    assertTrue(
         "Person was successfully loaded",
             loadedPerson != null &&
                 loadedPerson.username != null)
    }

}

This is a very straightforward test. Notice that we instantiate our Person entity using a java.util.Map containing default properties for our Groovy class. After our Person instance is instantiated, we verify that the instance validates and saves successfully. validate() verifies all the requirements specified within our domain model's constraints block. If our domain model does not validate successfully, Grails will set an errors property on our Person instance. The errors property contains details on each validation failure and is an implementation of the org.springframework.validation.Errors interface. This interface is quite useful for tracking and managing form submissions, and should be familiar to users of Spring MVC.

In the event of a validation error, we can iterate through each error to find out exactly what went wrong:

person.errors.allErrors.each {curError ->
    log.error("Error saving Person instance: ${curError}");
}

We can also get an error count this way:

person.errors.errorCount()

Note

A log instance variable is automatically injected in all controller and service classes, allowing you to easily emit logging messages. This is an instance of log4j's Logger class, and is configured in the Config.groovy file described earlier in this chapter.

Grails ships with a tag library that helps to render errors within a typical form submission. Additionally, the default Grails templates will create GSP views that will automatically render clear error messages in the event of any validation or save failures. Of course, default error messages can be easily overridden by updating the messages.properties file.

At this point, you should have a solid understanding of how to go about saving and loading a domain entity. Unfortunately, that won't get you very far. You'll want to be able to query the database. To demonstrate how that works, we first need to add some data to our database.

Let's return to the PersonTests.groovy file and define a setup() method that will be executed before each of our tests are run and allow us to populate the database with some sample data:

void setUp() {
  def baseNames = [
    "Sam", "Bob", "Heather",
    "Steve", "Sofia"]
  baseNames.each {curName ->
    def person = new Person(
      [firstName: curName,
       lastName: curName,
       username: curName,
       password: "1234",
       email: "${curName}@apress.com",
       roleLevel: Person.USER_ROLE])
    assertTrue (
      "Person entity is valid and can be saved",
      (person.validate() && person.save()))
    assertFalse(
      "There should be no errors on the saved entity",
      person.hasErrors())
  }
}

This method is a little archaic, as we simply iterate through a java.util.List of names and create new Person entities using these names as seed data for each field. Also notice that we've added a new assertion to verify that person.hasErrors() is false. After a save operation, calling hasErrors() is a useful idiom to ascertain that there were no errors preventing the entity from being persisted to the database. You will see this approach used frequently within the default Grails controllers.

Now that we have a way to seed our database with some sample data, let's see how Grails makes querying the database very intuitive.

void testFinders() {

  def foundPeople = Person.findAllByUsername("Sam");

  /* foundPeople should reference a List
             containing one Person entity */
  assertEquals("One person found", 1, foundPeople.size())

  /* singlePerson should refer to a single Person
     entity, and the lastName property
     should be equal to Sam*/
  def singlePerson = Person.findByUsername("Sam")
assertEquals(
    "Lastname is Sam", "Sam", singlePerson.lastName)

  def allPeopleSorted =
    Person.list(max: 3, order: "asc",
        sort: "username", offset: 0);

  assertTrue(
      "Three people returned", allPeopleSorted.size())

  assertEquals(
      "First person in list is Sam", "Sam",
          allPeopleSorted[0].username)

}

This new method helps to illustrate a lot of the flexibility for querying data using Grails' dynamic finder concept. Notice that the way each method name is formatted determines the query that eventually is generated on the database.

In our first example, we run Person.findAllByUsername("Sam"). This type of structure returns all data that matches the field username. Notice that we use camel casing. The format might be better expressed using the following structure:

DOMAIN.findAllBy<PROPERTYNAME>

If you look at the assertions, you will notice that this type of method will always return a collection of objects. Conversely, our next assertion uses the format:

DOMAIN.findBy<PROPERTYNAME>

This method works in a similar fashion but will return only a single object. This claim is validated on our assertion, as we demonstrate that the returned value is a single Person instance, instead of a collection.

Both the findAllBy and findBy dynamic methods can also be expanded, in order to specify modifiers on the property name or provide further constraints. For example, if we wanted to find all users that have first and last names that start with the letter p, this could be expressed in the following method:

Person.findAllByFirstNameIlikeAndLastNameIlike("P%", "P%");

In this example, we first specify a conditional property of firstName and then modify the condition using Ilike. The Ilike modifier is similar to the like modifier but is case-insensitive. Next, we append And to the method name to further constrain the query with an additional property condition.

A similar approach may be taken to find out the number of rows in the database that match a specified set of conditions by using the countBy* dynamic finder method. Based on this example, we can define a method-naming structure that delineates the way in which a dynamic-finder method is formatted:

countBy/findBy/findAllBy<PROPERTYNAME><MODIFIER>AND/OR<PROPERTYNAME><MODIFIER>

The following are some of the modifiers that can be used:

  • Between

  • GreaterThan

  • GreaterThanEquals

  • LessThan

  • LessThanEquals

  • Like

  • Ilike

  • Not

  • Equal

Our next example simply calls Person.list(), which returns all the instances of the Person domain class. However, we also pass in a Map of options that help to define constraints and sorting options on our returned data. These options can also be used for pagination, since you can set the maximum number of items to return (max), as well as an offset. Table 6-1 summarizes the options that can be passed to the list() method.

Table 6.1. Options for Sorting and Paginating a Result Set

Option

Purpose

sort

Field to sort on

order

Direction of sort (ascending or descending)

max

Maximum number of items to return

offset

Offset within total result set for first item returned

A Map containing the options listed in Table 6-1 will also work with the findAllBy* methods. For instance, we could request the second page (assuming each page contains ten objects) of Person instances, sorted by name in descending order:

def people = Person.list(sort: "name", order: "desc", max: 10, offset: 10);

Creating Advanced Query Methods

The dynamic finder approach described in the previous section works well for most types of queries. However, sometimes having a little more flexibility is important. Grails also provides the find() and findAll() methods, which allow you to utilize arbitrary HQL queries. Find() returns a single entity, and findAll() will return multiple entities. Alternatively, an even more flexible executeQuery() method allows you to define queries that don't return a specific domain entity.

Let's look at an example using HQL. Suppose we want to query for all ArtEntity objects that fall within a particular category. This could be represented using the following query:

List artEntities = ArtEntity.findAll(
 "from ArtEntity artEntity left join
      artEntity.categories as category with
          category.id = :categoryId",
              ["categoryId": category.id])

Notice that we use a left join on the Category domain object, specifying a with constraint for those categories matching the specified category ID.

We use named parameters in this query. As in a typical HQL query, parameter names are represented in the query by prefixing the name with a colon. The parameter name-value mappings are then passed in as a Map (as the second parameter to the findAll query).

Using the Criteria API

Just like standard Hibernate, Grails provides a means to express queries using the Criteria API. However, because we are using Groovy instead of Java, we can take advantage of a Criteria DSL, allowing us to define our query criteria in a more concise and readable way. For instance, we could query for all ArtEntity instances within one of two specified categories that also fall within a particular date range using the following query:

def criteria = ArtEntity.createCriteria()
def currentDate = new Date()
def earlierDate = currentDate - 3
def catName1 = "autumnPicts"
def catName2 = "summerPicts"
def results = criteria.list {
    between('displayDate', earlierDate, currentDate)
    categories {
        or {
            equals("name", catName1)
            equals("name", catName2)
        }
    }
}

The preceding example uses the Grails Criteria Builder, allowing us to express a fairly complex set of restrictions in a very intuitive manner. If you recall the standard Hibernate Criteria API, you should be able to infer most of what is occurring in our example. Criteria disjunctions and conjunctions can be specified using or and and blocks, respectively. Similarly, association criteria may be expressed by defining a block with the association name, which is what our categories block does in the preceding example. Within our categories block is a nested or disjunction, and within that block are our equals restrictions, allowing us to filter those categories that match either of the category names we've specified.

Handling Associations in Grails

We have described how associations can be defined by using the hasMany and belongsTo conventions. These constructs are effective for indicating how our domain entities relate to each other. Once our domain model is defined, we need to manipulate it.

Recall that in the Hibernate world, it is important to write code to ensure that bidirectional associations are properly managed. For instance, it is common practice to define add* and remove* methods within a Hibernate domain class that ensure both ends of an association are properly set or removed. Grails helps to ensure that both sides of an association are properly referenced (or dereferenced) by providing dynamic addTo* and removeFrom* methods. For instance, if we want to add new Comment instances to an ArtEntity, we could do so using the following code:

def loadedArtEntity = ArtEntity.findByName("Awesome Panorama");
def loggedInUser = Person.findByUsername("Sam");
Comment newComment = new Comment(
                         comment: "Cool pict!",
                         commentDate: new Date(),
                         person: loggedInUser);
loadedArtEntity.addToComments(newComment);
if (!loadedArtEntity.hasErrors() && loadedArtEntity.save()) {
    println("new comment saved");
} else {
    println("Error saving new comment");
}

In our example, we define a new Comment and then add it to the ArtEntity comments association using the addToComments method. We could also choose to remove a particular comment reference using the removeFromComments method. Notice that we did not invoke save() on our new Comment instance directly. Instead, we saved our ArtEntity instance, allowing the save operation to cascade to the comments association since we have specified that ArtEntity is the owner of the association. This association ownership is expressed in this line within the Comment domain class:

static belongsTo = [commentedArt: ArtEntity]

Scaffolding and Building Your Grails Application

With our domain model defined, we can rely on Grails' generation scripts to create scaffolded functionality for our gallery application. You can download the full Grails-based gallery application from this book's web site.

To generate controllers and views for a particular domain class, make sure you are at the root of our Grails gallery application and then run the following:

grails generate-all <<domain-class>>

Be sure to swap domain-class for the name of the domain entity for which you would like to generate controllers and GSPs. You can also generate just the controllers or just the GSPs by calling the following scripts, respectively:

grails generate-controller <<domain-class>
grails generate-views <<domain-class>>

We strongly recommend examining the generated controllers and views to get a better sense of how a typical Grails application works. Keep in mind that the generated code is based on scaffolding designed to work in a very generic way (so that it works for all types of domain models). Therefore, it is also useful to examine the sample Grails gallery application for a slightly different perspective.

Note

For details on Grails development, including building controllers and GSPs, see The Definitive Guide to Grails, Second Edition, by Graeme Rocher (Apress, 2009).

You can easily start up your Grails application using a particular environment, by passing the grails.env environment variable into the grails run-app script:

grails -Dgrails.env=development run-app

This command will automatically start up our application using the development environment configuration. You wouldn't normally want to run a production or staging application this way, but it is convenient for testing purposes. Internally, Grails uses an embedded Jetty server to run your application when you use the run-app command.

You can deploy Grails to any application server if you create a WAR file using the Grails war command. If you want to create an application for deploying into your own application server, you would instead run this:

grails -Dgrails.env=production war

We recommend explicitly using -Dgrails.env to specify an environment, as it supports both default and custom environments. However, if you are using the default Grails environments, you can use this shortcut:

grails prod war

Defining a Transactional Service Layer in Grails

You've learned about transactional support throughout this book. You know how important it is to ensure that operations within a particular method all complete (or roll back) as a single, atomic unit of work. Grails also encourages the use of the service facade pattern, and makes defining transactional requirements extremely easy. However, in the name of flexibility, Grails provides a couple of options for ensuring persistent operations occur within a transactional context.

If you don't want to create a service class, an alternative approach for ensuring persistence operations occur within a transactional context is to enclose a block of code inside a closure and pass this to the dynamic withTransaction method, injected to each domain class. For instance, we could ensure an update to a category and an ArtEntity occurs within a transaction by doing the following:

Comment.withTransaction {txStatus ->
    def comments = Comment.findAllByCommentDateGreaterThan(lastWeek);
    comments.each {Comment curComment ->
       if (Comment.hasSpam(curComment)) {
         curComment.delete()
       }
    }
}

Here, we are actually defining an anonymous closure block and passing this closure to the Comment domain object's dynamic withTransaction method. This is a trivial example, but it illustrates how simple defining a transaction can be using Grails.

Note

The txStatus closure parameter is an org.springframework.transaction.TransactionStatus object, which allows you to get information about the currently executing transaction and trigger a rollback programmatically by calling txStatus.setRollbackOnly().

A cleaner approach is to implement a service layer and organize your transactional operations within a service method. In Grails, you can create a new service method by running the following command:

grails create-service servicename

This will create a new service within the grails-app/services directory. Grails has a fairly simplistic way of declaring whether a particular service class should be transactional. Just add the following to the top of your service class:

static transactional = true;

If transactional is set to true, your methods will all run within a transactional context. If the static property is false, a transaction will not be used.

Summary

In this chapter, we've covered some of the fundamentals for developing a web application using Groovy and Grails. Grails provides an interesting contrast to the topics covered in the previous chapters. Although based firmly on Spring and Hibernate, Grails utilizes Active Record as an alternative to the DAO design pattern. This approach is more practical in Grails due to its use of the dynamic language Groovy, allowing new behavior and methods to be dynamically defined. Through the use of convention-over-configuration, Grails can significantly reduce the amount of effort required to get a working application up and running.

Despite some of these differences, Spring's profound influence is clearly present, and most of the lessons and patterns utilized with other persistence frameworks can still be applied to Grails. You've seen how some of the fundamental Spring concepts, such as dependency injection, can be further enhanced through Groovy-based configuration and implicit, convention-based wiring.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.237.29