With Grails 3, the plugin development experience changes a little bit compared to that of Grails 2. In this talk, Álvaro (member of the Grails team at OCI, Grails committer and author of several plugins) will cover several topics to understand how plugins work in Grails 3, focusing on best practices.
The session is structured as a set of tips and tricks with code samples in the following areas: modularisation, build system, testing and publishing.
10. Keep clean
• Start with the plugin profile whenever
possible.
• Remove empty and/or unwanted files/
folders.
• Otherwise, the burtbeckwith bot will
send you a cleanup pull request!
12. The burtbeckwith bot
• Watches messy plugin repos and sends a PR
to clean them up.
• 14 pull requests in the last 3 months!
• Likely hundreds in the last years!
13. The minimal plugin
• Folder containing:
• build.gradle
• src/main/groovy with plugin descriptor.
• Empty grails-app folder.
14. The plugin descriptor
• A class inside src/main/groovy. Extends
grails.plugins.Plugin.
• Can override methods to define behaviour
in the plugin lifecycle.
• Syntax has changed a bit from Grails 2.
16. Plugin configuration
• A plugin can define:
• Configuration values for the host Grails app.
• One of plugin.yml or plugin.groovy.
• Configuration for running the plugin as an
application, to test it.
• application.yml / application.groovy.
17. Excluding content
• In the plugin descriptor:
• In build.gradle:
// resources that are excluded from plugin packaging
def pluginExcludes = [
'**/com/example/myplugin/tests/**'
]
jar {
exclude 'com/example/myplugin/tests/**/**'
}
18. Command Line extensions
• Use create-script for code generation
commands.
• Runnable with the Grails CLI.
• Use create-command for interacting with a
loaded Grails application.
• Runnable with the Grails CLI or as a Gradle task.
19. Scripts
• Base class:
org.grails.cli.profile.commands.script.GroovyScriptCommand
import org.grails.cli.interactive.completers.DomainClassCompleter
description( "Generates a controller that performs REST operations" ) {
usage "grails generate-resource-controller [DOMAIN CLASS]"
argument name:'Domain Class', description:"The name of the domain class", required:true
completer DomainClassCompleter
flag name:'force', description:"Whether to overwrite existing files"
}
if(args) {
generateController(*args)
generateViews(*args)
generateUnitTest(*args)
generateFunctionalTest(*args)
} else {
error "No domain class specified"
}
23. Modularisation
• If your plugin becomes to grow, you might
end up creating a monolith.
• You can modularise your plugins as you
would do with your apps.
31. Artifact publication
• Snapshots:
• Using the artifactory Gradle plugin.
• Published in OJO (oss.jfrog.org).
• Releases:
• Using the grails-plugin-publish Gradle plugin.
• Published in Bintray.
37. Plugin portals
• Once your packages are published in your
Bintray repo, go to https://
bintray.com/grails/plugins and click
on “Include my package”.
• Grails 3: http://grails.org/plugins.html
• Grails 2: http://grails.org/plugins
39. Testing with a profile
• You can create a profile and use it as a TCK
for your plugin:
• Create test apps from that profile.
• Apps come with a set of tests.
• Use features to test different configurations.
40. Profile descriptor
description: Creates a test app for Spring Security REST plugin
build:
excludes:
- org.grails.grails-core
dependencies:
compile:
- "org.grails.plugins:spring-security-rest:${pluginVersion}"
- "org.grails:grails-datastore-rest-client:5.0.0.RC3"
testCompile:
- "com.codeborne:phantomjsdriver:1.2.1"
- "org.seleniumhq.selenium:selenium-api:2.47.1"
- "org.seleniumhq.selenium:selenium-firefox-driver:2.47.1"
profile.yml.tmpl
43. Skeleton
• Put in the skeleton all your test files and
resources.
• You can use features to have different sets of
tests, resources and configuration.
• Define global configuration values in profile’s
root skeleton folder.
44. Test them all!
for feature in `ls ../spring-security-rest-testapp-profile/features/`
do
grails create-app -profile
org.grails.plugins:spring-security-rest-testapp-profile:$pluginVersion
-features $feature $feature && cd $feature && ./gradlew check && cd ..
done