Search

Dark theme | Light theme
Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts

February 27, 2017

Grails Goodness: Custom JSON and Markup Views For Default REST Resources

In Grails we can use the @Resource annotation to make a domain class a REST resource. The annotation adds a controller as URL endpoint for the domain class. Values for the domain class properties are rendered with a default renderer. We can use JSON and markup views to customize the rendering of the domain class annotated with a @Resource annotation. First we must make sure we include views plugin in our build configuration. Then we must create a directory in the grails-app/views directory with the same name as our domain class name. Inside the directory we can add JSON and markup views with names that correspond with the controller actions. For example a file index.gson or index.gml for the index action. We can also create a template view that is automatically used for a resource instance by adding a view with the name of the domain class prefixed with an underscore (_).

In the next example application we create a custom view for the Book domain class that is annotated with the @Resource annotation:

// File: grails-app/domain/mrhaki/sample/Book.groovy
package mrhaki.sample

import grails.rest.Resource

@Resource(uri = '/books')
class Book {
    
    String title
    String isbn
    
    static constraints = {
        title blank: false
        isbn blank: false
    }    
}

Next we must make sure the Grails views code is available as a dependency. In our build.gradle file we must have the following dependencies in the dependencies {} block:

// File: build.gradle
...
dependencies {
    ....
    // Support for JSON views.
    compile "org.grails.plugins:views-json:1.1.5"
    // Support for markup views.
    compile "org.grails.plugins:views-markup:1.1.5"
    ....
}
...

It is time to create new JSON views for JSON responses. We create the directory grails-app/views/book/ and the file _book.gson. This template file is automatically used by Grails now when a Book instances needs to be rendered:

// File: grails-app/views/book/_book.gson
import grails.util.Environment
import mrhaki.sample.Book

model {
    Book book
}

json {
    id book.id
    version book.version
    title book.title
    isbn book.isbn
    information {
        generatedBy 'Sample application'
        grailsVersion Environment.grailsVersion
        environment Environment.current.name
    }
}

We also create the file index.gson to support showing multiple Book instances:

// File: grails-app/views/book/index.gson
import mrhaki.sample.Book

model {
    List<Book> bookList  
} 

// We can use template namespace
// method with a Collection.
json tmpl.book(bookList)

If we also want to support XML we need to create extra markup views. First we a general template for a Book instance with the name _book.gml:

// File: grails-app/views/book/_book.gml
import grails.util.Environment
import mrhaki.sample.Book

model {
    Book book
}

xmlDeclaration()
book {
    id book.id
    title book.title
    isbn book.isbn
    information {
        generatedBy 'Sample application'
        grailsVersion Environment.grailsVersion
        environment Environment.current.name
    }
}

Next we create the file index.gml to show Book instances. Note we cannot use the template namespace in the markup view opposed to in the JSON view:

// File: grails-app/views/book/index.gml
import grails.util.Environment
import mrhaki.sample.Book

model {
    List<Book> bookList
}

xmlDeclaration()
books {
    bookList.each { bookInstance ->
        book {
            id bookInstance.id
            title bookInstance.title
            isbn bookInstance.isbn
            information {
                generatedBy 'Sample application'
                grailsVersion Environment.grailsVersion
                environment Environment.current.name
            }
        }
    }
}

We start our Grails application and use cUrl to invoke our REST resource:

$ curl -H Accept:application/xml http://localhost:8080/books/1
<?xml version='1.0' encoding='UTF-8'?>
<books>
    <book>
        <id>1</id><title>Gradle Dependency Management</title><isbn>978-1784392789</isbn><information>
            <generatedBy>Sample application</generatedBy><grailsVersion>3.2.6</grailsVersion><environment>development</environment>
        </information>
    </book><book>
        <id>2</id><title>Gradle Effective Implementation Guide</title><isbn>978-1784394974</isbn><information>
            <generatedBy>Sample application</generatedBy><grailsVersion>3.2.6</grailsVersion><environment>development</environment>
        </information>
    </book>
</books>

$ curl -H Accept:application/xml http://localhost:8080/books/1
<?xml version='1.0' encoding='UTF-8'?>
<book>
    <id>1</id><title>Gradle Dependency Management</title><isbn>978-1784392789</isbn><information>
        <generatedBy>Sample application</generatedBy><grailsVersion>3.2.6</grailsVersion><environment>development</environment>
    </information>
</book>

$ curl -H Accept:application/json http://localhost:8080/books
[
    {
        "id": 1,
        "version": 0,
        "title": "Gradle Dependency Management",
        "isbn": "978-1784392789",
        "information": {
            "generatedBy": "Sample application",
            "grailsVersion": "3.2.6",
            "environment": "development"
        }
    },
    {
        "id": 2,
        "version": 0,
        "title": "Gradle Effective Implementation Guide",
        "isbn": "978-1784394974",
        "information": {
            "generatedBy": "Sample application",
            "grailsVersion": "3.2.6",
            "environment": "development"
        }
    }
]

$ curl -H Accept:application/json http://localhost:8080/books/1
{
    "id": 1,
    "version": 0,
    "title": "Gradle Dependency Management",
    "isbn": "978-1784392789",
    "information": {
        "generatedBy": "Sample application",
        "grailsVersion": "3.2.6",
        "environment": "development"
    }
}
$

Written with Grails 3.2.6.

February 21, 2017

Grails Goodness: Using Domain Classes Without Persistence

Normally when we create a domain class in Grails we rely on GORM for all the persistence logic. But we can use the static property mapWith with the value none to instruct Grails the domain class is not persisted. This can be useful for example if we want to use a RestfulController for a resource and use the default data binding support in the RestfulController. The resource must be a domain class to make it work, but we might have a custom persistence implementation that is not GORM. By using the mapWith property we can still have benefits from the RestfulController and implement our own persistence mechanism.

