Download - Grails plugin development
Grails Plugin Development
- Mohd Farid
Agenda
1. What is a plugin
2. Creating and Installing Plugins
3. Understanding a Plugin's Structure
4. Providing Basic Artefacts
5. Accessing the Application’s artefact classes
6. Hooking into Runtime Configuration
7. Adding Dynamic Methods at Runtime
8. Participating in Auto Reload Events
9. Understanding Plugin Load Order
10.Adding our own Artefact Types
11.Releasing our Plugin
What is a plugin
Wikipedia says:
In computing, a plugin is a software component that adds a specific feature to an existing software application.
● Very similar to a Grails application project
● Plus a *GrailsPlugin.groovy plugin descriptor file
● Use grails create plugin to create one
● Often adds artifacts, resources, scripts
● Good for code reuse
● Modular development
What is a Grails plugin
Creating and Installing Plugins
Creating and Installing Plugins
Command grails create-plugin my-first-plugin
Plugin descriptor file
A Groovy file whose name ends with GrailsPlugin
Creating and Installing Plugins contd...
Plugin descriptor specifies the details about the plugin:|
1. title
2. version Example "0.1", "0.2-SNAPSHOT", "1.1.4" etc.
3. grailsVersion - eg. "1.2 > *" (indicating 1.2 or higher)
4. author -
5. authorEmail -
6. description -
7. documentation - URL of the plugin's documentation
Creating and Installing Plugins contd...
Specifying the plugin location:
// Useful to test plugins you are developing.
grails.plugin.location.shiro = "/home/dilbert/dev/plugins/grails-shiro"
// Useful for modular applications where all plugins and
// applications are in the same directory.
grails.plugin.location.'grails-ui' = "../grails-grails-ui"
Demo
Creating an inplace plugin and
configuring it in Application
Understanding a plugin’s structure
Understanding a Plugin's Structure
1. Structure is similar to a normal grails application
2. When installed it differs slightly3. Contents of grails-app will go
into the plugins directory within the host application : plugins/example-1.0/grails-app
4. Not copied into the main source tree.
5. No interfering with the primary application.
6. Java / Groovy/ lib: Goes into web-app/WEB-INF/classes
Providing Basic Artefacts
Providing Basic Artefacts
Adding a new Script:
Add a gant script in scripts folder of the Plugin.
Adding a grails artefact:
Add a new domain, services, controller in the plugin’s respective directories.
Providing Basic Artefacts...Grails' view resolution mechanism
Just like controllers, we can provide default views from the plugin.
Scope to override the views provided by a plugin.
First checks for the view in the application.
If that fails will attempt to look for the view within the plugin.
DemoOverriding plugin view through application
Providing Basic Artefacts...
Files that are not packaged with the plugin:
1. BootStrap.groovy
2. BuildConfig.groovy
3. Config.groovy
4. DataSource.groovy (and any other *DataSource.groovy)
5. UrlMappings.groovy
6. resources.groovy
7. Everything within /web-app/WEB-INF
8. Everything within /web-app/plugins/**
9. Everything within /test/**
10.SCM management files within **/.svn/** and **/CVS/**
Accessing the Application’s artefact classes
Accessing the Application’s artefact classes
GrailsApplication application
1. application an implicit variable (instance GrailsApplication interface)
2. Has methods for accessing all artifact classes within our application.
Accessing the Application ..
Accessing all the Artefact Classes in Application
for (grailsClass in application.allClasses) {
println grailsClass.name
}Accessing all the controller classes:
for (controllerClass in application.controllerClasses){ println controllerClass.name}
Accessing the Application .. Some useful methods and their conventions
1. *Classes - eg application.controllerClasses)
2. get*Class - eg application.getControllerClass("PersonController")
3. is*Class - eg: application.isControllerClass(PersonController)
Artefact names:
4. domain
5. controller
6. tagLib
7. service
8. codec
9. bootstrap
10.urlMappings
Accessing the Application .. Some examples:
● application.domainClasses
● application.controllerClasses
● application.getDomainClass(“Person”)
● application.getControllerClass("PersonController")
● application.isTagLibClass(“ApplicationTagLib”)
Accessing the Application .. Each Artefact implements the GrailsClass :
getPropertyValue - Gets the initial value of the given property on the class
hasProperty - Returns true if the class has the specified property
newInstance - Creates a new instance of this class.
getName - Returns the logical name of the class in the application without the trailing convention part if applicable
getShortName - Returns the short name of the class without package prefix
Accessing the Application ..
some more methods in GrailsClass…
getFullName - Returns the full name of the class in the application with the trailing convention part and with the package name
getPropertyName - Returns the name of the class as a property name
getLogicalPropertyName - Returns the logical property name of the class in the application without the trailing convention part if applicable
getNaturalName - Returns the name of the property in natural terms (eg. 'lastName' becomes 'Last Name')
getPackageName - Returns the package name
DemoAccessing the Artefacts
Hooking into Runtime Configuration
Hooking into Runtime Configuration
1. Hooking into the Grails Spring configuration (doWithSpring)
2. Participating in web.xml Generation (doWithWebDescriptor)
3. Doing Post Initialisation Configuration (doWithApplicationContext)
Adding Dynamic Methods at Runtime
Adding Dynamic Methods at Runtime
def doWithDynamicMethods = { applicationContext -> for (controllerClass in application.controllerClasses) { controllerClass.metaClass.myNewMethod = {-> println "hello world" } } }
Demo
Adding a method through meta-programming
Participating in Auto Reload Events
Participating in Auto Reload Events
Monitoring Resources for Changes
def watchedResources = [ list of files that we want to watch for change]
def onchange = { event->
}
For other plugins
def influences = ['controllers']
def observe = ["controllers"]
Participating in Auto Reload Events
Monitoring Resources for Changes
def watchedResources
Eg values: ["file:./grails-app/jobs/**/*Job.groovy",
"file:./plugins/*/grails-app/jobs/**/*Job.groovy" ]
(from quartz plugin)
def onchange = { event->
println “Changed source: ${event.source}”
//we might want to re inject the meta class methods to certain artefacts.
}
Participating in Auto Reload Events
Monitoring Resources for Changes
event Object
● event.source - The source of the event, either the reloaded Class or a Spring Resource
● event.ctx - The Spring ApplicationContext instance
● event.plugin - The plugin object that manages the resource (usually this)
● event.application - The GrailsApplication instance
● event.manager - The GrailsPluginManager instance
def influences = ['controllers'] // reload the controller plugin when there is any change in my plugin
observes = ["controllers"] // reload my plugin if controller plugin has changes.
Participating in Auto Reload Events
Use Cases:
watchedResources: Quartz Plugin watches for changes Job Artefact.
influences: Service plugin influences controllers.
observes: Mail plugin wants to be notified if services or controller plugin has
changes.
Demo Watched Resources & OnChange events
Understanding Plugin Load Order
Understanding Plugin Load Order
Hard dependency def dependsOn = [foo: "* > 1.0"]def dependsOn = [foo: "1.0 > 1.1"]def dependsOn = [foo: "1.0 > *"]
Weaker dependencydef loadAfter = ['controllers']def loadBefore = ['controllers']
Understanding Plugin Load Order
Interacting with other plugins
manager: another implicit object : an instance of GrailsPluginManager
Eg: Hibernate plugin checks for presence of controllers plugin for some decision making.
if (manager?.hasGrailsPlugin("controllers")) {
// DO something
}
Adding our own Artefact Types
Adding our own Artefact Types
Steps for introducing a custom Artefact:
1. An implementation of ArtefactHandler (Can use ArtefactHandlerAdapter as base)
2. Each Artefact must implement GrailsClass
3. def artefacts = [ org.somewhere.MyArtefactHandler ] in plugin descriptor.
See by Example:
Quartz plugin’s ArtefactHandler
Releasing our plugin
Releasing our plugin
1. Register on grails.org
2. Fill out this form
3. Provide good documentation for the users to get started.
4. Once approved, install the release plugin in the plugin application
5. grails publish-plugin --stacktrace
6. Once successful, the plugin will be published in the grails plugin
repository. Users will be able to install it directly from Grails Plugin portal
by adding the dependency in BuildConfig.groovy
References and further reading
http://grails.org/doc/2.2.2/guide/plugins.html#creatingAndInstallingPlugins
https://github.com/grails-plugins/grails-quartz
https://github.com/gpc/grails-mail/
http://www.slideshare.net/mjhugo/building-grails-plugins-tips-and-tricks
thankyou