Loading...

June 24, 2016

Ratpacked: Handling Exceptions When Reading Configuration Sources

To define configuration sources for our Ratpack application we have several options. We can set default properties, look at environment variables or Java system properties, load JSON or YAML formatted configuration files or implement our own configuration source. When something goes wrong using one of these methods we want to be able to handle that situation. For example if an optional configuration file is not found, we want to inform the user, but the application must still start. The default exception handling will throw the exception and the application is stopped. We want to customise this so we have more flexibility on how to handle exceptions.

We provide the configuration source in the serverConfig configuration block of our Ratpack application. We must add the onError method and provide an error handler implementation before we load any configuration source. This error handler will be passed to each configuration source and is execute when an exception occurs when the configuration source is invoked. The error handler implements the Action interface with the type Throwable. In our implementation we can for example check for the type of Throwable and show a correct status message to the user.

In the following example application we rely on external configuration source files that are optional. If the file is present it must be loaded, otherwise a message must be shown to indicate the file is missing, but the application still starts:

// File: src/ratpack/ratpack.groovy
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import java.nio.file.NoSuchFileException
import java.nio.file.Paths

import static ratpack.groovy.Groovy.ratpack

final Logger log = LoggerFactory.getLogger('ratpack.server')

ratpack {
    serverConfig {
        // Use custom error handler, when
        // exceptions happen during loading
        // of configuration sources.
        onError { throwable ->
            if (throwable in NoSuchFileException) {
                final String file = throwable.file
                log.info "Cannot load optional configuration file '{}'", file
            } else {
                throw throwable
            }
        }
        
        yaml('application.yml')

        // Optional configuration files
        // to override values in 
        // 'application.yml'. This could
        // potentially give an exception if
        // the files don't exist.
        yaml(Paths.get('conf/application.yml'))
        json(Paths.get('conf/application.json'))
        
        args(args)
        sysProps()
        env()
        
        ...
    }

    ...
}

Next we start the application with the absence of the optional configuration files conf/application.yml and conf/application.json:

$ gradle run
...
:run

12:28:38.887 [main]            INFO  ratpack.server.RatpackServer - Starting server...
12:28:39.871 [main]            INFO  ratpack.server - Cannot load optional configuration file 'conf/application.yml'
12:28:39.873 [main]            INFO  ratpack.server - Cannot load optional configuration file 'conf/application.json'
12:28:40.006 [main]            INFO  ratpack.server.RatpackServer - Building registry...
12:28:40.494 [main]            INFO  ratpack.server.RatpackServer - Ratpack started (development) for http://localhost:5050

Notice that application is started and in the logging we have nice status messages that tell us the files are not found.

Written with Ratpack 1.3.3.

June 23, 2016

Groovy Goodness: Customise Log AST Annotations

Adding logging support to a class in Groovy is easy. We can choose to add SLF4J, Log4j, Log4j2, Apache Commons or Java Util Logging to our class. The default implementation of the Abstract Syntax Tree (AST) transformation is to add a log field of the correct type. As category name the complete class name (including the package) is used. We can change the name of the field with the value attribute. To alter the category name we use the attribute category.

In the following example snippet we change the log field name to LOGGER and set a custom category name:

@Grapes(
    @Grab(group='ch.qos.logback', module='logback-classic', version='1.1.7')
)
import groovy.util.logging.Slf4j

// Change name of the field to LOGGER and
// the category to 'mrhaki.blog.samples'.
@Slf4j(value = 'LOGGER', category = 'mrhaki.blog.samples')
class SampleLogging {

    String sample(final String message) {
        LOGGER.info 'Running sample({}) method', message
        
        "Groovy is $message!"
    }
    
}

def s = new SampleLogging()
println "System.out says: ${s.sample('gr8')}"

When we execute the script we get the following output:

16:33:56.972 [Thread-7] INFO mrhaki.blog.samples - Running sample(gr8) method
System.out says: Groovy is gr8!

Notice the category is mrhaki.blog.samples and we use the field LOGGER in our code.

Written with Groovy 2.4.7.

June 22, 2016

Groovy Goodness: Turn A Map Or List As String To Map Or List

In a previous post we learned how to use the toListString or toMapString methods. With these methods we create a String representation of a List or Map object. With a bit of Groovy code we can take such a String object and turn it into a List or Map again.

In the following code snippet we turn the String value [abc, 123, Groovy rocks!] to a List with three items:

// Original List with three items.
def original = ['abc', 123, 'Groovy rocks!']

// Create a String representation:
// [abc, 123, Groovy rocks!]
def listAsString = original.toListString()

// Take the String value between
// the [ and ] brackets, then
// split on , to create a List
// with values.
def list = listAsString[1..-2].split(', ')

assert list.size() == 3
assert list[0] == 'abc'
assert list[1] == '123' // String value
assert list[2] == 'Groovy rocks!'

We can do something similar for a String value representing a map structure:

// Original Map structure.
def original = [name: 'mrhaki', age: 42]

// Turn map into String representation:
// [name:mrhaki, age:42]
def mapAsString = original.toMapString()

