(Quick Reference)

16 Building a Successful Application

Version: 7.0.8-SNAPSHOT

16 Building a Successful Application

Building a successful Grails application goes beyond writing features. Code analysis, consistent styling, continuous integration, and reliable release processes help maintain quality as your project grows. This section covers tools and practices that support long-term project health.

16.1 Code Analysis and Styling for Groovy

CodeNarc is a static analysis tool for Groovy that finds defects, poor coding practices, inconsistencies, style issues, and more. Grails projects can integrate CodeNarc via the Gradle CodeNarc plugin.

Adding Code Analysis to Your Build

Apply the CodeNarc plugin and configure it using extensions.configure():

import org.gradle.api.plugins.quality.CodeNarcExtension

plugins {
    id 'codenarc'
}

dependencies {
    codenarc 'org.codenarc:CodeNarc:3.6.0-groovy-4.0'
}

extensions.configure(CodeNarcExtension) {
    it.configFile = file('config/codenarc/codenarc.groovy')
    it.maxPriority1Violations = 0
    it.maxPriority2Violations = 0
    it.maxPriority3Violations = 0
}
Use the -groovy-4.0 variant of CodeNarc for Grails 7 projects (which use Groovy 4.x). The plain artifact without a -groovy-4.0 suffix is built for Groovy 3.x and will not work correctly.

You can then run CodeNarc with:

$ ./gradlew codenarcMain

The HTML report is written to build/reports/codenarc/main.html.

GORM AST Compatibility

CodeNarc provides pre-built rulesets that can be imported as a group using the ruleset() syntax:

// config/codenarc/codenarc.groovy - DO NOT use this approach in Grails projects
ruleset {
    ruleset('rulesets/basic.xml')
    ruleset('rulesets/formatting.xml')
    ruleset('rulesets/unused.xml')
}
Importing entire rulesets with ruleset('rulesets/xxx.xml') in a Grails project causes compilation failures. This is because some CodeNarc rules (known as "enhanced" rules) perform semantic analysis at Groovy compiler phase 4. These enhanced rules attempt to resolve AST-transformed classes such as OrderedGormTransformation and ServiceTransformation, but CodeNarc compiles each source file independently without GORM’s AST transformation processors on its classpath. The result is ClassNotFoundException or NoClassDefFoundError during analysis.

Adding compilationClasspath to the CodeNarc Gradle task helps with basic class resolution but does not make GORM’s transformation processors available, so enhanced rules still fail.

The solution is to list individual rules explicitly rather than importing entire rulesets. This avoids pulling in enhanced rules that require GORM’s AST infrastructure. The Grails framework’s own build uses this approach:

// config/codenarc/codenarc.groovy
ruleset {

    description 'A Codenarc ruleset for the Grails codebase'

    BracesForClass
    ClassStartsWithBlankLine {
        ignoreInnerClasses = true
    }
    ClosureStatementOnOpeningLineOfMultipleLineClosure
    ConsecutiveBlankLines
    FileEndsWithoutNewline
    NoTabCharacter
    DuplicateImport
    ImportFromSamePackage
    Indentation
    MisorderedStaticImports {
        comesBefore = false // static imports should come last
    }
    MissingBlankLineAfterImports
    MissingBlankLineAfterPackage
    MissingBlankLineBeforeAnnotatedField
    NoWildcardImports
    SpaceAfterCatch
    SpaceAfterClosingBrace
    SpaceAfterComma
    SpaceAfterFor
    SpaceAfterIf
    SpaceAfterMethodCallName
    SpaceAfterMethodDeclarationName
    SpaceAfterNotOperator
    SpaceAfterOpeningBrace {
        ignoreEmptyBlock = true
    }
    SpaceAfterSemicolon
    SpaceAfterSwitch
    SpaceAfterWhile
    SpaceAroundClosureArrow
    SpaceAroundMapEntryColon {
        characterAfterColonRegex = ' '
    }
    SpaceAroundOperator {
        ignoreParameterDefaultValueAssignments = false
    }
    SpaceBeforeClosingBrace {
        ignoreEmptyBlock = true
    }
    SpaceBeforeOpeningBrace
    SpaceInsideParentheses
    UnnecessaryConstructor
    UnnecessaryDotClass
    UnnecessaryGroovyImport
    UnnecessaryGString
    UnnecessaryOverridingMethod
    UnnecessaryPublicModifier
    UnnecessarySafeNavigationOperator
    UnnecessarySemicolon
    UnusedImport
}

This is the exact ruleset used by the Grails framework’s own build. It covers formatting, imports, spacing, and unnecessary code - all without triggering GORM AST compatibility issues. You can add additional individual rules as needed.

You can find the full list of available CodeNarc rules at codenarc.org. Add individual rules as needed, testing that each one compiles cleanly against your Grails source files.

Separate Ruleset for Tests

Spock specifications often use patterns that trigger style rules (method names with spaces, loose typing, mock syntax). You can configure a separate, more lenient ruleset for test sources:

tasks.named('codenarcTest', CodeNarc) {
    configFile = file('config/codenarc/codenarc-test.groovy')
}

Reference

The grails-server-timing plugin provides a complete working example of CodeNarc and Checkstyle configuration using Gradle convention plugins in its build-logic/ directory. The Grails framework’s own CodeNarc ruleset can be found in the grails-core repository under build-logic/plugins/src/main/resources/META-INF/org.apache.grails.buildsrc.codestyle/codenarc/codenarc.groovy. Both are reliable starting points for any Grails project.