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
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.
• 14 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.
• Empty grails-app folder.
• 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.
Plugins 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
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

}



}
Enhancing artefacts
import grails.artefact.Enhances

import groovy.transform.CompileStatic



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

@CompileStatic

trait DateSupport {



Date now() {

return new Date()

}



}
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://grails.org/plugins.html
• 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
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.
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
Use case: the Spring
Security REST plugin
Thank you!
Álvaro Sánchez-Mariscal

More Related Content

What's hot

Swagger code motion talk
Swagger code motion talkSwagger code motion talk
Swagger code motion talk
Victor Trakhtenberg
 
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
Will Huang
 
Iterative Development with Swagger on the JDK
Iterative Development with Swagger on the JDKIterative Development with Swagger on the JDK
Iterative Development with Swagger on the JDK
Swagger API
 
Swagger 2.0: Latest and Greatest
Swagger 2.0: Latest and GreatestSwagger 2.0: Latest and Greatest
Swagger 2.0: Latest and Greatest
LaunchAny
 
Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...
Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...
Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...
The Software House
 
JHipster
JHipsterJHipster
JHipster
Yuen-Kuei Hsueh
 
Writer APIs in Java faster with Swagger Inflector
Writer APIs in Java faster with Swagger InflectorWriter APIs in Java faster with Swagger Inflector
Writer APIs in Java faster with Swagger Inflector
Tony Tam
 
Swagger 2.0 and Model-driven APIs
Swagger 2.0 and Model-driven APIsSwagger 2.0 and Model-driven APIs
Swagger 2.0 and Model-driven APIs
Apigee | Google Cloud
 
Swagger
SwaggerSwagger
Swagger UI
Swagger UISwagger UI
Swagger UI
Walaa Hamdy Assy
 
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
Alvaro Sanchez-Mariscal
 
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeEuroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Metosin Oy
 
How to generate a REST CXF3 application from Swagger ApacheConEU 2016
How to generate a REST CXF3 application from Swagger ApacheConEU 2016How to generate a REST CXF3 application from Swagger ApacheConEU 2016
How to generate a REST CXF3 application from Swagger ApacheConEU 2016
johannes_fiala
 
Getting Started With Angular
Getting Started With AngularGetting Started With Angular
Getting Started With Angular
Stormpath
 
Design Driven API Development
Design Driven API DevelopmentDesign Driven API Development
Design Driven API Development
Sokichi Fujita
 
戦う情シス!全社 API で社内アプリ開発を加速させよう
戦う情シス!全社 API で社内アプリ開発を加速させよう戦う情シス!全社 API で社内アプリ開発を加速させよう
戦う情シス!全社 API で社内アプリ開発を加速させよう
Yuki Hattori
 
Beautifying the Beautiful: Theming WSO2 API Manager
Beautifying the Beautiful: Theming WSO2 API ManagerBeautifying the Beautiful: Theming WSO2 API Manager
Beautifying the Beautiful: Theming WSO2 API Manager
WSO2
 
Magic of web components
Magic of web componentsMagic of web components
Magic of web components
HYS Enterprise
 
ASP.NET Core
ASP.NET CoreASP.NET Core
ASP.NET Core
Andrea Dottor
 

What's hot (20)

Swagger code motion talk
Swagger code motion talkSwagger code motion talk
Swagger code motion talk
 
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
你不可不知的 ASP.NET Core 3 全新功能探索 (.NET Conf 2019)
 
Iterative Development with Swagger on the JDK
Iterative Development with Swagger on the JDKIterative Development with Swagger on the JDK
Iterative Development with Swagger on the JDK
 
Swagger 2.0: Latest and Greatest
Swagger 2.0: Latest and GreatestSwagger 2.0: Latest and Greatest
Swagger 2.0: Latest and Greatest
 
Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...
Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...
Mój przepis na skalowalną architekturę mikroserwisową? Apollo Federation i Gr...
 
JHipster
JHipsterJHipster
JHipster
 
Writer APIs in Java faster with Swagger Inflector
Writer APIs in Java faster with Swagger InflectorWriter APIs in Java faster with Swagger Inflector
Writer APIs in Java faster with Swagger Inflector
 
