# 3. Configuration

It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now, but since what configuration there is typically a one off, it is best to get it out the way.

## 3.1 Basic Configuration

For general configuration Griffon provides a file called `griffon-app/conf/Config.groovy`. This file uses Groovy's ConfigSlurper which is very similar to Java properties files except it is pure Groovy hence you can re-use variables and use proper Java types!

You can add your own configuration in here, for example:

    foo.bar.hello = "world"

Then later in your application you can access these settings via the GriffonApplication object, which is available as a variable in mvc members

    assert "world" == app.config.foo.bar.hello

## 3.1.1 Logging

### The Basics

Griffon uses its common configuration mechanism to provide the settings for the underlying Log4j log system, so all you have to do is add a `log4j` setting to the file `griffon-app/conf/Config.groovy`.

So what does this `log4j` setting look like? Here's a basic example:

    log4j = {
        error  'org.codehaus.griffon'    info   'griffon.util',
               'griffon.core',
               'griffon.swing',
               'griffon.app'}

This says that for the 'org.codehaus.griffon' logger, only messages logged at 'error' level and above will be shown. The loggers whose category start with 'griffon' show messages at the 'info' level. What does that mean? First of all, you have to understand how levels work.

#### Logging levels

The are several standard logging levels, which are listed here in order of descending priority:

1. off
2. fatal
3. error
4. warn
5. info
6. debug
7. trace
8. all

When you log a message, you implicitly give that message a level. For example, the method `log.error(msg)` will log a message at the 'error' level. Likewise, `log.debug(msg)` will log it at 'debug'. Each of the above levels apart from 'off' and 'all' have a corresponding log method of the same name.

The logging system uses that message level combined with the configuration for the logger (see next section) to determine whether the message gets written out. For example, if you have an 'org.example.domain' logger configured like so:

    warn 'org.example.domain'

then messages with a level of 'warn', 'error', or 'fatal' will be written out. Messages at other levels will be ignored.

Before we go on to loggers, a quick note about those 'off' and 'all' levels. These are special in that they can only be used in the configuration; you can't log messages at these levels. So if you configure a logger with a level of 'off', then no messages will be written out. A level of 'all' means that you will see all messages. Simple.

#### Loggers

Loggers are fundamental to the logging system, but they are a source of some confusion. For a start, what are they? Are they shared? How do you configure them?

A logger is the object you log messages to, so in the call `log.debug(msg)`, `log` is a logger instance (of type Logger). These loggers are uniquely identified by name and if two separate classes use loggers with the same name, those loggers are effectively the same instance.

There are two main ways to get hold of a logger:

1. use the `log` instance injected into artifacts such as domain classes, controllers and services;
2. use the Slf4j API directly.

If you use the dynamic `log` property, then the name of the logger is 'griffon.app.<type>.<className>', where `type` is the type of the artifact, say 'controller' or 'service, and `className` is the fully qualified name of the artifact. For example, let's say you have this service:

    package org.exampleclass MyService {
        …
    }

then the name of the logger will be 'griffon.app.service.org.example.MyService'.

For other classes, the typical approach is to store a logger based on the class name in a constant static field:

    package org.otherimport org.slf4j.Logger
    import org.slf4j.LoggerFactoryclass MyClass {
        private static final Logger log = LoggerFactory.getLogger(MyClass)
        …
    }

This will create a logger with the name 'org.other.MyClass' - note the lack of a 'griffon.app.' prefix. You can also pass a name to the `getLog()` method, such as "myLogger", but this is less common because the logging system treats names with dots ('.') in a special way.

#### Configuring loggers

You have already seen how to configure a logger in Griffon:

    log4j = {
        error  'org.codehaus.griffon.runtime'
    }

This example configures a logger named 'org.codehaus.griffon.runtime' to ignore any messages sent to it at a level of 'warn' or lower. But is there a logger with this name in the application? No. So why have a configuration for it? Because the above rule applies to any logger whose name begins with 'org.codehaus.griffon.runtime.' as well. For example, the rule applies to both the `org.codehaus.griffon.runtime.core.DefaultArtifactManager` class and the `org.codehaus.griffon.runtime.util.GriffonApplicationHelper` one.

In other words, loggers are effectively hierarchical. This makes configuring them by package much, much simpler than it would otherwise be.