In the following example we have a simple Book resource. We define it as a domain class, but tell Grails the persistence should not be handled by GORM:

// File: grails-app/domain/mrhaki/sample/Book.groovy
package mrhaki.sample

import grails.rest.Resource

@Resource(uri = '/books', superClass= BookRestfulController)
class Book {
    
    static mapWith = 'none'
    
    String title
    String isbn
    
    static constraints = {
        title blank: false
        isbn blank: false
        
        // Allow to set id property directly in constructor.
        id bindable: true
    }
    
}

The application also has a Grails service BookRepositoryService that contains custom persistence logic for the Book class. In the following RestfulController for the Book resource we use BookRepositoryService and override methods of RestfulController to have a fully working Book resource:

// File: grails-app/controllers/mrhaki/sample/BookRestfulController.groovy
package mrhaki.sample

import grails.rest.RestfulController

class BookRestfulController extends RestfulController<Book> {
    
    BookRepositoryService bookRepositoryService
    
    BookRestfulController(final Class<Book> resource) {
        super(resource)
    }

    BookRestfulController(final Class<Book> resource, final boolean readOnly) {
        super(resource, readOnly)
    }

    @Override
    protected Book queryForResource(final Serializable id) {
        bookRepositoryService.get(Long.valueOf(id))
    }
    
    @Override
    protected List<Book> listAllResources(final Map params) {
        bookRepositoryService.all
    }

    @Override
    protected Integer countResources() {
        bookRepositoryService.total
    }

    @Override
    protected Book saveResource(final Book resource) {
        bookRepositoryService.add(resource)
    }

    @Override
    protected Book updateResource(final Book resource) {
        bookRepositoryService.update(resource)
    }

    @Override
    protected void deleteResource(final Book resource) {
        bookRepositoryService.remove(resource.id)
    }
}

Written with Grails 3.2.6.

December 9, 2016

Grails Goodness: Writing Log Messages With Grails 3.2 (Slf4J)

Grails 3.2 changed the logging implementation for the log field that is automatically injected in the Grails artefacts, like controllers and services. Before Grails 3.2 the log field was from Jakarta Apache Commons Log class, but since Grails 3.2 this has become the Logger class from Slf4J API. A big difference is the fact that the methods for logging on the Logger class don't accepts an Object as the first argument. Before there would be an implicit toString invocation on an object, but that doesn't work anymore.

In the following example we try to use an object as the first argument of the debug method in a controller class:

package mrhaki.grails3

class SampleController {

    def index() { 
        log.debug new Expando(action: 'index')
        [:]
    }
    
}

When we invoke the index action we get an exception:

...
2016-12-09 14:59:20.283 ERROR --- [nio-8080-exec-1] o.g.web.errors.GrailsExceptionResolver   : MissingMethodException occurred when processing request: [GET] /sample/index
No signature of method: ch.qos.logback.classic.Logger.debug() is applicable for argument types: (groovy.util.Expando) values: [{action=index}]
Possible solutions: debug(java.lang.String), debug(java.lang.String, [Ljava.lang.Object;), debug(java.lang.String, java.lang.Object), debug(java.lang.String, java.lang.Throwable), debug(org.slf4j.Marker, java.lang.String), debug(java.lang.String, java.lang.Object, java.lang.Object). Stacktrace follows:

java.lang.reflect.InvocationTargetException: null
        at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:210)
        at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:187)
        at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: groovy.lang.MissingMethodException: No signature of method: ch.qos.logback.classic.Logger.debug() is applicable for argument types: (groovy.util.Expando) values: [{action=index}]
