SlideShare a Scribd company logo
Mastering Grails 3
Plugins
Álvaro Sánchez-Mariscal
Álvaro Sánchez-Mariscal
Software Engineer
Grails Development Team
sanchezmariscala@ociweb.com
Mastering Grails 3 Plugins - G3 Summit 2016
OCI is the new home of Grails
More at ociweb.com/grails
The Basics
Creating a Grails 3 plugin
$ grails create-plugin myWebPlugin
| Plugin created at /private/tmp/myWebPlugin
$ grails create-plugin myPlugin -profile plugin
| Plugin created at /private/tmp/myPlugin
Understanding profiles
• A profile defines:
• Project’s build.gradle.
• Commands: create-domain-class,
run-app, etc.
• Features: hibernate, json-views, etc.
• Skeleton: files and folders.
plugin vs. web-plugin
Trim your plugin!
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!
The burtbeckwith bot
The burtbeckwith bot
• Watches messy plugin repos and sends a PR
to clean them up.
• Dozens of pull requests in the last 3
months!
• Likely hundreds in the last years!
The minimal plugin
• Folder containing:
• build.gradle
• src/main/groovy with plugin descriptor.
• grails-app/init with an Application class.
• Everything else can be removed.
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.
Demo - Creating a
plugin
Plugin features
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.
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/**/**'

}
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.
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"

}
Commands (3.1)
import grails.dev.commands.ApplicationCommand

import grails.dev.commands.ExecutionContext



class MyCommand implements ApplicationCommand {



@Override

boolean handle(ExecutionContext ctx) {

def dataSource = applicationContext.getBean(DataSource)

//Run some SQL...



return true

}



}
Commands (3.2)
import grails.dev.commands.ApplicationCommand

import grails.dev.commands.ExecutionContext



class MyCommand implements GrailsApplicationCommand {



@Override

boolean handle() {

def dataSource = applicationContext.getBean(DataSource)

//Run some SQL...



return true

}



}
Enhancing artefacts
import grails.artefact.Enhances

import groovy.transform.CompileStatic



@Enhances(['Controller', 'Service'])

@CompileStatic

trait DateSupport {



Date now() {

return new Date()

}



}
Bean definition
• In Grails 2.x, you could only define beans in
doWithSpring.
• With Grails 3.x, you can also leverage from
Spring Boot auto-configuration.
• Beware of the classpath scanning!
Auto-configuration
package com.acme.myplugin



import org.springframework.context.annotation.Bean

import org.springframework.context.annotation.Configuration



@Configuration

class MyPluginAutoConfiguration {



@Bean

MyService myService() {

new MyService()

}



}
Auto-configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=