The most common things that you will want to capture log output from are your controllers, services, and other artifacts. To do that you'll need to use the convention mentioned earlier: griffon.app.<artifactType>.<className> . In particular the class name must be fully qualifed, i.e. with the package if there is one:

    log4j = {
        // Set level for all application artifacts
        info "griffon.app"    // Set for a specific controller
        debug "griffon.app.controller.YourController"    // Set for a specific service class
        debug "griffon.app.service.org.example.SampleService"    // Set for all models
        info "griffon.app.model"
    }

The standard artifact names used in the logging configuration are:

- `model` - For model classes
- `controller` - For controllers
- `view` - For views
- `service` - For service classes

Griffon itself generates plenty of logging information and it can sometimes be helpful to see that. Here are some useful loggers from Griffon internals that you can use, especially when tracking down problems with your application:

- `org.codehaus.griffon.runtime.core` - Core internal information such as MVC group instantiation, etc.
- `griffon.swing` - Swing related initialization and application life cycle.

So far, we've only looked at explicit configuration of loggers. But what about all those loggers that don't have an explicit configuration? Are they simply ignored? The answer lies with the root logger.

#### The Root Logger

All logger objects inherit their configuration from the root logger, so if no explicit configuration is provided for a given logger, then any messages that go to that logger are subject to the rules defined for the root logger. In other words, the root logger provides the default configuration for the logging system.

Griffon automatically configures the root logger to only handle messages at 'error' level and above, and all the messages are directed to the console (stdout for those with a C background). You can customise this behaviour by specifying a 'root' section in your logging configuration like so:

    log4j = {
        root {
            info()
        }
        …
    }

