6 Application Profiles 6.0.0

(Quick Reference) # 6 Application Profiles Version: 6.0.0 ## Table of Contents # 6 Application Profiles When you create a Grails application with the create-app command by default the "web" profile is used:
    grails create-app myapp
You can specify a different profile with the profile argument:
    grails create-app myapp --profile=rest-api
Profiles encapsulate the project commands, templates and plugins that are designed to work for a given profile. The source for the profiles can be found on Github, whilst the profiles themselves are published as JAR files to the Grails central repository. To find out what profiles are available use the list-profiles command:
    $ grails list-profiles
For more information on a particular profile use the profile-info command:
    $ grails profile-info rest-api
| Commands such as `profile-info` or `list-profiles` are not available when you invoke the Grails CLI inside a grails project.
#### Profile Repositories By default Grails will resolve profiles from the Grails central repository. However, you can override what repositories will be searched by specifying repositories in the `USER_HOME/.grails/settings.groovy` file. If you want profiles to be resolved with a custom repository in addition to the Grails central repository, you must specify Grails central in the file as well:
    grails {
      profiles {
        repositories {
          myRepo {
            url = "http://foo.com/repo"
            snapshotsEnabled = true
          }
          grailsCentral {
            url = "https://repo.grails.org/grails/core"
            snapshotsEnabled = true
          }
        }
      }
    }
| Grails uses Aether to resolve profiles, as a Gradle instance is not yet available when the `create-app` command is executed. This means that you can also define repositories and more advanced configuration (proxies, authentication etc.) in your `USER_HOME/.m2/settings.xml` file if you wish.
It is also possible to store simple credentials for profile repositories directly in the `USER_HOME/.grails/settings.groovy` file.
    grails {
      profiles {
        repositories {
          myRepo {
            url = "http://foo.com/repo"
            snapshotsEnabled = true
            username = "user"
            password = "pass"
          }
          ...
        }
      }
    }
#### Profile Defaults To create an application that uses a custom profile, you must specify the full artifact.
    $ grails create-app myapp --profile=com.mycompany.grails.profiles:myprofile:1.0.0
To make this process easier, you can define defaults for a given profile in the `USER_HOME/.grails/settings.groovy` file.
    grails {
      profiles {
        myprofile {
          groupId = "com.mycompany.grails.profiles"
          version = "1.0.0"
        }
        repositories {
          ...
        }
      }
    }
With the default values specified, the command to create an application using that profile becomes:
    $ grails create-app myapp --profile=myprofile
## 6.1 Creating Profiles The idea behind creating a new profile is that you can setup a default set of commands and plugins that are tailored to a particular technology or organisation. To create a new profile you can use the create-profile command which will create a new empty profile that extends the base profile:
    $ grails create-profile mycompany
The above command will create a new profile in the "mycompany" directory where the command is executed. If you start interactive mode within the directory you will get a set of commands for creating profiles:
    $ cd mycompany
    $ grails
    | Enter a command name to run. Use TAB for completion:
    grails>

    create-command      create-creator-command      create-feature      create-generator-command    create-gradle-command   create-template
The commands are as follows: `create-command` - creates a new command that will be available from the Grails CLI when the profile is used `create-creator-command` - creates a command available to the CLI that renders a template (Example: create-controller) `create-generator-command` - creates a command available to the CLI that renders a template based on a domain class (Example: generate-controller) `create-feature` - creates a feature that can be used with this profile `create-gradle-command` - creates a CLI command that can invoke gradle `create-template` - creates a template that can be rendered by a command To customize the dependencies for your profile you can specify additional dependencies in `profile.yml`. Below is an example `profile.yml` file:
    features:
        defaults:
            - hibernate
            - asset-pipeline
    build:
        plugins:
            - org.grails.grails-web
        excludes:
            - org.grails.grails-core
    dependencies:
        - scope: compile
          coords: "org.mycompany:myplugin:1.0.1"
        - scope: testCompile
          coords: org.spockframework:spock-core
          excludes:
            - group: org.codehaus.groovy
              module: groovy-all
With the above configuration in place you can publish the profile to your local repository with `gradle install`:
    $ gradle install
Your profile is now usable with the `create-app` command:
    $ grails create-app myapp --profile mycompany
With the above command the application will be created with the "mycompany" profile which includes an additional dependency on the "myplugin" plugin and also includes the "hibernate" and "asset-pipeline" features (more on features later). Note that if you customize the dependency coordinates of the profile (group, version etc.) then you may need to use the fully qualified coordinates to create an application:
    $ grails create-app myapp --profile com.mycompany:mycompany:1.0.1
## 6.2 Profile Inheritance One profile can extend one or many different parent profiles. To define profile inheritance you can modify the `build.gradle` of a profile and define the profile dependences. For example typically you want to extend the `base` profile:
    dependencies {
        runtime "org.grails.profiles:base:$baseProfileVersion"
    }