Possible solutions: debug(java.lang.String), debug(java.lang.String, [Ljava.lang.Object;), debug(java.lang.String, java.lang.Object), debug(java.lang.String, java.lang.Throwable), debug(org.slf4j.Marker, java.lang.String), debug(java.lang.String, java.lang.Object, java.lang.Object)
        at mrhaki.grails3.SampleController.index(SampleController.groovy:6)
        ... 14 common frames omitted
...

When we change the log statement to log.debug new Expando(action: 'index').toString() it works.

Another time saver and great feature is the use of placeholders {} in the logging message. This allows for late binding of variables that are used in the logging message. Remember when we used the Apache Commons Logging library we had to enclose a logging statement in a if statement to check if logging was enabled. Because otherwise the logging message with variable references was always evaluated, even though the logging was disabled. With Slf4J Logger we don't have to wrap logging statements with an if statement if we use the {} placeholders. Slf4J will first check if logging is enabled for the log message and then the logging message is created with the variables. This allows for much cleaner code.

In the following example we use the placeholders to create a logging message that included the variable id:

package mrhaki.grails3

class SampleController {

    def show(final String id) {
        // Before Grails 3.2 we should write:
        // if (log.debugEnabled) {
        //     log.debug "Invoke show with id [$id]"
        // }
        // With Grails 3.2 it is only the debug method and 
        // String evaluation using {}.
        log.debug 'Invoke show with id [{}]', id
        [id: id]
    }
    
}

Written with Grails 3.2.3

November 23, 2016

Grails Goodness: Enabling Grails View In IntelliJ IDEA For Grails 3

IntelliJ IDEA 2016.3 re-introduced the Grails view for Grails 3 applications. Grails 2 applications already were supported with a Grails view in IDEA. Using this view we get an overview of all the Grails artifacts like controller, services, views and more. We can easily navigate to the the class files we need. Now this view is also available for Grails 3 applications.

To enable the view we must click on the view selector in the project view:


We select the Grails option and we get an nice overview of our Grails project in the Grails view:


Also the New action is context sensitive in the Grails view. If we right click on the Services node we can see the option to create a new service class:


If we right click on the root node we get the option to create Grails artifacts:


Written with IntelliJ IDEA 2016.3 and Grails 3.2.2.

November 18, 2016

Grails Goodness Notebook Is Updated

Grails Goodness Notebook has been updated with the latest blog posts. If you have purchased the book before you can download the latest version of the book for free.

  • Saving Server Port In A File
  • Creating A Runnable Distribution
  • Change Version For Dependency Defined By BOM
  • Use Random Server Port In Integration Tests
  • Running Tests Continuously
  • Add Git Commit Information To Info Endpoint
  • Adding Custom Info To Info Endpoint
  • Add Banner To Grails 3.1 Application
  • Creating A Fully Executable Jar
  • Pass JSON Configuration Via Command Line

October 19, 2016

Grails Goodness: Skip Bootstrap Code

Grails normally will run any *Bootstrap classes at startup. A Bootstrap class has a init and destroy closure. The init closure is invoked during startup and destroy when the application stops. The class name must end with Bootstrap and be placed in the grails-app/init folder. Since Grails 3.2 we can skip the execution of Bootstrap classes by setting the Java system property grails.bootstrap.skip with the value true.

In the following example Bootstrap class we simply add a println to see the effect of using the system property grails.bootstrap.skip:

// File: grails-app/init/mrhaki/Bootstrap.groovy
package mrhaki

class Bootstrap {
    def init = { servletContext ->
        println "Run Bootstrap"
    }
    
    def destroy = {
    }
}

First we build the application and than start it from the generated WAR file:

$ gradle build
...
:build

BUILD SUCCESSFUL

Total time: 22.235 secs
$ java -jar build/libs/sample-app-0.1.war
Run Bootstrap
Grails application running at http://localhost:8080 in environment: production

Next we use the Java system property grails.bootstrap.skip:

$ java -Dgrails.bootstrap.skip=true -jar build/libs/sample-app-0.1.war
Grails application running at http://localhost:8080 in environment: production

Notice the println statement from Bootstrap.groovy is not invoked anymore.

Written with Grails 3.2.1

June 27, 2016

Grails Goodness: Pass JSON Configuration Via Command Line

We can use the environment variable SPRING_APPLICATION_JSON with a JSON value as configuration source for our Grails 3 application. The JSON value is parsed and merged with the configuration. Instead of the environment variable we can also use the Java system property spring.application.json.

Let's create a simple controller that reads the configuration property app.message:

// File: grails-app/controllers/mrhaki/grails/config/SampleController.groovy
package mrhaki.grails.config

import org.springframework.beans.factory.annotation.Value

class MessageController {
    
    @Value('${app.message}')
    String message

    def index() { 
        render message
    }
}

Next we start Grails and set the environment variable SPRING_APPLICATION_JSON with a value for app.message:

$ SPRING_APPLICATION_JSON='{"app":{"message":"Grails 3 is Spring Boot on steroids"}}' grails run-app
| Running application...
Grails application running at http://localhost:8080 in environment: development

When we request the sample endpoint we see the value of app.message:

$ http -b :8080/message
Grails 3 is Spring Boot on steroids
$

If we want to use the Java system property spring.application.json with the Grails command we must first configure the bootRun task so all system properties are passed along:

// File: build.gradle
...
bootRun {
    systemProperties System.properties
}
...

With the following command we pass the configuration as inline JSON:

$ grails -Dspring.application.json='{"app":{"message":"Grails 3 is Spring Boot on steroids"}}' run-app
| Running application...
Grails application running at http://localhost:8080 in environment: development

Written with Grails 3.1.8.

June 20, 2016

Grails Goodness: Add Banner To Grails 3.1 Application

In a previous post we learned how to add a banner to a Grails 3.0 application. We used the Spring Boot support in Grails to show a banner on startup. The solution we used doesn't work for a Grails 3.1 application. We need to implement a different solution to show a banner on startup.

First of all we create a new class that implements the org.springframework.boot.Banner interface. We implement the single method printBanner and logic to display a banner, including colors:

// File: src/main/groovy/mrhaki/grails/GrailsBanner.groovy
package mrhaki.grails

import org.springframework.boot.Banner
import grails.util.Environment
import org.springframework.boot.ansi.AnsiColor
import org.springframework.boot.ansi.AnsiOutput
import org.springframework.boot.ansi.AnsiStyle

import static grails.util.Metadata.current as metaInfo

/**
 * Class that implements Spring Boot Banner
 * interface to show information on application startup.
 */
class GrailsBanner implements Banner {

    /**
     * ASCCI art Grails 3.1 logo built on
     * http://patorjk.com/software/taag/#p=display&f=Graffiti&t=Type%20Something%20
     */
    private static final String BANNER = $/
  _________________    _____  .___.____       _________ ________      ____ 
 /  _____|______   \  /  _  \ |   |    |     /   _____/ \_____  \    /_   |
/   \  ___|       _/ /  /_\  \|   |    |     \_____  \    _(__  <     |   |
\    \_\  \    |   \/    |    \   |    |___  /        \  /       \    |   |
 \______  /____|_  /\____|__  /___|_______ \/_______  / /______  / /\ |___|
        \/       \/         \/            \/        \/         \/  \/      
    /$

    @Override
    void printBanner(
            org.springframework.core.env.Environment environment,
            Class<?> sourceClass,
            PrintStream out) {

        // Print ASCII art banner with color yellow.
        out.println AnsiOutput.toString(AnsiColor.BRIGHT_YELLOW, BANNER)

        // Display extran infomratio about the application.
        row 'App version', metaInfo.getApplicationVersion(), out
        row 'App name', metaInfo.getApplicationName(), out
        row 'Grails version', metaInfo.getGrailsVersion(), out
        row 'Groovy version', GroovySystem.version, out
        row 'JVM version', System.getProperty('java.version'), out
        row 'Reloading active', Environment.reloadingAgentEnabled, out
        row 'Environment', Environment.current.name, out
        
        out.println()
    }

    private void row(final String description, final value, final PrintStream out) {
        out.print AnsiOutput.toString(AnsiColor.DEFAULT, ':: ')
        out.print AnsiOutput.toString(AnsiColor.GREEN, description.padRight(16))
        out.print AnsiOutput.toString(AnsiColor.DEFAULT, ' :: ')
        out.println AnsiOutput.toString(AnsiColor.BRIGHT_CYAN, AnsiStyle.FAINT, value)
    }

}

Next we must override the GrailsApp class. We override the printBanner method, which has no implementation in the GrailsApp class. In our printBanner method we use GrailsBanner:

// File: src/main/groovy/mrhaki/grails/BannerGrailsApp.groovy
package mrhaki.grails

import grails.boot.GrailsApp
import groovy.transform.InheritConstructors
import org.springframework.core.env.Environment

@InheritConstructors
class BannerGrailsApp extends GrailsApp {
    
    @Override
    protected void printBanner(final Environment environment) {
        // Create GrailsBanner instance.
        final GrailsBanner banner = new GrailsBanner()

        banner.printBanner(environment, Application, System.out)
    }
    
}

Finally in the Application class we use BannerGrailsApp instead of the default GrailsApp object:

// File: grails-app/init/mrhaki/grails/Application.groovy
package mrhaki.grails

import grails.boot.config.GrailsAutoConfiguration

class Application extends GrailsAutoConfiguration {
    static void main(String[] args) {
        final BannerGrailsApp app = new BannerGrailsApp(Application)
        app.run(args)
    }
}

When we start our Grails application on a console with color support we see the following banner:

Written with Grails 3.1.8.

Grails Goodness: Creating A Fully Executable Jar

With Grails 3 we can create a so-called fat jar or war file. To run our application we only have to use java -jar followed by our archive file name and the application starts. Another option is to create a fully executable jar or war file, which adds a shell script in front of the jar or war file so we can immediately run the jar or war file. We don't have to use java -jar anymore to run our Grails application. The fully executable JAR file can only run on Unix-like systems and it is ready to be used as service using init.d or systemd.

To create a fully executable jar file for our Grails application we must add the following lines to our build.gradle file:

// File: build.gradle
...
// Disable war plugin to create a jar file
// otherwise a fully executable war file
// is created.
//apply plugin: 'war'

...
springBoot {
    // Enable the creation of a fully
    // executable archive file.
    executable = true
}

Next we execute the Gradle assemble task to create the fully executable archive:

grails> assemble
...
:compileGroovyPages
:jar
:bootRepackage
:assemble

BUILD SUCCESSFUL

Total time: 5.619 secs
| Built application to build/libs using environment: production
grails>

We can find the executable archive file in the build/libs directory. Suppose our Grails application is called grails-full-executable-jar and has version 0.1 we can execute the jar file grails-full-executable-jar-0.1.jar:

$ cd build/libs
$ ./grails-full-executable-jar-0.1.jar
Grails application running at http://localhost:8080 in environment: production

The launch script that is prepended to the archive file can be changed by defining a new launch script with the springBoot property embeddedLaunchScript. The default launch script that is used has some variable placeholders we can change using the embeddedLaunchScriptProperties property. For example the launch script can determine if the script is used to run the application standalone or as a Linux/Unix service and will act accordingly. We can also set the mode property to service so it will always act like a Linux/Unix service. Furthermore we can set some meta information for the launch script with several properties. To learn more about the different options see the Spring Boot documentation.

// File: build.gradle
...
springBoot {
    // Enable the creation of a fully
    // executable archive file.
    executable = true

    // Set values for variable placeholders
    // in the default launch script.
    embeddedLaunchScriptProperties =
        [initInfoDescription: project.description,
         initInfoShortDescription: project.name,
         initInfoProvides: jar.baseName,
         mode: 'service']
}

After we have recreated the archive file we can check the launch script that is created:

$ head -n 55 build/libs/grails-full-executable-jar-0.1.jar
#!/bin/bash
#
#    .   ____          _            __ _ _
#   /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
#  ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
#   \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
#    '  |____| .__|_| |_|_| |_\__, | / / / /
#   =========|_|==============|___/=/_/_/_/
#   :: Spring Boot Startup Script ::
#

### BEGIN INIT INFO
# Provides:          grails-full-executable-jar
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: grails-full-executable-jar
# Description:       Sample Grails Application
# chkconfig:         2345 99 01
### END INIT INFO

[[ -n "$DEBUG" ]] && set -x

# Initialize variables that cannot be provided by a .conf file
WORKING_DIR="$(pwd)"
# shellcheck disable=SC2153
[[ -n "$JARFILE" ]] && jarfile="$JARFILE"
[[ -n "$APP_NAME" ]] && identity="$APP_NAME"

# Follow symlinks to find the real jar and detect init.d script
cd "$(dirname "$0")" || exit 1
[[ -z "$jarfile" ]] && jarfile=$(pwd)/$(basename "$0")
while [[ -L "$jarfile" ]]; do
  [[ "$jarfile" =~ init\.d ]] && init_script=$(basename "$jarfile")
  jarfile=$(readlink "$jarfile")
  cd "$(dirname "$jarfile")" || exit 1
  jarfile=$(pwd)/$(basename "$jarfile")
done
jarfolder="$(dirname "$jarfile")"
cd "$WORKING_DIR" || exit 1

# Source any config file
configfile="$(basename "${jarfile%.*}.conf")"
# shellcheck source=/dev/null
[[ -r "${jarfolder}/${configfile}" ]] && source "${jarfolder}/${configfile}"

# Initialize PID/LOG locations if they weren't provided by the config file
[[ -z "$PID_FOLDER" ]] && PID_FOLDER="/var/run"
[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="/var/log"
! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp"
! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp"

# Set up defaults
[[ -z "$MODE" ]] && MODE="service" # modes are "auto", "service" or "run"
$ cd build/libs
$ ./grails-full-executable-jar.0.1.jar
Usage: ./grails-full-executable-jar-0.1.jar {start|stop|restart|force-reload|status|run}
$

Written with Grails 3.1.8.

June 17, 2016

Grails Goodness: Adding Custom Info To Info Endpoint

In a previous post we learned how to add Git commit information to the /info endpoint in our Grails application. We can add our own custom information to this endpoint by defining application properties that start with info..

Let's add the Grails environment the application runs in to the /info endpoint. We create the file grails-app/conf/application.groovy. To get the value we must have a piece of code that is executed so using the application.groovy makes this possible instead of a static configuration file like application.yml:

// File: grails-app/conf/application.groovy
import grails.util.Environment

// Property info.app.grailsEnv.
// Because it starts with info. it ends
// up in the /info endpoint.
info {
    app {
        grailsEnv = Environment.isSystemSet() ? Environment.current.name : Environment.PRODUCTION.name
    }
}

We also want to have information available at build time to be included. Therefore we write a new Gradle task in our build.gradle that create an application.properties file in the build directory. The contents is created when we run or build our Grails application. We just have to make sure the properties stored in application.properties start with info.:

// File: build.gradle
...
task buildInfoProperties() {
    ext {
        buildInfoPropertiesFile = 
            file("$buildDir/resources/main/application.properties")
        
        info = [
            // Look for System environment variable BUILD_TAG.    
            tag: System.getenv('BUILD_TAG') ?: 'N/A', 
            // Use current date.    
            time: new Date().time,
            // Get username from System properties.    
            by: System.properties['user.name']]
    }
    
    inputs.properties info
    outputs.file buildInfoPropertiesFile

    doFirst {
        buildInfoPropertiesFile.parentFile.mkdirs()
        
        ant.propertyfile(file: ext.buildInfoPropertiesFile) {
            for(me in info) {
                entry key: "info.buildInfo.${me.key}", value: me.value
            }
        }
    }
}
processResources.dependsOn(buildInfoProperties)

// Add extra information to be saved in application.properties.
buildInfoProperties.info.machine = "${InetAddress.localHost.hostName}"
...

Let's run our Grails application:

$ export BUILD_TAG=jenkins-grails_app-42 
$ grails run-app
...
| Running application...
Grails application running at http://localhost:8080 in environment: development

And we look at the output of the /info endpoint:

$ http --body http://localhost:8080/info
{
    "app": {
        "grailsEnv": "development",
        "grailsVersion": "3.1.8",
        "name": "grails-gitinfo",
        "version": "1.0.0.DEVELOPMENT"
    },
    "buildInfo": {
        "by": "mrhaki",
        "machine": "mrhaki-laptop-2015.local",
        "time": "1466173858064",
        "tag": "jenkins-grails_app-42"
    }
}
$

Written with Grails 3.1.8.

Grails Goodness: Add Git Commit Information To Info Endpoint

We know Grails 3 is based on Spring Boot. This means we can use Spring Boot features in our Grails application. For example a default Grails application has a dependency on Spring Boot Actuator, which means we have a /info endpoint when we start the application. We add the Git commit id and branch to the /info endpoint so we can see which Git commit was used to create the running application.

First we must add the Gradle Git properties plugin to our build.gradle file. This plugin create a git.properties file that is picked up by Spring Boot Actuator so it can be shown to the user:

buildscript {
    ext {
        grailsVersion = project.grailsVersion
    }
    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/core" }
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.8.2"
        classpath "org.grails.plugins:hibernate4:5.0.6"
        
        // Add Gradle Git properties plugin
        classpath "gradle.plugin.com.gorylenko.gradle-git-properties:gradle-git-properties:1.4.16"
    }
}

version "1.0.0.DEVELOPMENT"
group "mrhaki.grails.gitinfo"

apply plugin:"eclipse"
apply plugin:"idea"
apply plugin:"war"
apply plugin:"org.grails.grails-web"
apply plugin:"org.grails.grails-gsp"
apply plugin:"asset-pipeline"

// Add Gradle Git properties plugin
apply plugin: "com.gorylenko.gradle-git-properties"
...

And that is everything we need to do. We can start our application and open the /info endpoint and we see our Git commit information:

$ http --body localhost:8080/info
{
    "app": {
        "grailsVersion": "3.1.8",
        "name": "grails-gitinfo",
        "version": "1.0.0.DEVELOPMENT"
    },
    "git": {
        "branch": "master",
        "commit": {
            "id": "481efde",
            "time": "1466156037"
        }
    }
}
$

Written with Grails 3.1.8.

May 12, 2016

Grails Goodness: Running Tests Continuously

When we write software it is good practice to also write tests. Either before writing actual code or after, we still need to write tests. In Grails we can use the test-app command to execute our tests. If we specify the extra option -continuous Grails will monitor the file system for changes in class files and automatically compiles the code and executes the tests again. This way we only have to start this command once and start writing our code with tests. If we save our files, our code gets compiled and tested automatically. We can see the output in the generated HTML report or on the console.

Suppose we have our Grails interactive shell open and we type the following command:

grails> test-app -continuous
| Started continuous test runner. Monitoring files for changes...
grails>

Written with Grails 3.1.6.

May 11, 2016

Grails Goodness: Use Random Server Port In Integration Tests

Because Grails 3 is based on Spring Boot we can use a lot of the functionality of Spring Boot in our Grails applications. For example we can start Grails 3 with a random available port number, which is useful in integration testing scenario's. To use a random port we must set the application property server.port to the value 0. If we want to use the random port number in our code we can access it via the @Value annotation with the expression ${local.server.port}.

Let's create a very simple controller with a corresponding integration test. The controller is called Sample:

// File: grails-app/controllers/mrhaki/SampleController.groovy
package mrhaki

class SampleController {

    def index() { 
        respond([message: 'Grails 3 is awesome!'])
    }
}

We write a Spock integration test that will start Grails and we use the HTTP Requests library to access the /sample endpoint of our application.

// File: src/integration-test/groovy/mrhaki/SampleControllerIntSpec.groovy
package mrhaki

import com.budjb.httprequests.HttpClient
import com.budjb.httprequests.HttpClientFactory
import grails.test.mixin.integration.Integration
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import spock.lang.Specification

@Integration
class SampleControllerIntSpec extends Specification {
    
    /**
     * Server port configuration for Grails test 
     * environment is set to server.port = 0, which
     * means a random available port is used each time
     * the application starts.
     * The value for the port number is accessible
     * via ${local.server.port} in our integration test.
     */
    @Value('${local.server.port}')
    Integer serverPort

    /**
     * HTTP test client from the HTTP Requests library:
     * http://budjb.github.io/http-requests/latest
     */
    @Autowired
    HttpClientFactory httpClientFactory

    private HttpClient client

    def setup() {
        // Create HTTP client for testing controller.
        client = httpClientFactory.createHttpClient()
    }

    void "sample should return JSON response"() {
        when:
        // Nice DSL to build a request.
        def response = client.get {
            // Here we use the serverPort variable.
            uri = "http://localhost:${serverPort}/sample"
            accept = 'application/json'
        }
        
        then:
        response.status == 200
        
        and:
        final Map responseData = response.getEntity(Map)
        responseData.message == 'Grails 3 is awesome!'
    }
}

Finally we add the server.port to the application configuration:

# File: grails-app/conf/application.yml
...
environments:
    test:
        server:
            port: 0 # Random available port
...

Let's run the integration test: $ grails test-app mrhaki.SampleControllerIntSpec -integration. When we open the test report and look at the standard output we can see that a random port is used:

Written with Grails 3.1.6.

Grails Goodness: Change Version For Dependency Defined By BOM

Since Grails 3 we use Gradle as the build system. This means we also use Gradle to define dependencies we need. The default Gradle build file that is created when we create a new Grails application contains the Gradle dependency management plugin via the Gradle Grails plugin. With the dependency management plugin we can import a Maven Bill Of Materials (BOM) file. And that is exactly what Grails does by importing a BOM with Grails dependencies. A lot of the versions of these dependencies can be overridden via Gradle project properties.

To get the list of version properties we write a simple Gradle task to print out the values:

// File: build.gradle
...
task dependencyManagementProperties << {
    description = 'Print all BOM properties to the console'

    // Sort properties and print to console.
    dependencyManagement
        .importedProperties
        .toSorted()
        .each { property -> println property }
}
...

When we run the task we get an overview of the properties:

$ gradle dependencyManagementProperties
:dependencyManagementProperties
activemq.version=5.12.3
antlr2.version=2.7.7
artemis.version=1.1.0
aspectj.version=1.8.8
atomikos.version=3.9.3
bitronix.version=2.1.4
cassandra-driver.version=2.1.9
commons-beanutils.version=1.9.2
commons-collections.version=3.2.2
commons-dbcp.version=1.4
commons-dbcp2.version=2.1.1
commons-digester.version=2.1
commons-pool.version=1.6
commons-pool2.version=2.4.2
crashub.version=1.3.2
derby.version=10.12.1.1
dropwizard-metrics.version=3.1.2
ehcache.version=2.10.1
elasticsearch.version=1.5.2
embedded-mongo.version=1.50.2
flyway.version=3.2.1
freemarker.version=2.3.23
gemfire.version=8.1.0
glassfish-el.version=3.0.0
gradle.version=1.12
groovy.version=2.4.6
gson.version=2.3.1
h2.version=1.4.191
...
BUILD SUCCESSFUL

Total time: 1.316 secs

For example if we want to change the version of the PostgreSQL JDBC driver that is provided by the BOM we only have to set the Gradle project property postgresql.version either in our build file or in the properties file gradle.properties:

// File: build.gradle
...
// Change version of PostgreSQL driver
// defined in the BOM.
ext['postgresql.version'] = '9.4.1208'
...
dependencies {
    ...
    // We don't have to specify the version
    // of the dependency, because it is 
    // resolved via the dependency management
    // plugin.
    runtime 'org.postgresql:postgresql'
}
...

Another way to change the version for a dependency defined in the BOM is to include a dependency definition in the dependencyManagement configuration block. Let's see what it looks like for our example:

// File: build.gradle
...
dependencyManagement {
    imports {
        mavenBom "org.grails:grails-bom:$grailsVersion"
    }
    dependencies {
        // Dependencies defined here overrule the
        // dependency definition from the BOM.
        dependency 'org.postgresql:postgresql:9.4.1208'
    }
    applyMavenExclusions false
}

dependencies {
    ...
    // We don't have to specify the version
    // of the dependency, because it is 
    // resolved via the dependency management
    // plugin.
    runtime 'org.postgresql:postgresql'
}
...

To see the actual version that is used we can run the task dependencyInsight:

$ gradle dependencyInsight --dependency postgres --configuration runtime
:dependencyInsight
org.postgresql:postgresql:9.4.1208 (selected by rule)

org.postgresql:postgresql: -> 9.4.1208
\--- runtime

BUILD SUCCESSFUL

Total time: 1.312 secs

This is just another nice example of the good choice of the Grails team to use Gradle as the build system.

Written with Grails 3.1.6

February 8, 2016

Grails Goodness: Creating A Runnable Distribution

Grails 3.1 allows us to build a runnable WAR file for our application with the package command. We can run this WAR file with Java using the -jar option. In Grails 3.0 the package command also created a JAR file that could be executed as standalone application. Let's see how we can still create the JAR with Grails 3.1.

First we use the package command to create the WAR file. The file is generated in the directory build/libs. The WAR file can be run with the command java -jar sample-0.1.war if the file name of our WAR file is sample-0.1.war. It is important to run this command in the same directory as where the WAR file is, otherwise we get an ServletException when we open the application in our web browser (javax.servlet.ServletException: Could not resolve view with name '/index' in servlet with name 'grailsDispatcherServlet').

$ grails package
:compileJava UP-TO-DATE
:compileGroovy
:findMainClass
:assetCompile
...
Finished Precompiling Assets
:buildProperties
:processResources
:classes
:compileWebappGroovyPages UP-TO-DATE
:compileGroovyPages
:war
:bootRepackage
:assemble

BUILD SUCCESSFUL

| Built application to build/libs using environment: production
$ cd build/libs
$ java -jar sample-0.1.war
Grails application running at http://localhost:8080 in environment: production

Instead of using the Grails package command we can use the assemble task if we use Gradle: $ ./gradlew assemble

To create a runnable JAR file we only have to remove the war plugin from our Gradle build file. The package command now creates the JAR file in the directory build/libs.

$ grails package
:compileJava UP-TO-DATE
:compileGroovy
:findMainClass
:assetCompile
...
Finished Precompiling Assets
:buildProperties
:processResources
:classes
:compileWebappGroovyPages UP-TO-DATE
:compileGroovyPages
:jar
:bootRepackage
:assemble

BUILD SUCCESSFUL

| Built application to build/libs using environment: production
$ java -jar build/libs/sample-0.1.jar
Grails application running at http://localhost:8080 in environment: production

Alternatively we can use the Gradle task assemble instead of the Grails package command.

Written with Grails 3.1.

February 5, 2016

Grails Goodness: Saving Server Port In A File

In a previous post we learned how to save the application PID in a file when we start our Grails application. We can also save the port number the application uses in a file when we run our Grails application. We must use the class EmbeddedServerPortFileWriter and add it as a listener to the GrailsApp instance. By default the server port is saved in a file application.port. But we can pass a custom file name or File object to the constructor of the EmbeddedServerPortFileWriter class.

In the following example we use the file name application.server.port to store the port number:

// File: grails-app/init/sample/Application.groovy
package sample

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import groovy.transform.CompileStatic
import org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter

@CompileStatic
class Application extends GrailsAutoConfiguration {

    static void main(String[] args) {
        final GrailsApp app = new GrailsApp(Application)

        // Save port number in file name application.server.port
        final EmbeddedServerPortFileWriter serverPortFileWriter =
                new EmbeddedServerPortFileWriter('application.server.port')

        // Add serverPortFileWriter as application listener
        // so the port number is saved when we start
        // our Grails application.
        app.addListeners(serverPortFileWriter)
        
        app.run(args)
    }
    
}

When the application is started we can find the file application.server.port in the directory from where the application is started. When we open it we see the port number:

$ cat application.server.port
8080
$

Written with Grails 3.1.

February 1, 2016

Grails Goodness Notebook Updated

Grails Goodness Notebook has been updated with the latest blog posts. If you have purchased the book before you can download the latest version of the book for free.

New posts in the book are:

  • Run Grails Application As Docker Container
  • Enable Hot Reloading For Non-Development Environments
  • Change Locale With Request Parameter
  • Go To Related Classes In IntelliJ IDEA
  • Quickly Create GSP From Controller In IntelliJ IDEA
  • Using Spring Cloud Config Server
  • Changing Gradle Version
  • Getting More Information About A Profile
  • Using Features When Creating An Application

January 29, 2016

Grails Goodness: Using Features When Creating An Application

With the release of Grails 3.1 we can use features, defined in a profile, when we create a new application. Features will add certain dependencies to our Grails project, so we can start quickly. To see which features are available we use the profile-info command. This command lists available features for an application. We can choose the features we want to be included and pass them via the --features command line option of the create-app command.

When we look at the features available for the rest-api profile we see the following list:

$ grails profile-info rest-api
...
Provided Features:
--------------------
* asset-pipeline - Adds Asset Pipeline to a Grails project
* hibernate - Adds GORM for Hibernate to the project
* json-views - Adds support for JSON Views to the project
* markup-views - Adds support for Markup Views to the project
* mongodb - Adds GORM for MongoDB to the project
* neo4j - Adds GORM for Neo4j to the project
* security - Adds Spring Security REST to the project

$

Let's create a new Grails application with the rest-api profile and use the mongodb, json-views and security features:

$ grails create-app --profile rest-api --features mongodb,json-views,security api
| Application created at /Users/mrhaki/Projects/mrhaki.com/blog/posts/samples/grails31/api
$

When we look at the contents of the generated build.gradle we can see dependencies for the features we have selected:

// File: build.gradle
buildscript {
    ext {
        grailsVersion = project.grailsVersion
    }
    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/core" }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "org.grails.plugins:views-gradle:1.0.0"
    }
}

version "0.1"
group "api"

apply plugin:"eclipse"
apply plugin:"idea"
apply plugin:"org.grails.grails-web"
apply plugin:"org.grails.plugins.views-json"

ext {
    grailsVersion = project.grailsVersion
    gradleWrapperVersion = project.gradleWrapperVersion
}

repositories {
    mavenLocal()
    maven { url "https://repo.grails.org/grails/core" }
}

dependencyManagement {
    imports {
        mavenBom "org.grails:grails-bom:$grailsVersion"
    }
    applyMavenExclusions false
}

dependencies {
    compile "org.springframework.boot:spring-boot-starter-logging"
    compile "org.springframework.boot:spring-boot-autoconfigure"
    compile "org.grails:grails-core"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    compile "org.springframework.boot:spring-boot-starter-tomcat"
    compile "org.grails:grails-plugin-url-mappings"
    compile "org.grails:grails-plugin-rest"
    compile "org.grails:grails-plugin-codecs"
    compile "org.grails:grails-plugin-interceptors"
    compile "org.grails:grails-plugin-services"
    compile "org.grails:grails-plugin-datasource"
    compile "org.grails:grails-plugin-databinding"
    compile "org.grails:grails-plugin-async"
    compile "org.grails:grails-web-boot"
    compile "org.grails:grails-logging"
    compile "org.grails.plugins:cache"
    compile "org.grails.plugins:views-json"
    compile "org.grails.plugins:mongodb"
    compile "org.grails:grails-plugin-gsp"
    compile "org.grails.plugins:spring-security-rest:2.0.0.M1"
    console "org.grails:grails-console"
    profile "org.grails.profiles:rest-api:3.1.0"
    testCompile "org.grails:grails-plugin-testing"
    testCompile "org.grails.plugins:geb"
    testCompile "org.grails:grails-datastore-rest-client"
    testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
    testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"
}

task wrapper(type: Wrapper) {
    gradleVersion = gradleWrapperVersion
}

Written with Grails 3.1.

Grails Goodness: Getting More Information About A Profile

Since Grails 3.1 we can use the profile-info command to get more information about a profile. We see which commands are added to our project by the profile and which features can be chosen when we create a new application with the profile.

Suppose we want to know more about the rest-api profile then we invoke the profile-info command:

$ grails profile-info rest-api
Profile: rest-api
--------------------
Profile for Web API applications

Provided Commands:
--------------------
* create-controller - Creates a controller
* create-domain-resource - Creates a domain class that represents a resource
* create-functional-test - Creates an functional test
* create-integration-test - Creates an integration test
* create-interceptor - Creates an interceptor
* create-restful-controller - Creates a REST controller
* help - Prints help information for a specific command
* open - Opens a file in the project
* gradle - Allows running of Gradle tasks
* clean - Cleans a Grails application's compiled sources
* compile - Compiles a Grails application
* create-domain-class - Creates a Domain Class
* create-service - Creates a Service
* create-unit-test - Creates a unit test
* dependency-report - Prints out the Grails application's dependencies
* install - Installs a Grails application or plugin into the local Maven cache
* assemble - Creates a JAR or WAR archive for production deployment
* bug-report - Creates a zip file that can be attached to issue reports for the current project
* console - Runs the Grails interactive console
* create-script - Creates a Grails script
* list-plugins - Lists available plugins from the Plugin Repository
* plugin-info - Prints information about the given plugin
* run-app - Runs a Grails application
* shell - Runs the Grails interactive shell
* stats - Prints statistics about the project
* stop-app - Stops the running Grails application
* test-app - Runs the applications tests
* generate-all - Generates a controller that performs REST operations
* generate-controller - Generates a controller that performs REST operations
* generate-functional-test - Generates a functional test for a controller that performs REST operations
* generate-unit-test - Generates a unit test for a controller that performs REST operations
* generate-views - Generates a controller that performs REST operations

Provided Features:
--------------------
* asset-pipeline - Adds Asset Pipeline to a Grails project
* hibernate - Adds GORM for Hibernate to the project
* json-views - Adds support for JSON Views to the project
* markup-views - Adds support for Markup Views to the project
* mongodb - Adds GORM for MongoDB to the project
* neo4j - Adds GORM for Neo4j to the project
* security - Adds Spring Security REST to the project

$

Written with Grails 3.1.

January 27, 2016

Grails Goodness: Changing Gradle Version

Since Grails 3 Gradle is used as the build tool. The Grails shell and commands use Gradle to execute tasks. When we create a new Grails 3 application a Gradle wrapper is added to our project. The Gradle wrapper is used to download and use a specific Gradle version for a project. This version is also used by the Grails shell and commands. The default version (for Grails 3.0.12) is Gradle 2.3, which is also part of the Grails distribution. At the time of writing this blog post the latest Gradle version is 2.10. Sometimes we use Gradle plugins in our project that need a higher Gradle version, or we just want to use the latest version because of improvements in Gradle. We can change the Gradle version that needs to be used by Grails in different ways.

Grails will first look for an environment variable GRAILS_GRADLE_HOME. It must be set to the location of a Gradle installation. If it is present is used as the Gradle version by Grails. In the following example we use this environment variable to force Grails to use Gradle 2.10:

$ GRAILS_GRADLE_HOME=~/.sdkman/gradle/2.10 grails

BUILD SUCCESSFUL

| Enter a command name to run. Use TAB for completion:
grails> gradle help
:help

Welcome to Gradle 2.10.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 0.861 secs
grails>

Another way to set the Gradle version is by change the Gradle wrapper version. In our build.gradle file there is a task wrapper. This creates a Gradle wrapper for our project with the version that is specified in the file gradle.properties with the property gradleWrapperVersion. Let's change the value of gradleWrapperVersion to 2.10 and execute the wrapper task. We can change the value in the grade.properties file, the build.gradle file or pass it via the command line:

$ ./gradlew wrapper -PgradleWrapperVersion=2.10
:wrapper

BUILD SUCCESSFUL

Total time: 2.67 secs

$ grails

BUILD SUCCESSFUL

| Enter a command name to run. Use TAB for completion:
grails> gradle help
:help

Welcome to Gradle 2.10.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 0.861 secs
grails> 

It could be that we get an org/gradle/mvn3/org/apache/maven/model/building/ModelBuildingException exception after upgrading to a newer version. This is because the io.spring.dependency-management plugin is set to a version not supported by the newer Gradle version. If we change the version of the plugin to the latest version (0.5.4.RELEASE at the time of writing this blog post) the error is solved.

It also important to notice that Grails will look for Gradle wrapper defined for the base project if we use our Grails project in a multi-module project. So the directory that contains the settings.gradle file is then used to look for a Gradle wrapper. If it is not found the default Gradle version that is defined by the Grails distribution is used.

Written with Grails 3.0.12.