The above example configures the root logger to log messages at 'info' level and above to the default console appender. You can also configure the root logger to log to one or more named appenders (which we'll talk more about shortly):

    log4j = {
        appenders {
            file name:'file', file:'/var/logs/mylog.log'
        }
        root {
            debug 'stdout', 'file'
        }
    }

In the above example, the root logger will log to two appenders - the default 'stdout' (console) appender and a custom 'file' appender.

For power users there is an alternative syntax for configuring the root logger: the root `org.apache.log4j.Logger` instance is passed as an argument to the log4j closure. This allows you to work with the logger directly:

    log4j = { root ->
        root.level = org.apache.log4j.Level.DEBUG
        …
    }

For more information on what you can do with this `Logger` instance, refer to the Log4j API documentation.

Those are the basics of logging pretty well covered and they are sufficient if you're happy to only send log messages to the console. But what if you want to send them to a file? How do you make sure that messages from a particular logger go to a file but not the console? These questions and more will be answered as we look into appenders.

### Appenders

Loggers are a useful mechanism for filtering messages, but they don't physically write the messages anywhere. That's the job of the appender, of which there are various types. For example, there is the default one that writes messages to the console, another that writes them to a file, and several others. You can even create your own appender implementations!

This diagram shows how they fit into the logging pipeline:

As you can see, a single logger may have several appenders attached to it. In a standard Griffon configuration, the console appender named 'stdout' is attached to all loggers through the default root logger configuration. But that's the only one. Adding more appenders can be done within an 'appenders' block:

    log4j = {
        appenders {
            rollingFile name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log"
        }
    }

The following appenders are available by default:

- console (ConsoleAppender) - Logs to the console.
- file (FileAppender) - Logs to a single file.
- rollingFile (RollingFileAppender) - Logs to rolling files, for example a new file each day.
- event (GriffonApplicationEventAppender) - Logs to application events. Event name is "LogEvent"; args are log level (as String), log message and optional throwable.

Each named argument passed to an appender maps to a property of the underlying Appender implementation. So the previous example sets the `name`, `maxFileSize` and `file` properties of the `RollingFileAppender` instance.

You can have as many appenders as you like - just make sure that they all have unique names. You can even have multiple instances of the same appender type, for example several file appenders that log to different files.

If you prefer to create the appender programmatically or if you want to use an appender implementation that's not available via the above syntax, then you can simply declare an `appender` entry with an instance of the appender you want:

    import org.apache.log4j.*log4j = {
        appenders {
            appender new RollingFileAppender(name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log")
        }
    }

This approach can be used to configure `JMSAppender`, `SocketAppender`, `SMTPAppender`, and more.

Once you have declared your extra appenders, you can attach them to specific loggers by passing the name as a key to one of the log level methods from the previous section:

    error myAppender: "griffon.app.controller.BookController"

This will ensure that the 'org.codehaus.groovy.griffon.commons' logger and its children send log messages to 'myAppender' as well as any appenders configured for the root logger. If you want to add more than one appender to the logger, then add them to the same level declaration:

    error myAppender:      "griffon.app.controller.BookController",
          myFileAppender:  ["griffon.app.controller.BookController", "griffon.app.service.BookService"],
          rollingFile:     "griffon.app.controller.BookController"

The above example also shows how you can configure more than one logger at a time for a given appender (`myFileAppender`) by using a list.

Be aware that you can only configure a single level for a logger, so if you tried this code:

    error myAppender:      "griffon.app.controller.BookController"
    debug myFileAppender:  "griffon.app.controller.BookController"
    fatal rollingFile:     "griffon.app.controller.BookController"

you'd find that only 'fatal' level messages get logged for 'griffon.app.controller.BookController'. That's because the last level declared for a given logger wins. What you probably want to do is limit what level of messages an appender writes.

Let's say an appender is attached to a logger configured with the 'all' level. That will give us a lot of logging information that may be fine in a file, but makes working at the console difficult. So, we configure the console appender to only write out messages at 'info' level or above:

    log4j = {
        appenders {
            console name: "stdout", threshold: org.apache.log4j.Level.INFO
        }
    }

The key here is the `threshold` argument which determines the cut-off for log messages. This argument is available for all appenders, but do note that you currently have to specify a `Level` instance - a string such as "info" will not work.

### Custom Layouts

By default the Log4j DSL assumes that you want to use a PatternLayout. However, there are other layouts available including:

- `xml` - Create an XML log file
- `html` - Creates an HTML log file
- `simple` - A simple textual log
- `pattern` - A Pattern layout

You can specify custom patterns to an appender using the `layout` setting:

    log4j = {
        appenders {
            console name: "customAppender", layout: pattern(conversionPattern: "%c{2} %m%n")
        }
    }

This also works for the built-in appender "stdout", which logs to the console:

    log4j = {
        appenders {
            console name: "stdout", layout: pattern(conversionPattern: "%c{2} %m%n")
        }
    }

### Environment-specific configuration

Since the logging configuration is inside `Config.groovy`, you can of course put it inside an environment-specific block. However, there is a problem with this approach: you have to provide the full logging configuration each time you define the `log4j` setting. In other words, you cannot selectively override parts of the configuration - it's all or nothing.

To get round this, the logging DSL provides its own environment blocks that you can put anywhere in the configuration:

    log4j = {
        appenders {
            console name: "stdout", layout: pattern(conversionPattern: "%c{2} %m%n")        environments {
                production {
                    rollingFile name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log"
                }
            }
        }    root {
            //…
        }    // other shared config
        info "griffon.app.controller"    environments {
            production {
                // Override previous setting for 'griffon.app.controller'
                error "griffon.app.controller"
            }
        }
    }

The one place you can't put an environment block is inside the `root` definition, but you can put the `root` definition inside an environment block.

### Full stacktraces

When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Griffon filters these typically irrelevant details and restricts traces to non-core Griffon/Groovy class packages.

When this happens, the full trace is always logged to the `StackTrace` logger, which by default writes its output to a file called `stacktrace.log`. As with other loggers though, you can change its behaviour in the configuration. For example if you prefer full stack traces to go to the console, add this entry:

    error stdout: "StackTrace"

This won't stop Griffon from attempting to create the stacktrace.log file - it just redirects where stack traces are written to. An alternative approach is to change the location of the 'stacktrace' appender's file:

    log4j = {
        appenders {
            rollingFile name: "stacktrace", maxFileSize: 1024, file: "/var/tmp/logs/myApp-stacktrace.log"
        }
    }

or, if you don't want to the 'stacktrace' appender at all, configure it as a 'null' appender:

    log4j = {
        appenders {
            'null' name: "stacktrace"
        }
    }

You can of course combine this with attaching the 'stdout' appender to the 'StackTrace' logger if you want all the output in the console.

Finally, you can completely disable stacktrace filtering by setting the `griffon.full.stacktrace` VM property to `true`:

    griffon -Dgriffon.full.stacktrace=true run-app

### Logger inheritance

Earlier, we mentioned that all loggers inherit from the root logger and that loggers are hierarchical based on '.'-separated terms. What this means is that unless you override a parent setting, a logger retains the level and the appenders configured for that parent. So with this configuration:

    log4j = {
        appenders {
            file name:'file', file:'/var/logs/mylog.log'
        }
        root {
            debug 'stdout', 'file'
        }
    }

all loggers in the application will have a level of 'debug' and will log to both the 'stdout' and 'file' appenders. What if you only want to log to 'stdout' for a particular logger? In that case, you need to change the 'additivity' for a logger.

Additivity simply determines whether a logger inherits the configuration from its parent. If additivity is false, then its not inherited. The default for all loggers is true, i.e. they inherit the configuration. So how do you change this setting? Here's an example:

    log4j = {
        appenders {
            …
        }
        root {
            …
        }    info additivity: false
             stdout: ["griffon.app.controller.BookController", "griffon.app.service.BookService"]
    }

So when you specify a log level, add an 'additivity' named argument. Note that you when you specify the additivity, you must configure the loggers for a named appender. The following syntax will not work:

    info additivity: false, "griffon.app.controller.BookController", "griffon.app.service.BookService"

## 3.2 Environments

#### Per Environment Configuration

Griffon supports the concept of per environment configuration. The `BuildConfig.groovy` file within the `griffon-app/conf` directory can take advantage of per environment configuration using the syntax provided by ConfigSlurper . As an example consider the following default packaging definitions provided by Griffon:

    environments {
        development {
            signingkey {
                params {
                    sigfile = 'GRIFFON'
                    keystore = "${basedir}/griffon-app/conf/keys/devKeystore"
                    alias = 'development'
                    storepass = 'BadStorePassword'
                    keypass   = 'BadKeyPassword'
                    lazy      = true // only sign when unsigned
                }
            }    }
        test {
            griffon {
                jars {
                    sign = false
                    pack = false
                }
            }
        }
        production {
            signingkey {
                params {
                    sigfile = 'GRIFFON'
                    keystore = 'CHANGE ME'
                    alias = 'CHANGE ME'
                    lazy = false // sign, regardless of existing signatures
                }
            }        griffon {
                jars {
                    sign = true
                    pack = true
                    destDir = "${basedir}/staging"
                }
                webstart {
                    codebase = 'CHANGE ME'
                }
            }
        }
    }griffon {
        jars {
            sign = false
            pack = false
            destDir = "${basedir}/staging"
            jarName = "${appName}.jar"
        }
    }

Notice how the common configuration is provided at the bottom level (it actually can be placed before the `environments` block too), the `environments` block specifies per environment settings for the `jars` property.

#### Packaging and Running for Different Environments

Griffon' command line has built in capabilities to execute any command within the context of a specific environment. The format is:

    griffon [environment] [command name]

In addition, there are 3 preset environments known to Griffon: `dev`, `prod`, and `test` for `development`, `production` and `test`. For example to package an application for the `development` (avoiding jar signing by default) environment you could do:

    griffon dev package

If you have other environments that you need to target you can pass a `griffon.env` variable to any command:

    griffon -Dgriffon.env=UAT run-app

#### Programmatic Environment Detection

Within your code, such as in a Gant script or a bootstrap class you can detect the environment using the Environment class:

    import griffon.util.Environment...switch(Environment.current) {
        case Environment.DEVELOPMENT:
            configureForDevelopment()
            break
        case Environment.PRODUCTION:
            configureForProduction()
        break
    }

#### Generic Per Environment Execution

You can use the `griffon.util.Environment` class to execute your own environment specific logic:

    Environment.executeForCurrentEnvironment {
        production {
            // do something in production
        }
        development {
            // do something only in development
        }
    }

## 3.3 Versioning

#### Versioning Basics

Griffon has built in support for application versioning. When you first create an application with the create-app command the version of the application is set to `0.1`. The version is stored in the application meta data file called `application.properties` in the root of the project.

To change the version of your application you can run the set-version command:

    griffon set-version 0.2

The version is used in various commands including the package command which will append the application version to the end of the created distribution zip files.

#### Detecting Versions at Runtime

You can detect the application version using Griffon' support for application metadata using the app class. For example within controllers there is an implicit app variable that can be used:

    def version = app.metadata['app.version']

If it is the version of Griffon you need you can use:

    def griffonVersion = app.metadata['app.griffon.version']

## 3.4 Dependency Resolution

In order to control how JAR dependencies are resolved Griffon features (since version 0.9) a dependency resolution DSL that allows you to control how dependencies for applications and plugins are resolved.

Inside the `griffon-app/conf/BuildConfig.groovy` file you can specify a `griffon.project.dependency.resolution` property that configures how dependencies are resolved:

    griffon.project.dependency.resolution = {
       // config here
    }

The default configuration looks like the following:

    griffon.project.dependency.resolution = {
        // inherit Griffon' default dependencies
        inherits("global") {
        }
        log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
        repositories {
            griffonHome()        // uncomment the below to enable remote dependency resolution
            // from public Maven repositories
            //mavenLocal()
            //mavenCentral()
            //mavenRepo "http://snapshots.repository.codehaus.org"
            //mavenRepo "http://repository.codehaus.org"
            //mavenRepo "http://download.java.net/maven/2/"
            //mavenRepo "http://repository.jboss.com/maven2/"
        }
        dependencies {
            // specify dependencies here under either 'build', 'compile', 'runtime' or 'test' scopes eg.
            // runtime 'mysql:mysql-connector-java:5.1.5'
        }
    }

The details of the above will be explained in the next few sections.

## 3.4.1 Configurations and Dependencies

Griffon features 5 dependency resolution configurations (or 'scopes') which you can take advantage of:

- `build`: Dependencies for the build system only
- `compile`: Dependencies for the compile step
- `runtime`: Dependencies needed at runtime but not for compilation (see above)
- `test`: Dependencies needed for testing but not at runtime (see above)

Within the `dependencies` block you can specify a dependency that falls into one of these configurations by calling the equivalent method. For example if your application requires the MySQL driver to function at `runtime` you can specify as such:

    runtime 'com.mysql:mysql-connector-java:5.1.5'

The above uses the string syntax which is `group:name:version`. You can also use a map-based syntax:

    runtime group:'com.mysql', name:'mysql-connector-java', version:'5.1.5'

Multiple dependencies can be specified by passing multiple arguments:

    runtime 'com.mysql:mysql-connector-java:5.1.5',
            'commons-lang:commons-lang:2.6'// Orruntime(
        [group: 'com.mysql',     name: 'mysql-connector-java', version: '5.1.5'],
        [group: 'commnons-lang', name: 'commons-lang',         version: '2.6']
    )

You may specify a classifier too

    runtime 'net.sf.json-lib:json-lib:2.4:jdk15'// Orruntime group: 'net.sf.json-lib' name: 'json-lib', version: '2.4', classifier: 'jdk15'

## 3.4.2 Dependency Repositories

#### Remote Repositories

Griffon, when installed, does not use any remote public repositories. There is a default `griffonHome()` repository that will locate the JAR files Griffon needs from your Griffon installation. If you want to take advantage of a public repository you need to specify as such inside the `repositories` block:

    repositories {
        mavenCentral()
    }

In this case the default public Maven repository is specified. To use the SpringSource Enterprise Bundle Repository you can use the `ebr()` method:

    repositories {
        ebr()
    }

You can also specify a specific Maven repository to use by URL:

    repositories {
        mavenRepo "http://repository.codehaus.org"
    }

#### Local Resolvers

If you do not wish to use a public Maven repository you can specify a flat file repository:

    repositories {
        flatDir name:'myRepo', dirs:'/path/to/repo'
    }

#### Custom Resolvers

If all else fails since Griffon builds on Apache Ivy you can specify an Ivy resolver:

    repositories {
        resolver new URLResolver(...)
    }

#### Authentication

If your repository requires some form of authentication you can specify as such using a `credentials` block:

    credentials {
        realm = ".."
        host = "localhost"
        username = "myuser"
        password = "mypass"
    }

The above can also be placed in your `USER_HOME/.griffon/settings.groovy` file using the `griffon.project.ivy.authentication` setting:

    griffon.project.ivy.authentication = {
        credentials {
            realm = ".."
            host = "localhost"
            username = "myuser"
            password = "mypass"
        }
    }

## 3.4.3 Debugging Resolution

If you are having trouble getting a dependency to resolve you can enable more verbose debugging from the underlying engine using the `log` method:

    // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
    log "warn"

## 3.4.4 Inherited Dependencies

By default every Griffon application inherits a bunch of framework dependencies. This is done through the line:

    inherits "global"

Inside the `BuildConfig.groovy` file. If you wish exclude certain inherited dependencies then you can do so using the `excludes` method:

    inherits("global") {
        excludes "oscache", "ehcache"
    }

## 3.4.5 Dependency Reports

As mentioned in the previous section a Griffon application consists of dependencies inherited from the framework, the plugins installed and the application dependencies itself.

To obtain a report of an application's dependencies you can run the dependency-report command:

    griffon dependency-report

This will output a report to the `target/dependency-report` directory by default. You can specify which configuration (scope) you want a report for by passing an argument containing the configuration name:

    griffon dependency-report runtime

## 3.4.6 Plugin JAR Dependencies

#### Specifying Plugin JAR dependencies

The way in which you specify dependencies for a plugin is identical to how you specify dependencies in an application. When a plugin is installed into an application the application automatically inherits the dependencies of the plugin.

If you want to define a dependency that is resolved for use with the plugin but not exported to the application then you can set the `exported` property of the dependency:

    compile('org.hibernate:hibernate-core:3.3.1.GA') {
        exported = false
    }

In this can the `hibernate-core` dependency will be available only to the plugin and not resolved as an application dependency.

#### Overriding Plugin JAR Dependencies in Your Application

If a plugin is using a JAR which conflicts with another plugin, or an application dependency then you can override how a plugin resolves its dependencies inside an application using exclusions. For example:

    plugins {
        compile("org.codehaus.griffon.plugins:miglayout:0.3" ) {
            excludes "miglayout"
        }
    }dependencies {
        String miglayoutVersion = '4.2'
        compile "com.miglayout:miglayout-core:$miglayoutVersion",
                "com.miglayout:miglayout-swing:$miglayoutVersion"
    }

In this case the application explicitly declares a dependency on the "miglayout" plugin and specifies an exclusion using the `excludes` method, effectively excluding the miglayout library as a dependency.

## 3.4.7 Plugin Dependencies

As of Griffon 0.9 you can declaratively specify dependencies on plugins rather than using the install-plugin command:

    plugins {
        runtime ':artifacts:0.2'
    }

If you don't specify a group id the default plugin group id of `org.griffon.plugins` is used. You can specify to use the latest version of a particular plugin by using "latest.integration" as the version number:

    plugins {
        runtime ':artifacts:latest.integration'
    }

#### Integration vs. Release

The "latest.integration" version label will also include resolving snapshot versions. If you don't want to include snapshot versions then you can use the "latest.release" label:

    plugins {
        runtime ':artifacts:latest.release'
    }

> The "latest.release" label only works with Maven compatible repositories. If you have a regular SVN-based Griffon repository then you should use "latest.integration".

And of course if you are using a Maven repository with an alternative group id you can specify a group id:

    plugins {
        runtime 'mycompany:artifacts:latest.integration'
    }

#### Plugin Exclusions

You can control how plugins transitively resolves both plugin and JAR dependencies using exclusions. For example:

    plugins {
        runtime( ':weceem:0.8' ) {
            excludes "searchable"
        }
    }

Here we have defined a dependency on the "weceem" plugin which transitively depends on the "searchable" plugin. By using the `excludes` method you can tell Griffon not to transitively install the searchable plugin. You can combine this technique to specify an alternative version of a plugin:

    plugins {
        runtime( ':weceem:0.8' ) {
            excludes "searchable" // excludes most recent version
        }
        runtime ':searchable:0.5.4' // specifies a fixed searchable version
    }

You can also completely disable transitive plugin installs, in which case no transitive dependencies will be resolved:

    plugins {
        runtime( ':weceem:0.8' ) {
            transitive = false
        }
        runtime ':searchable:0.5.4' // specifies a fixed searchable version
    }

## 3.5 Project Documentation

Since Griffon 0.9, the documentation engine that powers the creation of this documentation is available to your Griffon projects.

The documentation engine uses a variation on the Textile syntax to automatically create project documentation with smart linking, formatting etc.

#### Creating project documentation

To use the engine you need to follow a few conventions. Firstly you need to create a `src/docs/guide` directory and then have numbered text files using the `gdoc` format. For example:

    + src/docs/guide/1. Introduction.gdoc
    + src/docs/guide/2. Getting Started.gdoc

The title of each chapter is taken from the file name. The order is dictated by the numerical value at the beginning of the file name.

#### Creating reference items

Reference items appear in the left menu on the documentation and are useful for quick reference documentation. Each reference item belongs to a category and a category is a directory located in the `src/docs/ref` directory. For example say you defined a new method called `renderPDF`, that belongs to a category called `Controllers` this can be done by creating a gdoc text file at the following location:

    + src/ref/Controllers/renderPDF.gdoc

#### Configuring Output Properties

There are various properties you can set within your `griffon-app/conf/BuildConfig.groovy` file that customize the output of the documentation such as:

- griffon.doc.authors - The authors of the documentation
- griffon.doc.license - The license of the software
- griffon.doc.copyright - The copyright message to display
- griffon.doc.footer - The footer to use

Other properties such as the name of the documentation and the version are pulled from your project itself.

#### Generating Documentation

Once you have created some documentation (refer to the syntax guide in the next chapter) you can generate an HTML version of the documentation using the command:

    griffon doc

This command will output an `docs/manual/index.html` which can be opened to view your documentation.

#### Documentation Syntax

As mentioned the syntax is largely similar to Textile or Confluence style wiki markup. The following sections walk you through the syntax basics.

##### Basic Formatting

Monospace: `monospace`

    @monospace@

Italic: italic

    _italic_

Bold: bold

    *bold*

Image:

    !http://dist.codehaus.org/griffon/media/griffon.png!

##### Linking

There are several ways to create links with the documentation generator. A basic external link can either be defined using confluence or textile style markup:

    [Griffon|http://griffon.codehaus.org/] or "Griffon":http://griffon.codehaus.org/

For links to other sections inside the user guide you can use the `guide:` prefix:

    [Intro|guide:1. Introduction]

The documentation engine will warn you if any links to sections in your guide break. Sometimes though it is preferable not to hard code the actual names of guide sections since you may move them around. To get around this you can create an alias inside `griffon-app/conf/BuildConfig.groovy`:

    griffon.doc.alias.intro="1. Introduction"

And then the link becomes:

    [Intro|guide:intro]

This is useful since if you linked the to "1. Introduction" chapter many times you would have to change all of those links.

To link to reference items you can use a special syntax:

    [controllers|renderPDF]

In this case the category of the reference item is on the left hand side of the | and the name of the reference item on the right.

Finally, to link to external APIs you can use the `api:` prefix. For example:

    [String|api:java.lang.String]

The documentation engine will automatically create the appropriate javadoc link in this case. If you want to add additional APIs to the engine you can configure them in `griffon-app/conf/BuildConfig.groovy`. For example:

    griffon.doc.api.org.hibernate="http://docs.jboss.org/hibernate/stable/core/api"

The above example configures classes within the `org.hibernate` package to link to the Hibernate website's API docs.

##### Lists and Headings

Headings can be created by specifying the letter 'h' followed by a number and then a dot:

    h3.<space>Heading3
    h4.<space>Heading4

Unordered lists are defined with the use of the * character:

    * item 1
    ** subitem 1
    ** subitem 2
    * item 2

Numbered lists can be defined with the # character:

    # item 1

Tables can be created using the `table` macro:

Name | Number
--- | ---
Albert | 46
Wilma | 1348
James | 12

    {table}
     *Name* | *Number*
     Albert | 46
     Wilma | 1348
     James | 12
    {table}

##### Code and Notes

You can define code blocks with the `code` macro:

    class Book {
        String title
    }

    {code}
    class Book {
        String title
    }
    {code}

The example above provides syntax highlighting for Java and Groovy code, but you can also highlight XML markup:

    <hello>world</hello>

    {code:xml}
    <hello>world</hello>
    {code}

There are also a couple of macros for displaying notes and warnings:

Note:

> This is a note!

    {note}
    This is a note!
    {note}

Warning:

> This is a warning!

    {warning}
    This is a warning!
    {warning}