18.1 Creating and Installing Plugins

Creating Plugins

Creating a Grails plugin is a simple matter of running the command:

  1. grails create-plugin <<PLUGIN NAME>>

This will create a plugin project for the name you specify. For example running grails create-plugin example would create a new plugin project called example.

In Grails 3.0 you should consider whether the plugin you create requires a web environment or whether the plugin can be used with other profiles. If your plugin does not require a web environment then use the "plugin" profile instead of the "web-plugin" profile:

  1. grails create-plugin <<PLUGIN NAME>> --profile=plugin

Make sure the plugin name does not contain more than one capital letter in a row, or it won’t work. Camel case is fine, though.

Being a regular Grails project has a number of benefits in that you can immediately test your plugin by running (if the plugin targets the "web" profile):

  1. grails run-app
Plugin projects don’t provide an index.gsp by default since most plugins don’t need it. So, if you try to view the plugin running in a browser right after creating it, you will receive a page not found error. You can easily create a grails-app/views/index.gsp for your plugin if you’d like.

The structure of a Grails plugin is very nearly the same as a Grails application project’s except that in the src/main/groovy directory under the plugin package structure you will find a plugin descriptor class (a class that ends in "GrailsPlugin"). For example:

  1. import grails.plugins.*
  2. class ExampleGrailsPlugin extends Plugin {
  3. ...
  4. }

All plugins must have this class under the src/main/groovy directory, otherwise they are not regarded as a plugin. The plugin class defines metadata about the plugin, and optionally various hooks into plugin extension points (covered shortly).

You can also provide additional information about your plugin using several special properties:

  • title - short one-sentence description of your plugin

  • grailsVersion - The version range of Grails that the plugin supports. eg. "1.2 > *" (indicating 1.2 or higher)

  • author - plugin author’s name

  • authorEmail - plugin author’s contact e-mail

  • developers - Any additional developers beyond the author specified above.

  • description - full multi-line description of plugin’s features

  • documentation - URL of the plugin’s documentation

  • license - License of the plugin

  • issueManagement - Issue Tracker of the plugin

  • scm - Source code management location of the plugin

Here is a slimmed down example from the Quartz Grails plugin:

  1. package quartz
  2. @Slf4j
  3. class QuartzGrailsPlugin extends Plugin {
  4. // the version or versions of Grails the plugin is designed for
  5. def grailsVersion = "3.0.0.BUILD-SNAPSHOT > *"
  6. // resources that are excluded from plugin packaging
  7. def pluginExcludes = [
  8. "grails-app/views/error.gsp"
  9. ]
  10. def title = "Quartz" // Headline display name of the plugin
  11. def author = "Jeff Brown"
  12. def authorEmail = "[email protected]"
  13. def description = '''\
  14. Adds Quartz job scheduling features
  15. '''
  16. def profiles = ['web']
  17. List loadAfter = ['hibernate3', 'hibernate4', 'hibernate5', 'services']
  18. def documentation = "http://grails.org/plugin/quartz"
  19. def license = "APACHE"
  20. def issueManagement = [ system: "Github Issues", url: "http://github.com/grails3-plugins/quartz/issues" ]
  21. def developers = [
  22. [ name: "Joe Dev", email: "[email protected]" ]
  23. ]
  24. def scm = [ url: "https://github.com/grails3-plugins/quartz/" ]
  25. Closure doWithSpring()......

Installing Local Plugins

To make your plugin available for use in a Grails application run the install command:

  1. grails install

This will install the plugin into your local Maven cache. Then to use the plugin within an application declare a dependency on the plugin in your build.gradle file:

  1. compile "org.grails.plugins:quartz:0.1"
In Grails 2.x plugins were packaged as ZIP files, however in Grails 3.x plugins are simple JAR files that can be added to the classpath of the IDE.

Plugins and Multi-Project Builds

If you wish to setup a plugin as part of a multi project build then follow these steps.

Step 1: Create the application and the plugin

Using the grails command create an application and a plugin:

  1. $ grails create-app myapp
  2. $ grails create-plugin myplugin

Step 2: Create a settings.gradle file

In the same directory create a settings.gradle file with the following contents:

  1. include "myapp", "myplugin"

The directory structure should be as follows:

  1. PROJECT_DIR
  2. - settings.gradle
  3. - myapp
  4. - build.gradle
  5. - myplugin
  6. - build.gradle

Step 3: Declare a project dependency on the plugin

Within the build.gradle of the application declare a dependency on the plugin within the plugins block:

  1. grails {
  2. plugins {
  3. compile project(':myplugin')
  4. }
  5. }
You can also declare the dependency within the dependencies block, however you will not get subproject reloading if you do this!

Step 4: Run the application

Now run the application using the grails run-app command from the root of the application directory, you can use the verbose flag to see the Gradle output:

  1. $ cd myapp
  2. $ grails run-app -verbose

You will notice from the Gradle output that plugins sources are built and placed on the classpath of your application:

  1. :myplugin:compileAstJava UP-TO-DATE
  2. :myplugin:compileAstGroovy UP-TO-DATE
  3. :myplugin:processAstResources UP-TO-DATE
  4. :myplugin:astClasses UP-TO-DATE
  5. :myplugin:compileJava UP-TO-DATE
  6. :myplugin:configScript UP-TO-DATE
  7. :myplugin:compileGroovy
  8. :myplugin:copyAssets UP-TO-DATE
  9. :myplugin:copyCommands UP-TO-DATE
  10. :myplugin:copyTemplates UP-TO-DATE
  11. :myplugin:processResources
  12. :myapp:compileJava UP-TO-DATE
  13. :myapp:compileGroovy
  14. :myapp:processResources UP-TO-DATE
  15. :myapp:classes
  16. :myapp:findMainClass
  17. :myapp:bootRun
  18. Grails application running at http://localhost:8080 in environment: development

Notes on excluded Artefacts

Although the create-plugin command creates certain files for you so that the plugin can be run as a Grails application, not all of these files are included when packaging a plugin. The following is a list of artefacts created, but not included by package-plugin:

  • grails-app/build.gradle (although it is used to generate dependencies.groovy)

  • grails-app/conf/application.yml (renamed to plugin.yml)

  • grails-app/conf/spring/resources.groovy

  • grails-app/conf/logback.groovy

  • Everything within /src/test/\

  • SCM management files within \/.svn/\ and \/CVS/\

Customizing the plugin contents

When developing a plugin you may create test classes and sources that are used during the development and testing of the plugin but should not be exported to the application.

To exclude test sources you need to modify the pluginExcludes property of the plugin descriptor AND exclude the resources inside your build.gradle file. For example say you have some classes under the com.demo package that are in your plugin source tree but should not be packaged in the application. In your plugin descriptor you should exclude these:

  1. // resources that should be loaded by the plugin once installed in the application
  2. def pluginExcludes = [
  3. '**/com/demo/**'
  4. ]

And in your build.gradle you should exclude the compiled classes from the JAR file:

  1. jar {
  2. exclude "com/demo/**/**"
  3. }

Inline Plugins in Grails 3.0

In Grails 2.x it was possible to specify inline plugins in BuildConfig, in Grails 3.x this functionality has been replaced by Gradle’s multi-project build feature.

To set up a multi project build create an appliation and a plugin in a parent directory:

  1. $ grails create-app myapp
  2. $ grails create-plugin myplugin

Then create a settings.gradle file in the parent directory specifying the location of your application and plugin:

  1. include 'myapp', 'myplugin'

Finally add a dependency in your application’s build.gradle on the plugin:

  1. compile project(':myplugin')

Using this technique you have achieved the equivalent of inline plugins from Grails 2.x.