com.acme.myplugin.MyPluginAutoConfiguration
src/main/groovy/resources/META-INF/spring.factories
Auto-configuration
• Place services in src/main/groovy.
• Grails registers automatically grails-app/
services/*.
• Users will have to configure classpath
scanning.
• By default, scanning is limited to the app, not
dependent JARS.
Classpath scanning
• The Grails way:
class Application extends GrailsAutoConfiguration {

static void main(String[] args) {

GrailsApp.run(Application, args)

}



@Override

protected boolean limitScanningToApplication() {

return false

}



@Override

Collection<String> packageNames() {

return ['com.acme.myplugin']

}





}
Classpath scanning
• The Spring Boot way:
@ComponentScan(basePackages = ['com.acme.myplugin'])

class Application extends GrailsAutoConfiguration {

static void main(String[] args) {

GrailsApp.run(Application, args)

}

}
Modularisation
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.
Modularisation
Monolithic plugin
Multi-module plugin
Modularisation
• Benefits:
• Optional dependencies.
• Smaller JAR files.
• Build logic reuse.
Modularisation setup
• settings.gradle:
include ‘myPlugin-core', ‘myPlugin-domain' //etc
Modularisation setup
• Root build.gradle:
allprojects {

apply plugin:"idea"

}



subprojects { Project project ->

ext {

grailsVersion = project.grailsVersion

gradleWrapperVersion = project.gradleWrapperVersion

}



repositories {

//Common repos

}



version "1.0.0.M1"

group "org.grails.plugins"



apply plugin: "org.grails.grails-plugin"



dependencies {

//Common deps

}

}
Modularisation setup
• Sub-module build.gradle:
dependencyManagement {

imports {

mavenBom "org.grails:grails-bom:$grailsVersion"

}

applyMavenExclusions false

}



dependencies {

compile project(":myPlugin-core")



compile "com.example:library:1.0.0"

}
Publishing
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.
Bintray setup
• For Snapshots:
Build setup
artifactory {

contextUrl = 'http://oss.jfrog.org'

publish {

repository {

repoKey = 'oss-snapshot-local'

username = bintrayUser

password = bintrayKey

}

defaults {

publications('maven')

}

}

}



artifactoryPublish {

dependsOn sourcesJar, javadocJar

}
grailsPublish {

user = bintrayUser

key = bintrayKey

portalUser = pluginPortalUser

portalPassword = pluginPortalPassword



repo = 'plugins'

githubSlug = 'alvarosanchez/my-plugin'

license = 'APACHE 2.0'

title = "My Plugin"

desc = "A very cool Grails plugin"

developers = [

alvarosanchez: "Alvaro Sanchez-Mariscal"

]

}
• For Releases:
Build setup
Build setup
• Define rootProject.name in
settings.gradle.
• Define credentials in
~/.gradle/gradle.properties.
Running it
• Snapshot publishing:
• Release publishing:
$ ./gradlew artifactoryPublish
$ ./gradlew publishPlugin notifyPluginPortal
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://plugins.grails.org/
• Grails 2: http://grails.org/plugins
Testing
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.
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
Feature descriptor
description: First configuration of GORM

dependencies:

build:

- "org.grails.plugins:hibernate4:5.0.0.RC2"

compile:

- "org.grails.plugins:hibernate4"

- "org.hibernate:hibernate-ehcache"

- "org.grails.plugins:spring-security-rest-gorm:${pluginVersion}"

runtime:

- "com.h2database:h2"
features/gorm1/feature.yml.tmpl
Build setup
task generateProfileConfig << {

copy {

from 'profile.yml.tmpl'

into '.'

rename { String fileName -> fileName.replaceAll '.tmpl', '' }

expand pluginVersion: project.version

}



file('features').eachDir { feature ->

copy {

from "features/${feature.name}/feature.yml.tmpl"

into "features/${feature.name}/"

rename { String fileName -> fileName.replaceAll '.tmpl', '' }

expand pluginVersion: project.version

}

}

}



compileProfile.dependsOn generateProfileConfig
Build setup
cd build
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


done
generate-test-apps.sh
File build = new File('build')

if (build.exists()) {

build.eachDir {

include it.path

}

}

settings.gradle
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.
Demo - The Spring
Security REST plugin
Thank you!
Álvaro Sánchez-Mariscal

More Related Content

PDF
Desarrollo de aplicaciones con Grails 3, Angular JS y Spring Security
PDF
Mastering Grails 3 Plugins - GR8Conf US 2016
PDF
Creating applications with Grails, Angular JS and Spring Security - G3 Summit...
PDF
Creating applications with Grails, Angular JS and Spring Security - GR8Conf U...
PDF
Creating applications with Grails, Angular JS and Spring Security - GR8Conf E...
PDF
Mastering Grails 3 Plugins - GR8Conf EU 2016
PDF
Creating applications with Grails, Angular JS and Spring Security
PDF
Mastering Grails 3 Plugins - Greach 2016
Desarrollo de aplicaciones con Grails 3, Angular JS y Spring Security
Mastering Grails 3 Plugins - GR8Conf US 2016
Creating applications with Grails, Angular JS and Spring Security - G3 Summit...
Creating applications with Grails, Angular JS and Spring Security - GR8Conf U...
Creating applications with Grails, Angular JS and Spring Security - GR8Conf E...
Mastering Grails 3 Plugins - GR8Conf EU 2016
Creating applications with Grails, Angular JS and Spring Security
Mastering Grails 3 Plugins - Greach 2016

What's hot (20)

PPTX
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
PDF
Rest with grails 3
PDF
Using React with Grails 3
PDF
Swagger code motion talk
PDF
Swagger 2.0: Latest and Greatest
PDF
Drone CI - Container native continuous Integration / Delivery
PDF
JHipster
ODP
Jenkins and rails app - Le Dinh Vu
PDF
Swagger UI
PPTX
Automazione serverless con Azure Functions e PowerShell - Marco Obinu - DevOp...
PDF
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
PDF
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
PDF
How to generate a REST CXF3 application from Swagger ApacheConEU 2016
PDF
戦う情シス!全社 API で社内アプリ開発を加速させよう
PDF
Web view
PDF
Why you can't ignore GitLab
PDF
Getting Started With Angular
PPTX
Magic of web components
PPTX
Grails Plugin
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
Rest with grails 3
Using React with Grails 3
Swagger code motion talk
Swagger 2.0: Latest and Greatest
Drone CI - Container native continuous Integration / Delivery
JHipster
Jenkins and rails app - Le Dinh Vu
Swagger UI
Automazione serverless con Azure Functions e PowerShell - Marco Obinu - DevOp...
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
How to generate a REST CXF3 application from Swagger ApacheConEU 2016
戦う情シス!全社 API で社内アプリ開発を加速させよう
Web view
Why you can't ignore GitLab
Getting Started With Angular
Magic of web components
Grails Plugin
Ad

Similar to Mastering Grails 3 Plugins - G3 Summit 2016 (20)

PPTX
Grails Custom Plugin
PPTX
Custom plugin
PPTX
Grails plugin development
PDF
Grails Plugin Best Practices
PDF
Grails 3.0 Preview
PDF
Migrating from Grails 2 to Grails 3
PDF
GR8Conf 2011: Grails, how to plug in
ODP
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
PDF
Building Grails Plugins - Tips And Tricks
PPTX
Grails Advanced
PDF
Grails 101
PDF
Cut your Grails application to pieces - build feature plugins
ODP
Plugin development
POT
intoduction to Grails Framework
KEY
Grails at DMC Digital
PPT
Grails Plugins
PDF
Introduction To Groovy And Grails - SpringPeople
PPT
Introduction To Grails
PDF
Future of Grails
PDF
Groovy grailstutorial
Grails Custom Plugin
Custom plugin
Grails plugin development
Grails Plugin Best Practices
Grails 3.0 Preview
Migrating from Grails 2 to Grails 3
GR8Conf 2011: Grails, how to plug in
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Building Grails Plugins - Tips And Tricks
Grails Advanced
Grails 101
Cut your Grails application to pieces - build feature plugins
Plugin development
intoduction to Grails Framework
Grails at DMC Digital
Grails Plugins
Introduction To Groovy And Grails - SpringPeople
Introduction To Grails
Future of Grails
Groovy grailstutorial
Ad

More from Alvaro Sanchez-Mariscal (20)

PDF
Serverless functions with Micronaut
PDF
Asynchronous and event-driven Grails applications
PDF
6 things you need to know about GORM 6
PDF
Reactive microservices with Micronaut - GR8Conf EU 2018
PDF
Reactive microservices with Micronaut - Greach 2018
PDF
Practical Spring Cloud
PDF
Efficient HTTP applications on the JVM with Ratpack - JDD 2015
PDF
Stateless authentication with OAuth 2 and JWT - JavaZone 2015
PDF
Stateless authentication for microservices - GR8Conf 2015
PDF
Ratpack 101 - GR8Conf 2015
PDF
Ratpack 101 - GeeCON 2015
PDF
Stateless authentication for microservices - Spring I/O 2015
PDF
Stateless authentication for microservices - Greach 2015
PDF
Stateless authentication for microservices applications - JavaLand 2015
PDF
Stateless authentication for microservices
PDF
Stateless token-based authentication for pure front-end applications
PDF
Workshop: Creating RESTful API’s with Grails and Spring Security (GR8Conf 2014)
PDF
Embrace the frontend revolution
PDF
DevQA: make your testers happier with Groovy, Spock and Geb (Greach 2014)
PDF
Creating RESTful API’s with Grails and Spring Security
Serverless functions with Micronaut
Asynchronous and event-driven Grails applications
6 things you need to know about GORM 6
Reactive microservices with Micronaut - GR8Conf EU 2018
Reactive microservices with Micronaut - Greach 2018
Practical Spring Cloud
Efficient HTTP applications on the JVM with Ratpack - JDD 2015
Stateless authentication with OAuth 2 and JWT - JavaZone 2015
Stateless authentication for microservices - GR8Conf 2015
Ratpack 101 - GR8Conf 2015
Ratpack 101 - GeeCON 2015
Stateless authentication for microservices - Spring I/O 2015
Stateless authentication for microservices - Greach 2015
Stateless authentication for microservices applications - JavaLand 2015
Stateless authentication for microservices
Stateless token-based authentication for pure front-end applications
Workshop: Creating RESTful API’s with Grails and Spring Security (GR8Conf 2014)
Embrace the frontend revolution
DevQA: make your testers happier with Groovy, Spock and Geb (Greach 2014)
Creating RESTful API’s with Grails and Spring Security

Recently uploaded (20)

PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
iTop VPN 6.5.0 Crack + License Key 2025 (Premium Version)
PDF
Nekopoi APK 2025 free lastest update
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
L1 - Introduction to python Backend.pptx
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Complete Guide to Website Development in Malaysia for SMEs
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Oracle Fusion HCM Cloud Demo for Beginners
Navsoft: AI-Powered Business Solutions & Custom Software Development
iTop VPN 6.5.0 Crack + License Key 2025 (Premium Version)
Nekopoi APK 2025 free lastest update
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
Monitoring Stack: Grafana, Loki & Promtail
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Operating system designcfffgfgggggggvggggggggg
L1 - Introduction to python Backend.pptx
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Complete Guide to Website Development in Malaysia for SMEs
Salesforce Agentforce AI Implementation.pdf
CHAPTER 2 - PM Management and IT Context
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Odoo Companies in India – Driving Business Transformation.pdf
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx

Mastering Grails 3 Plugins - G3 Summit 2016

  • 4. OCI is the new home of Grails More at ociweb.com/grails
  • 6. Creating a Grails 3 plugin $ grails create-plugin myWebPlugin | Plugin created at /private/tmp/myWebPlugin $ grails create-plugin myPlugin -profile plugin | Plugin created at /private/tmp/myPlugin
  • 7. Understanding profiles • A profile defines: • Project’s build.gradle. • Commands: create-domain-class, run-app, etc. • Features: hibernate, json-views, etc. • Skeleton: files and folders.
  • 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. • Dozens of 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. • grails-app/init with an Application class. • Everything else can be removed.
  • 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.
  • 15. Demo - Creating a plugin
  • 17. 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.
  • 18. 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/**/**'
 }
  • 19. 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.
  • 20. 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"
 }
  • 21. Commands (3.1) import grails.dev.commands.ApplicationCommand
 import grails.dev.commands.ExecutionContext
 
 class MyCommand implements ApplicationCommand {
 
 @Override
 boolean handle(ExecutionContext ctx) {
 def dataSource = applicationContext.getBean(DataSource)
 //Run some SQL...
 
 return true
 }
 
 }
  • 22. Commands (3.2) import grails.dev.commands.ApplicationCommand
 import grails.dev.commands.ExecutionContext
 
 class MyCommand implements GrailsApplicationCommand {
 
 @Override
 boolean handle() {
 def dataSource = applicationContext.getBean(DataSource)
 //Run some SQL...
 
 return true
 }
 
 }
  • 23. Enhancing artefacts import grails.artefact.Enhances
 import groovy.transform.CompileStatic
 
 @Enhances(['Controller', 'Service'])
 @CompileStatic
 trait DateSupport {
 
 Date now() {
 return new Date()
 }
 
 }
  • 24. Bean definition • In Grails 2.x, you could only define beans in doWithSpring. • With Grails 3.x, you can also leverage from Spring Boot auto-configuration. • Beware of the classpath scanning!
  • 25. Auto-configuration package com.acme.myplugin
 
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
 
 @Configuration
 class MyPluginAutoConfiguration {
 
 @Bean
 MyService myService() {
 new MyService()
 }
 
 }
  • 27. Auto-configuration • Place services in src/main/groovy. • Grails registers automatically grails-app/ services/*. • Users will have to configure classpath scanning. • By default, scanning is limited to the app, not dependent JARS.
  • 28. Classpath scanning • The Grails way: class Application extends GrailsAutoConfiguration {
 static void main(String[] args) {
 GrailsApp.run(Application, args)
 }
 
 @Override
 protected boolean limitScanningToApplication() {
 return false
 }
 
 @Override
 Collection<String> packageNames() {
 return ['com.acme.myplugin']
 }
 
 
 }
  • 29. Classpath scanning • The Spring Boot way: @ComponentScan(basePackages = ['com.acme.myplugin'])
 class Application extends GrailsAutoConfiguration {
 static void main(String[] args) {
 GrailsApp.run(Application, args)
 }
 }
  • 31. 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.
  • 33. Modularisation • Benefits: • Optional dependencies. • Smaller JAR files. • Build logic reuse.
  • 34. Modularisation setup • settings.gradle: include ‘myPlugin-core', ‘myPlugin-domain' //etc
  • 35. Modularisation setup • Root build.gradle: allprojects {
 apply plugin:"idea"
 }
 
 subprojects { Project project ->
 ext {
 grailsVersion = project.grailsVersion
 gradleWrapperVersion = project.gradleWrapperVersion
 }
 
 repositories {
 //Common repos
 }
 
 version "1.0.0.M1"
 group "org.grails.plugins"
 
 apply plugin: "org.grails.grails-plugin"
 
 dependencies {
 //Common deps
 }
 }
  • 36. Modularisation setup • Sub-module build.gradle: dependencyManagement {
 imports {
 mavenBom "org.grails:grails-bom:$grailsVersion"
 }
 applyMavenExclusions false
 }
 
 dependencies {
 compile project(":myPlugin-core")
 
 compile "com.example:library:1.0.0"
 }
  • 38. 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.
  • 40. • For Snapshots: Build setup artifactory {
 contextUrl = 'http://oss.jfrog.org'
 publish {
 repository {
 repoKey = 'oss-snapshot-local'
 username = bintrayUser
 password = bintrayKey
 }
 defaults {
 publications('maven')
 }
 }
 }
 
 artifactoryPublish {
 dependsOn sourcesJar, javadocJar
 }
  • 41. grailsPublish {
 user = bintrayUser
 key = bintrayKey
 portalUser = pluginPortalUser
 portalPassword = pluginPortalPassword
 
 repo = 'plugins'
 githubSlug = 'alvarosanchez/my-plugin'
 license = 'APACHE 2.0'
 title = "My Plugin"
 desc = "A very cool Grails plugin"
 developers = [
 alvarosanchez: "Alvaro Sanchez-Mariscal"
 ]
 } • For Releases: Build setup
  • 42. Build setup • Define rootProject.name in settings.gradle. • Define credentials in ~/.gradle/gradle.properties.
  • 43. Running it • Snapshot publishing: • Release publishing: $ ./gradlew artifactoryPublish $ ./gradlew publishPlugin notifyPluginPortal
  • 44. 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://plugins.grails.org/ • Grails 2: http://grails.org/plugins
  • 46. 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.
  • 47. 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
  • 48. Feature descriptor description: First configuration of GORM
 dependencies:
 build:
 - "org.grails.plugins:hibernate4:5.0.0.RC2"
 compile:
 - "org.grails.plugins:hibernate4"
 - "org.hibernate:hibernate-ehcache"
 - "org.grails.plugins:spring-security-rest-gorm:${pluginVersion}"
 runtime:
 - "com.h2database:h2" features/gorm1/feature.yml.tmpl
  • 49. Build setup task generateProfileConfig << {
 copy {
 from 'profile.yml.tmpl'
 into '.'
 rename { String fileName -> fileName.replaceAll '.tmpl', '' }
 expand pluginVersion: project.version
 }
 
 file('features').eachDir { feature ->
 copy {
 from "features/${feature.name}/feature.yml.tmpl"
 into "features/${feature.name}/"
 rename { String fileName -> fileName.replaceAll '.tmpl', '' }
 expand pluginVersion: project.version
 }
 }
 }
 
 compileProfile.dependsOn generateProfileConfig
  • 50. Build setup cd build 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 
 done generate-test-apps.sh File build = new File('build')
 if (build.exists()) {
 build.eachDir {
 include it.path
 }
 }
 settings.gradle
  • 51. 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.
  • 52. Demo - The Spring Security REST plugin