By inheriting from a parent profile you get the following benefits: When the create-app command is executed the parent profile’s skeleton is copied first Dependencies and `build.gradle` is merged from the parent(s) The `application.yml` file is merged from the parent(s) CLI commands from the parent profile are inherited Features from the parent profile are inherited To define the order of inheritance ensure that your dependencies are declared in the correct order. For example:
    dependencies {
        runtime "org.grails.profiles:plugin:$baseProfileVersion"
        runtime "org.grails.profiles:web:$baseProfileVersion"
    }
In the above snippet the skeleton from the "plugin" profile is copied first, followed by the "web" profile. In addition, the "web" profile overrides commands from the "plugin" profile, whilst if the dependency order was reversed the "plugin" profile would override the "web" profile. ## 6.3 Publishing Profiles #### Publishing Profiles to the Grails Central Repository Any profile created with the create-profile command already comes configured with a `grails-profile-publish` plugin defined in `build.gradle`:
    apply plugin: "org.grails.grails-profile-publish"
To publish a profile using this plugin to the Grails central repository first upload the source to Github (closed source profiles will not be accepted). Then register for an account on Bintray and configure your keys as follows in the profile’s `build.gradle` file:
    grailsPublish {
      user = 'YOUR USERNAME'
      key = 'YOUR KEY'
      githubSlug = 'your-repo/your-profile'
      license = 'Apache-2.0'
    }
| The `githubSlug` argument should point to the path to your Github repository. For example if your repository is located at https://github.com/foo/bar then your `githubSlug` is `foo/bar`
With this in place you can run `gradle publishProfile` to publish your profile:
    $ gradle publishProfile
The profile will be uploaded to Bintray. You can then go the Grails profiles repository and request to have your profile included by clicking "Include My Package" button on Bintray’s interface (you must be logged in to see this). #### Publishing Profiles to an Internal Repository The aforementioned `grails-profile-publish` plugin configures Gradle’s Maven Publish plugin. In order to publish to an internal repository all you need to do is define the repository in `build.gradle`. For example:
    publishing {
        repositories {
            maven {
                credentials {
                    username "foo"
                    password "bar"
                }

                url "http://foo.com/repo"
            }
        }
    }
Once configured you can publish your plugin with `gradle publish`:
    $ gradle publish
## 6.4 Understanding Profiles A profile is a simple directory that contains a `profile.yml` file and directories containing the "commands", "skeleton" and "templates" defined by the profile. Example:
    /web
        commands/
            create-controller.yml
            run-app.groovy
            ...
        features/
            asset-pipeline/
                skeleton
                feature.yml
        skeleton/
            grails-app/
                controllers/
                ...
            build.gradle
        templates/
            artifacts/
                Controller.groovy
        profile.yml
The above example is a snippet of structure of the 'web' profile. The `profile.yml` file is used to describe the profile and control how the build is configured. #### Understanding the profile.yml descriptor The `profile.yml` can contain the following child elements. #### 1) repositories A list of Maven repositories to include in the generated build. Example:
    repositories:
        - "https://repo.grails.org/grails/core"
#### 2) build.repositories A list of Maven repositories to include in the buildscript section of the generated build. Example:
    build:
        repositories:
            - "https://repo.grails.org/grails/core"
#### 3) build.plugins A list of Gradle plugins to configure in the generated build. Example:
    build:
        plugins:
            - eclipse
            - idea
            - org.grails.grails-core
#### 4) build.excludes A list of Gradle plugins to exclude from being inherited from the parent profile:
    build:
        excludes:
            - org.grails.grails-core
#### 5) dependencies A map of scopes and dependencies to configure. The `excludes` scope can be used to exclude from the parent profile. Example:
    dependencies:
        - scope: excludes
          coords: "org.grails:hibernate:*"
        - scope: build
          coords: "org.grails:grails-gradle-plugin:$grailsVersion"
        - scope: compile
          coords: "org.springframework.boot:spring-boot-starter-logging"
        - scope: compile
          coords: "org.springframework.boot:spring-boot-autoconfigure"
##### Excluding Transitive Dependencies To exclude transitive dependencies, define `excludes` key with a List of transitive dependencies Map of the dependency group, module, classifier, and `extension` as:
    dependencies:
        - scope: testCompile
          coords: org.spockframework:spock-core
          excludes:
            - group: org.codehaus.groovy
              module: groovy-all
#### 6) features.defaults A default list of features to use if no explicit features are specified.
    features:
        defaults:
            - hibernate
            - asset-pipeline
#### 7) skeleton.excludes A list of files to exclude from parent profile’s skeletons (supports wildcards).
    skeleton:
        excludes:
            - gradlew
            - gradlew.bat
            - gradle/