def map = 
    // Take the String value between
    // the [ and ] brackets.
    mapAsString[1..-2]
        // Split on , to get a List.
        .split(', ')
        // Each list item is transformed
        // to a Map entry with key/value.
        .collectEntries { entry -> 
            def pair = entry.split(':')
            [(pair.first()): pair.last()]
        }
        

assert map.size() == 2
assert map.name == 'mrhaki'
assert map.age == '42'

Written with Groovy 2.4.7.

June 21, 2016

Groovy Goodness: Represent Map As String

Groovy adds to Map objects the toMapString method. With this method we can have a String representation of our Map. We can specify an argument for the maximum width of the generated String. Groovy will make sure at least the key/value pairs are added as a pair, before adding three dots (...) if the maximum size is exceeded.

def course = [
    name: 'Groovy 101',
    teacher: 'mrhaki',
    location: 'The Netherlands']
    
assert course.toMapString(15) == '[name:Groovy 101, ...]'
assert course.toMapString(25) == '[name:Groovy 101, teacher:mrhaki, ...]'

As mentioned in a previous post we can use the toListString method to represent a List as a String:

def names = ['mrhaki', 'hubert']

assert names.toListString(5) == '[mrhaki, ...]'

Written with Groovy 2.4.7.

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.

Groovy Goodness: IntelliJ IDEA Formatting Of Closure Chains

When we write code with a lot of method chaining that involves closures and the use the Reformat code feature of IntelliJ IDEA things might get screwed up. Luckily we can changes some Groovy formatting rules in IntelliJ IDEA to prevent the reformatting.

In the following screenshot we see the original piece of code in the IntelliJ IDEA editor:

When we invoke Reformat code command we can have the following result where the cod his not aligned anymore:

Let's set two options in the Preferences to keep the code formatted as is. We need to go to Editor | Code Style | Groovy. In the section Braces placement we enable the option Use flying geese braces:

In the section Chained method calls we enable the option Align when multiline:

Now when we reformat our original piece of code that alignment stays:

Written with IntelliJ IDEA 2016.1.

June 16, 2016

Spring Sweets: Running Our Own Spring Initializr Server

To start a new project based on Spring or Spring Boot we can use the website start.spring.io. We can easily create a project templates based on Maven or Gradle and define all needed dependencies by clicking on checkboxes in the UI. In a previous post we also learned how to create a project using a URL using the same start.spring.io website. The start.spring.io website is actually a Spring Boot application and we can easily host our own server. With our own server we can for example limit the number of dependencies, force Gradle as the only build tool and set default values for project name, packages and much more.

To get started we must first clone the GitHub project. We need to build the project with Maven to install the libraries in our local Maven repository. After that is done we are reading to use it in our own Spring Boot application that is our customised Spring Initializr server. The easiest way to run the server is to have the Spring CLI tool installed. The easiest way to install it is using SDKMAN!. We type on the command line $ sdk install springboot.

Next we create a new directory and inside the directory we create a new Groovy file initializr.groovy:

package app

@Grab('io.spring.initalizr:initializr-web:1.0.0.BUILD-SNAPSHOT')
@Grab('spring-boot-starter-web')
class InitializerService {}

Next we need a configuration file which all the options for the Spring Initializr server. We can start by copying the file application.yml from the initializr-service project on GitHub to our directory with the file initializr.groovy. This file contains a lot of information. The configuration format is explained on the GitHub wiki, but it is really straight forward. If we open the file we can for example remove dependencies from the dependencies or set default values for the groupId. If we only want to support Gradle we can remove the Maven references from the types section. And of course to have Groovy as the default language we can in the languages section set the default to true for Groovy.

...
  artifactId:
    value: sample
  groupId:
    value: com.mrhaki
  version:
    value: 1.0.0.DEVELOPMENT
  name:
    value: Sample
  description:
    value: Sample Project
  packageName:
    value: com.mrhaki.demo
...
  types:
    - name: Gradle Project
      id: gradle-project
      description: Generate a Gradle based project archive
      sts-id: gradle.zip
      tags:
        build: gradle
        format: project
      default: false
      action: /starter.zip
    - name: Gradle Config
      id: gradle-build
      description: Generate a Gradle build file
      sts-id: build.gradle
      tags:
        build: gradle
        format: build
      default: true
      action: /build.gradle
...
  javaVersions:
    - id: 1.8
      default: true
  languages:
    - name: Java
      id: java
      default: false
    - name: Groovy
      id: groovy
      default: true
...

And that is it! We are ready to start our own Spring Initializr server:

$ spring run initializr.groovy
...

For a finishing touch we can also override the static resources and templates of the server application. For example we can add a new spring.css file in the directory static/css. And place a file home.html in the directory templates. We can take the existing files as sample and change what we want.

The following screenshot shows a customized template with some style changes:

We can even use our server to create a project from IntelliJ IDEA. When we create a new project and select Spring Initializr from the list box on the left we can type in the URL of our server:

Next we see our default values for the project details:

And finally we can select the dependencies we have defined in our application.yml file: