© Adam L. Davis 2019
Adam L. DavisLearning Groovy 3https://doi.org/10.1007/978-1-4842-5058-7_13

13. Grails

Adam L. Davis1 
(1)
New York, NY, USA
 

Grails is a web framework for Groovy that follows the example of Ruby on Rails to be an opinionated web framework with a command-line tool that gets things done really fast. Grails uses convention over configuration to reduce configuration overhead.

Grails lives firmly in the Java ecosystem and is built on top of technologies like Spring and Hibernate. Grails also includes (optionally) an object relational mapping (ORM) framework called GORM and has a large collection of plugins.

Different versions of Grails can be very different, so you need to take care when upgrading your Grails application, especially with major versions (2.5 to 3.0, for example).

This chapter contains a quick overview of how Grails (3.3) works and then includes a short history of Grails.

Quick Overview of Grails

After installing Grails,1 you can create an app by running the following on the command-line (replace TEST with the name of the directory you want to use):
1   $ grails create-app TEST

By default this will create an application using the “web” profile (to get a list of available profiles, run grails list-profiles).

Then you can run commands like create-domain-class and generate-all to create your application as you go. Run grails help to see the full list of commands available.

Grails applications have a very specific project structure. The following is a simple breakdown of most of that structure:
  • grails-app—The Grails-specific folder.
    • assets
      • images—Images used by your web application.

      • javascripts—Your JavaScript files go here.

      • stylesheets—CSS stylesheets.

    • conf—Configuration, such as an application.yml or application.properties file.

    • controllers—Controllers of the application and the UrlMappings class. Provides code for actions like list, save, show, and create.

    • domain—Domain model; classes representing your persistent data if you use GORM.

    • i18n—Message bundles which enable you to provide text in multiple different languages.

    • init—Includes Application.groovy and BootStrap.groovy.

    • services—Backend services where your backend or “business” logic goes.

    • taglib—You can very easily define your own tags for use in your GSP files here.

    • views—Views of MVC; typically these are GSP files (HTML based).

    • utils—Can contain utility classes.

  • src—Any common code that doesn’t fit anywhere else.
    • main/java—Java code

    • main/groovy—Groovy code

    • main/resources—Any non-code resources you want in the main classpath.

    • test/groovyGroovy-based tests which can use JUnit or Spock.

    • integration-test/groovy—Includes Geb-based tests.

    • integration-test/resources—Includes GebConfig.groovy for configuring Geb.

To create a new domain (model) class, run a command like the following:
1   $ grails create-domain-class example.Post

It’s a good idea to include a package for your domain classes (here the package is “example” and the class is named Post).

A domain class in Grails also defines its mapping to the database. For example, here’s a domain class representing a blog post (assuming User and Comment were already created):
 1   class  Post  {
 2       String text
 3       int rating
 4       Date created = new  Date()
 5       User createdBy
 6
 7       static hasMany = [comments: Comment]
 8
 9       static constraints = {
10           text(size:10..5000)
11       }
12   }

The static hasMany field is a map that represents one-to-many relationships in your database. GORM uses Hibernate in the background to create tables for all of your domain classes and relationships. Every table gets an id field for the primary key by default.

To have Grails automatically create your controller and views, run the following:
1   $ grails generate-all example.Post

../images/426440_2_En_13_Chapter/426440_2_En_13_Figa_HTML.gifWarning

Grails will ask if you want to overwrite existing files if they exist. Be careful when using this command.

When you want to run your application directly to try it out, you can simply run the following:
1   $ grails run-app
If you want to deploy to an application container (e.g., Tomcat), you can create a war file by running the following:
1   $ grails war

Configuration

Since Grails 3+ is built on Spring Boot, configuration works in a similar way using the grails-app/conf/application.yml file by default.

Toward the bottom of this file, you’ll see the default configuration uses an in-memory h2 database for development and test and a file-based h2 database for production. They are configured as follows (this is where you would change the configuration to change your database):
development:
    dataSource:
            dbCreate: create-drop
            url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
test:
    dataSource:
            dbCreate: update
            url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
production:
    dataSource:
            dbCreate: none
            url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
            properties:
                jmxEnabled: true
                initialSize: 5
...(cut for brevity)

Plugins

The Grails ecosystem includes over 100 plugins. To list all of the plugins, simply execute this command:
1   $ grails list-plugins
When you’ve picked a plugin you want to use, execute the following command to see the available versions and how to include it in your build dependencies (with the plugin name):
1   $ grails plugin-info [NAME]
This will show you the appropriate code to add to your build.gradle file for adding the plugin to your project. For example, let’s look at the “geb” plugin (Geb is a web testing framework). Here is the output:
$ grails plugin-info geb
| Plugin Info: geb
| Latest Version: 2.0.0
| All Versions: 1.0.2,1.1.1,1.1.2,1.1.3,1.1.4,1.1.5,2.0.0.RC1,2.0.0
| Title: Geb Plugin
Plugin that adds Geb functional testing code generation features.
* License: APACHE
* Documentation: http://grails.org/plugin/geb
* Issue Tracker: http://github.com/grails3-plugins/geb/issues
* Source: http://github.com/grails3-plugins/geb
* Definition:
dependencies {
      compile "org.grails.plugins:geb:2.0.0"
}

GSP and Taglibs

Grails uses GSP by default for generating views in a web application. Take a look at the grails-app/views directory. You should see an index.gsp file which generates the landing page for your application. If you generated the example.Post views as described earlier you will also see some GSP files under a “post” directory. These generate the pages for showing, listing, creating, and editing Posts.

GSP is based on HTML with the addition of its own built-in tag libraries (starting with the g: prefix). You can add you own tag library by adding a class ending with TagLib to the grails-app/taglib directory . For example, add a file named SimpleTagLib.groovy to the taglib directory with the following code (which would format dates with a given format):
class SimpleTagLib {
      static namespace = "my" // changes from g: namespace to my:
      def dateFormat = { attrs, body ->
        out << new
    java.text.SimpleDateFormat(attrs.format).format(attrs.date)
      }
}
This would now allow you to use the following tag in your gsp files:
<my:dateFormat format="dd-MM-yyyy" date="${new Date()}" />

Serving JSON or XML

Groovy includes some built-in support for JSON (JavaScript Object Notation) encoding and decoding, including the JsonSlurper . Grails also includes converters for easily converting objects to XML or JSON or vice versa. For example, see the following PostController with methods for rendering Posts as JSON and XML:
 1   import grails.converters.JSON
 2   import grails.converters.XML
 3
 4   class  PostController  {
 5               def getPosts() {
 6                       render Post.list() as JSON
 7               }
 8               def getPostsXML() {
 9                       render Post.list() as XML
10               }
11   }
For web services that service multiple formats, you can use the built-in withFormat in Grails. So the above code could be reduced to the following:
1   def getPosts() {
2           withFormat {
3                   json { render list as JSON }
4                   xml { render list as XML }
5           }
6   }

Then Grails would decide which format to use based on numerous inputs, the simplest being the extension of the URL, such as .json, or the request’s Accept header .

For using web services in Grails, you could use the http-builder-helper plugin2 or you could use the built-in HTTP client from Micronaut (included in Grails 4).

UrlMappings

By default, Grails reads the UrlMappings class to determine how to route incoming requests to your web application. It consists of a static value named “mappings” that uses a DSL to describe the routing of the application. The default UrlMappings for a new project looks like the following:
class UrlMappings {
    static mappings = {
        "/$controller/$action?/$id?(.$format)?"{
            constraints {
                // apply constraints here
            }
        }
        "/"(view:"/index")
        "500"(view:'/error')
        "404"(view:'/notFound')
    }
}

The variables controller, action, id, and format within the first GString take on a special meaning in this context. Using them in this way will match any value given and set the corresponding variable to it. For example, the path /post/show/123 would initiate the “show” action on the PostController with a parameter ID of 123. You can modify the mappings to create custom paths. For example, you could create a custom route to create a new post like this: "/new/post/" (controller: "post", action: "create").

The first path matched is what route Grails will use.

Short History of Grails

What follows is a brief history of the features added to Grails starting with version 2.0.

Grails 2.0

There were the following improvements in Grails 2.0:
  • Better error page that shows code what caused the problem.

  • H2 database console in development mode (at the URI /dbconsole).

  • Grails 2.0 supports Groovy 1.8.

  • Runtime reloading for typed services, domain classes, src/groovy, and src/java.

  • Run any command with -reloading to dynamically reload it.

  • Binary plugins (jars).

  • Better scaffolding that’s HTML 5 compliant (mobile/tablet ready).

  • PageRenderer and LinkGenerator API for services.

  • Servlet 3.0 async API supported; events plugin; platform core.

  • Resources plugin integrated into core.

  • Plugins for GZIP, cache, bundling (install-plugin cached-resources, zipped-resources).

  • New tags: img, external, and javascript.

  • The jQuery plugin is now the default JavaScript library installed in a Grails application.

  • A new date method has been added to the params object to allow easy, null-safe parsing of dates: def val = params.date('myDate', 'dd-MM-yyyy').