#### 8) skeleton.parent.target The target folder that parent profile’s skeleton should be copied into. This can be used to create multi-project builds.
    skeleton:
        parent:
            target: app
#### 9) skeleton.binaryExtensions Which file extensions should be copied from the profile as binary. Inherited and combined from parent profiles.
    skeleton:
        binaryExtensions: [exe, zip]
#### 10) skeleton.executable File patterns that should be marked as executable in the resulting application. Inherited and combined from parent profiles. The patterns are parsed with Ant.
    skeleton:
        executable:
          - "**/gradlew*"
          - "**/grailsw*"
#### 11) instructions Text to be displayed to the user after the application is created
    instructions: Here are some instructions
#### What happens when a profile is used? When the `create-app` command runs it takes the skeleton of the parent profiles and copies the skeletons into a new project structure. The `build.gradle` file is generated is result of obtaining all of the dependency information defined in the `profile.yml` files and produces the required dependencies. The command will also merge any `build.gradle` files defined within a profile and its parent profiles. The `grails-app/conf/application.yml` file is also merged into a single YAML file taking into account the profile and all of the parent profiles. ## 6.5 Creating Profile Commands A profile can define new commands that apply only to that profile using YAML or Groovy scripts. Below is an example of the create-controller command defined in YAML:
    description:
        - Creates a controller
        - usage: 'create-controller <<controller name>>'
        - completer: org.grails.cli.interactive.completers.DomainClassCompleter
        - argument: "Controller Name"
          description: "The name of the controller"
    steps:
     - command: render
       template: templates/artifacts/Controller.groovy
       destination: grails-app/controllers/`artifact.package.path`/`artifact.name`Controller.groovy
     - command: render
       template: templates/testing/Controller.groovy
       destination: src/test/groovy/`artifact.package.path`/`artifact.name`ControllerSpec.groovy
     - command: mkdir
       location: grails-app/views/`artifact.propertyName`
Commands defined in YAML must define one or many steps. Each step is a command in itself. The available step types are: `render` - To render a template to a given destination (as seen in the previous example) `mkdir` - To make a directory specified by the `location` parameter `execute` - To execute a command specified by the `class` parameter. Must be a class that implements the Command interface. `gradle` - To execute one or many Gradle tasks specified by the `tasks` parameter. For example to invoke a Gradle task, you can define the following YAML:
    description: Creates a WAR file for deployment to a container (like Tomcat)
    minArguments: 0
    usage: |
     war
    steps:
     - command: gradle
       tasks:
         - war
If you need more flexibility than what the declarative YAML approach provides you can create Groovy script commands. Each Command script is extends from the GroovyScriptCommand class and hence has all of the methods of that class available to it. The following is an example of the create-script command written in Groovy:
    description( "Creates a Grails script" ) {
      usage "grails create-script <<SCRIPT NAME>>"
      argument name:'Script Name', description:"The name of the script to create"
      flag name:'force', description:"Whether to overwrite existing files"
    }

    def scriptName = args[0]
    def model = model(scriptName)
    def overwrite = flag('force') ? true : false

    render  template: template('artifacts/Script.groovy'),
            destination: file("src/main/scripts/${model.lowerCaseName}.groovy"),
            model: model,
            overwrite: overwrite
For more information on creating CLI commands see the section on creating custom scripts in the Command Line section of the user guide. ## 6.6 Creating Profile Features A Profile feature is a shareable set of templates and dependencies that may span multiple profiles. Typically you create a base profile that has multiple features and child profiles that inherit from the parent and hence can use the features available from the parent. To create a feature use the `create-feature` command from the root directory of your profile:
    $ grails create-feature myfeature
This will create a `myfeature/feature.yml` file that looks like the following:
    description: Description of the feature
    # customize versions here
    # dependencies:
    #   - scope: compile
    #     coords: "org.grails.plugins:myplugin2:1.0"
    #
As a more concrete example. The following is the `feature.yml` file from the "asset-pipeline" feature:
    description: Adds Asset Pipeline to a Grails project
    build:
        plugins:
            - asset-pipeline
    dependencies:
        - scope: build
          coords: 'com.bertramlabs.plugins:asset-pipeline-gradle:2.5.0'
        - scope: runtime
          coords: "org.grails.plugins:asset-pipeline"
The structure of a feature is as follows:
    FEATURE_DIR
        feature.yml
        skeleton/
            grails-app/
                conf/
                    application.yml
            build.gradle
The contents of the skeleton get copied into the application tree, whilst the `application.yml` and `build.gradle` get merged with their respective counterparts in the profile by used. With the `feature.yml` you can define additional dependencies. This allows users to create applications with optional features. For example:
    $ grails create-app myapp --profile myprofile --features myfeature,hibernate
The above example will create a new application using your new feature and the "hibernate" feature. | Quick Reference (hide)