Swagger 2.0 and Model-driven APIs
Swagger 2.0 and Model-driven APIsSwagger 2.0 and Model-driven APIs
Swagger 2.0 and Model-driven APIs
 
Swagger
SwaggerSwagger
Swagger
 
Swagger UI
Swagger UISwagger UI
Swagger UI
 
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
Efficient HTTP applications on the JVM with Ratpack - Voxxed Days Berlin 2016
 
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesomeEuroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
 
How to generate a REST CXF3 application from Swagger ApacheConEU 2016
How to generate a REST CXF3 application from Swagger ApacheConEU 2016How to generate a REST CXF3 application from Swagger ApacheConEU 2016
How to generate a REST CXF3 application from Swagger ApacheConEU 2016
 
Getting Started With Angular
Getting Started With AngularGetting Started With Angular
Getting Started With Angular
 
Design Driven API Development
Design Driven API DevelopmentDesign Driven API Development
Design Driven API Development
 
戦う情シス!全社 API で社内アプリ開発を加速させよう
戦う情シス!全社 API で社内アプリ開発を加速させよう戦う情シス!全社 API で社内アプリ開発を加速させよう
戦う情シス!全社 API で社内アプリ開発を加速させよう
 
Beautifying the Beautiful: Theming WSO2 API Manager
Beautifying the Beautiful: Theming WSO2 API ManagerBeautifying the Beautiful: Theming WSO2 API Manager
Beautifying the Beautiful: Theming WSO2 API Manager
 
Web view
Web viewWeb view
Web view
 
Magic of web components
Magic of web componentsMagic of web components
Magic of web components
 
ASP.NET Core
ASP.NET CoreASP.NET Core
ASP.NET Core
 

Similar to Mastering Grails 3 Plugins - GR8Conf US 2016

Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016
Alvaro Sanchez-Mariscal
 
Make Your Build Great Again (DroidConSF 2017)
Make Your Build Great Again (DroidConSF 2017)Make Your Build Great Again (DroidConSF 2017)
Make Your Build Great Again (DroidConSF 2017)
Jared Burrows
 
Gradle
GradleGradle
Building Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksBuilding Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksMike Hugo
 
Grails 3.0 Preview
Grails 3.0 PreviewGrails 3.0 Preview
Grails 3.0 Preview
graemerocher
 
Making the Most of Your Gradle Builds
Making the Most of Your Gradle BuildsMaking the Most of Your Gradle Builds
Making the Most of Your Gradle Builds
Egor Andreevich
 
OpenCms Days 2012 - Developing OpenCms with Gradle
OpenCms Days 2012 - Developing OpenCms with GradleOpenCms Days 2012 - Developing OpenCms with Gradle
OpenCms Days 2012 - Developing OpenCms with Gradle
Alkacon Software GmbH & Co. KG
 
Grails Custom Plugin
Grails Custom PluginGrails Custom Plugin
Grails Custom Plugin
NexThoughts Technologies
 
Custom plugin
Custom pluginCustom plugin
Custom plugin
Vijay Shukla
 
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 EnglishGrails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Sven Haiges
 
Grails Plugins
Grails PluginsGrails Plugins
Grails Plugins
NexThoughts Technologies
 
Spring boot
Spring bootSpring boot
Spring boot
Bhagwat Kumar
 
Grails Connecting to MySQL
Grails Connecting to MySQLGrails Connecting to MySQL
Grails Connecting to MySQL
ashishkirpan
 
Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]
Ryan Cuprak
 
Config BuildConfig
Config BuildConfigConfig BuildConfig
Config BuildConfig
Vijay Shukla
 
Config/BuildConfig
Config/BuildConfigConfig/BuildConfig
Config/BuildConfig
Vijay Shukla
 
Config BuildConfig
Config BuildConfigConfig BuildConfig
Config BuildConfig
NexThoughts Technologies
 
GR8Conf 2011: Grails, how to plug in
GR8Conf 2011: Grails, how to plug inGR8Conf 2011: Grails, how to plug in
GR8Conf 2011: Grails, how to plug inGR8Conf
 
Before & After Docker Init
Before & After Docker InitBefore & After Docker Init
Before & After Docker Init
Angel Borroy López
 

Similar to Mastering Grails 3 Plugins - GR8Conf US 2016 (20)

Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016Mastering Grails 3 Plugins - Greach 2016
Mastering Grails 3 Plugins - Greach 2016
 
Make Your Build Great Again (DroidConSF 2017)
Make Your Build Great Again (DroidConSF 2017)Make Your Build Great Again (DroidConSF 2017)
Make Your Build Great Again (DroidConSF 2017)
 
Gradle
GradleGradle
Gradle
 
Building Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And TricksBuilding Grails Plugins - Tips And Tricks
Building Grails Plugins - Tips And Tricks
 
Grails 3.0 Preview
Grails 3.0 PreviewGrails 3.0 Preview
Grails 3.0 Preview
 
Making the Most of Your Gradle Builds
Making the Most of Your Gradle BuildsMaking the Most of Your Gradle Builds
Making the Most of Your Gradle Builds
 
OpenCms Days 2012 - Developing OpenCms with Gradle
OpenCms Days 2012 - Developing OpenCms with GradleOpenCms Days 2012 - Developing OpenCms with Gradle
OpenCms Days 2012 - Developing OpenCms with Gradle
 
Grails Custom Plugin
Grails Custom PluginGrails Custom Plugin
Grails Custom Plugin
 
Custom plugin
Custom pluginCustom plugin
Custom plugin
 
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 EnglishGrails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
 
Grails Plugins
Grails PluginsGrails Plugins
Grails Plugins
 
Spring boot
Spring bootSpring boot
Spring boot
 
Grails Connecting to MySQL
Grails Connecting to MySQLGrails Connecting to MySQL
Grails Connecting to MySQL
 
Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]
 
Config BuildConfig
Config BuildConfigConfig BuildConfig
Config BuildConfig
 
Config/BuildConfig
Config/BuildConfigConfig/BuildConfig
Config/BuildConfig
 
Config BuildConfig
Config BuildConfigConfig BuildConfig
Config BuildConfig
 
GR8Conf 2011: Grails, how to plug in
GR8Conf 2011: Grails, how to plug inGR8Conf 2011: Grails, how to plug in
GR8Conf 2011: Grails, how to plug in
 
Before & After Docker Init
Before & After Docker InitBefore & After Docker Init
Before & After Docker Init
 
Generators
GeneratorsGenerators
Generators
 

More from Alvaro Sanchez-Mariscal

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

More from Alvaro Sanchez-Mariscal (20)

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

Recently uploaded

Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfEnhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Jay Das
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 

Recently uploaded (20)

Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfEnhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 

Mastering Grails 3 Plugins - GR8Conf US 2016

  • 2. Álvaro Sánchez-Mariscal Software Engineer Grails Development Team sanchezmariscala@ociweb.com
  • 3.
  • 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. • 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. • 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.
  • 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"
 }
  • 20. Commands 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
 }
 
 }
  • 21. Enhancing artefacts import grails.artefact.Enhances
 import groovy.transform.CompileStatic
 
 @Enhances(['Controller', 'Service'])
 @CompileStatic
 trait DateSupport {
 
 Date now() {
 return new Date()
 }
 
 }
  • 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.
  • 25. Modularisation • Benefits: • Optional dependencies. • Smaller JAR files. • Build logic reuse.
  • 26. Modularisation setup • settings.gradle: include ‘myPlugin-core', ‘myPlugin-domain' //etc
  • 27. 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
 }
 }
  • 28. 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"
 }
  • 30. 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.
  • 32. • 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
 }
  • 33. 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
  • 34. Build setup • Define rootProject.name in settings.gradle. • Define credentials in ~/.gradle/gradle.properties.
  • 35. Running it • Snapshot publishing: • Release publishing: $ ./gradlew artifactoryPublish $ ./gradlew publishPlugin notifyPluginPortal
  • 36. 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
  • 38. 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.
  • 39. 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
  • 40. 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
  • 41. 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
  • 42. 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.
  • 43. 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
  • 44. Use case: the Spring Security REST plugin