Wednesday, October 21, 2009

Session Notes - Grails Plugin System Part 1

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)




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



No comments: