Presenter: Graeme Rocher
Agenda
- plugin quick start
- technical vs. functional plugins
- plugins for modularity
- distribution and dependency management
- plugin demo
Key Facts
- grails itself is made up of a collection of plugins
- hibernate, webflow, gsp, etc.
- grails core is essentially a set of plugins (about a dozen)
- there are 300+ plugins available now
- what a plugin can do is wide and varied
- plugins are easy to create
- don’t need to spend a ton of time learning the internals of the framework to create a plugin
- plugins are easy to distribute
- everyone is a plugin developer
- well over 25 million lines of user contributed code in the plugin repository
- searchable
- automatically makes any domain class searchable
- taggable
- adds apis to tag domain classes
- rateable
- ratings for domain classes
- quartz
- for scheduling tasks
- interesting because it adds a new concept to grails — “jobs”
- adds create-job command to command line, has a jobs directory, etc.
- gwt
- weceem cms
- example of a functional plugin as opposed to just providing new apis
- this plugin contains views, controllers, domains, etc. as part of the plugin
- feeds (rss and atom feeds)
- iwebkit (iphone)
- searchable
Common Use Case
- you have a tag library
- you have two applications
- you want to share functionality
- create a plugin!
- grails create-plugin pluginName creates the plugin skeleton
- grails 1.2 creates intellij project files
Plugin Structure
- more or less identical to a grails application structure
- can run the plugins as standalone apps
- developing a plugin is the same as developing an application
- only real difference is there’s a plugin descriptor in the root of each plugin
- contains info about plugin version, grails versions supported
- can also exclude specific resources when the plugin is installed
- also numerous plugin hooks that can be accessed (doWithWebDescriptor, doWithSpring, etc.)
- using packages is important–should always uses packages in your applications
Plugin Quick Start — 5 steps
- grails create-plugin myPlugin
- cd myPlugin
- grails create-tag-lib myTagLib
- grails package-plugin
- grails install-plugin
Plugin Extension Points
- normal grails development
- tag libraries, controllers, etc.
- the build
- theses are very trivial to do
- requires additional knowledge
- spring configuration
- new apis
- addition of additional properties/methods to domain classes and domain controllers
- new concepts
Plugin Types
- relate to the “split” above
- functional plugins
- taglibs, controllers, extend the build, etc.
- technical plugins
- see above–spring config, metaprogramming, etc.
Examples
- functional plugins
- weceem cms
- nimble
- provides user management, integration with facebook, etc.
- technical plugins
- gwt
- functional test
- both functional and technical
- spring security
- searchable
- adds search to domain classes, but also provides a complete search UI to your application
Functional Plugins
- easier to understand
- just like building a normal grails application
- silos of functionality
- forums, blog, search, etc.
- used to create modular applications
Demo: Building a Functional Plugin
- example: twitter clone
- two different teams–web UI team, mobile team
- underlying functionality is the same
- good candidate for a plugin–need to share the domain model between the two apps
- can install plugins in other plugins
- e.g. can install both the iwebkit and the twitter domain model plugin into the iphone version of the app
- can specify plugins and versions in dependsOn block in the plugin descriptor
- when you package up your plugin it will bundle up the plugins on which your plugin depends and include them
- can use BootStrap.groovy within plugins
- can configure local plugin repositories and can specify order in which plugin repositories are searched
Certain Things that Plugins Cannot Package by Default
- BootStrap.groovy, UrlMappings.groovy, DataSource.groovy
- can create something like FooUrlMappings.groovy and that will get packaged
Some Tips
- inline plugins
- if you’re modularizing your entire application, becomes impractical to repackage and reinstall every plugin as they change during development
- url mappings
- jar dependencies
- testing
- plugin distribution
Inline Plugins
- use plugins without installing them
- prevents package/install cycle
- great for modular application development
- go to grails-app/conf/BuildConfig.groovy and set grails.plugin.location.”pluginName”=”../path/to/plugin”
- BuildConfig.groovy
- not generated automatically in 1.1.1
- lets you configure various aspects of the build, locations of generated files, etc.
URL Mappings
- normal UrlMappings.groovy file is excluded from the package plugin process
- if you want to define url mappings as part of your plugin, create a file called something like MyPluginUrlMappings.groovy and that will be included
Plugin Dependencies
- grails supports transitive installs and plugin dependencies using dependsOn
- can use ranges of versions for dependencies, e.g. hibernate:”1.1 > *”
- to implement a “soft” dependency use loadAfter
- def loadAfter = [“hibernate”]
- can also specify loadBefore
Plugin JAR Dependencies
- you can put jar files in the lib directory of the project just like applications
- even better, in grails 1.2 you can define dependencies in grails-app/conf/BuildConfig.groovy
- grails.project.dependency.resolution = {
inherits “global” // inherit grails’ default dependencies
dependencies {
runtime “org.apache.ant:ant:1.7.1”
}
} - different scopes can be involved–build, runtime, test, provided (needed during grails run-app but not during WAR deployment)
- this means the jar files are NOT included in the plugin packaging
- allows application into which the application is installed to resolve the dependencies
- in a traditional java project, the jar dependency list is flat
- in grails, you have dependencies of the app, of the framework, and of any plugins involved
Testing
- done just like a normal application
- sometimes it’s useful to have classes used only for testing and not distributed with the plugin
- use pluginExcludes in the plugin descriptor to achieve this
- class MyPlugin {
def pluginExcludes = [
“ant/path/here“
]
}
Plugin Distribution
- central repository
- grails release-plugin
- custom repository
- can configure custom repos in BuildConfig.groovy
- can also set this in settings.groovy in your user home directory
- Grails separates notion of repos used for discovery vs. distribution (e.g. http for discovery, https for distribution)
- can specify the repository into which to release the plugin when you run grails release-plugin
- custom repos use svn for distribution
- can use a basic file server for discovery
- plugins don’t necessarily have to be open source to be in the central repository
- need to specify the license
- would distribute jars instead of source
Summary
- developing grails plugins is very simple
- functional plugins are an easy way to modularize your application
- in part 2 we’ll be looking at how to develop technical plugins
Q&A
- as part of modularization is there any integration with osgi?
- not yet, but looking into it–probably next year there will be something more concrete
- are there particular plugins that you would highlight that follow best practices or as good models to follow?
- depends on what you want to do
- for a functional plugin check out weceem cms–complete end-to-end with views, js, etc.
- for a technical plugin check out Build Test Data (creates mock data for you)
- quartz plugin is a good example of a plugin that adds a new concept to grails, new command line arguments, etc.
- exercises the artefact api
- SpringWS plugin adds notion of an endpoint to Grails
- Ratable, Commentable, Featurable, and Taggable are great examples of modifying domain classes on app load