Various GORM improvements include:
  • Support for DetachedCriteria and new findOrCreate and findOrSave methods .

  • GORM supports MongoDB,3 riak,4 Cassandra,5 neo4j,6 redis,7 and Amazon SimpleDB.8

  • New compile-time checked query DSL (“where” method which takes a Closure parameter) which includes: avg, sum, subqueries, .size(), and so on.

  • Multiple scoped data sources.

  • Added database migration plugin for updating production databases.

Grails 2.1

  • Grails’ Maven support has been improved in a number of significant ways. For example, it is now possible to specify plugins within your pom.xml file.

  • The grails command now supports a -debug option which will start the remote debug agent.

  • Installs the cache plugin by default.

  • In Grails 2.1.1, domain classes now have static methods named first and last that retrieve the first and last instances from the datastore.

Grails 2.2

  • Grails 2.2 supports Groovy 2.

  • Adds new functionality to criteria queries to provide access to Hibernate’s SQL projection API.

  • Supports forked JVM execution of the Tomcat container in development mode.

  • Includes improved support for managing naming conflicts between artifacts provided by an application and its plugins.

Grails 2.3

  • Improved dependency management using the same library used by Maven (Aether) by default.

  • Includes a new data binding mechanism that’s more flexible and easier to maintain than the data binder used in previous versions.

  • All major commands can now be forked into a separate JVM, thus isolating the build path from the runtime and test paths.

  • Grails’ REST support has been significantly improved.

  • Grails’ scaffolding feature has been split into a separate plugin (includes support for generating REST controllers, async controllers, and Spock unit tests).

  • Includes new asynchronous programming APIs that allow for asynchronous processing of requests and integrates seamlessly with GORM.

  • Controllers may now be defined in a namespace that allows for multiple controllers to be defined with the same name in different packages.

Grails 2.4

  • Grails 2.4 comes with Groovy 2.3.

  • Uses Hibernate 4.3.5 by default. (Hibernate 3 is still available as an optional install.)

  • The Asset-Pipeline replaces Resources to serve static assets.

  • Now has great support for static type checking and static compilation. The GrailsCompileStatic annotation (from the grails.compiler package) behaves much like the groovy.transform.Compi annotation and provides special handling for Grails.

Grails 2.5

  • Upgraded to Groovy 2.4

  • Spring upgrading to 4.1

  • Other various upgrades

Grails 3.1.x

Grails 3 represents a huge refactoring of Grails. The public API is now located in the grails package and everything has been redone to use Traits. Each new project also features an Application class with a traditional static void main.

Grails 3 comes with Groovy 2.4, Spring 4.1, and Spring Boot 1.2, and the build system uses Gradle (instead of the previously used Gant system).

Among other changes, the use of filters has been deprecated and should be replaced with interceptors. To create a new interceptor, use the following command:
1   grails create-interceptor MyInterceptor
An interceptor contains the following methods:
1   boolean before() { true }
2   boolean after() { true }
3   void afterView() {}
  • The before method is executed before a matched action. The return value determines whether the action should execute, allowing you to cancel the action.

  • The after method is executed after the action executes but prior to view rendering. Its return value determines whether the view rendering should execute.

  • The afterView method is executed after view rendering completes.

Grails 3 supports built-in support for Spock/Geb functional tests using the create-functional-test command.

Grails 4

Grails 4 included updates to the versions of the underlying libraries like Spring Boot as well as integration of Micronaut into the core. The following are the minimum library versions supported in Grails 4.0:
  • Spring 5.1

  • Spring Boot 2.1

  • Java 8

  • Hibernate 5.4

  • Groovy 2.5

Testing

Grails supports unit testing with a mixin approach. It inludes the following annotations:
  • @TestFor(X)—Specifies the class under test

  • @Mock(Y)—Creates a mock for the given class

For tests, GORM provides an in-memory mock database that uses ConcurrentHashMap. You can create tests for tag libraries, command objects, URL-Mappings, XML and JSON, and so on.

Cache Plugin

The cache plugin can be used to cache content to enhance the performance of web applications.
  • You can add the @Cacheable annotation on service or controller methods.

  • Cache tags include cache:block and cache:render.

  • Related plugins include cache-ehcache, cache-guava, and cache–headers.

../images/426440_2_En_13_Chapter/426440_2_En_13_Figb_HTML.gifOnly an Overview

This has been a brief overview of Grails. Many books have been written about Grails and how to use it. For more information on using Grails, visit https://grails.org.9

../images/426440_2_En_13_Chapter/426440_2_En_13_Figc_HTML.gifExercise

Create your own Grails app.

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

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