SlideShare a Scribd company logo
Grails: How To Plug In

Burt Beckwith
SpringSource




                                                       CONFIDENTIAL
                         © 2010 SpringSource, A division of VMware. All rights reserved
Agenda

 What Is A Plugin?
 Implementation Details
 Testing
 Source Control and Release Management
 Best Practices and Tips



                            CONFIDENTIAL   2
My Plugins
 Acegi                                       Flex Scaffold (major rework, not yet released)
 App Info
                                              SpringMVC
 BlazeDS
                                              Spring Security Core
 Cloud Foundry
                                              Spring Security ACL
 Cloud Foundry UI
                                              Spring Security App Info
 CodeNarc
                                              Spring Security Kerberos
 Console
 Database Reverse Engineering                Spring Security LDAP
 Database Migrations                         Spring Security Open ID
 Datasources                                 Spring Security CAS
 Dynamic Controller                          Spring Security UI
 Dynamic Domain Class (core code)            Twitter
 FamFamFam                                   UI Performance
 Flex

                                     CONFIDENTIAL                                               3
What Is A Plugin?




      CONFIDENTIAL   4
What Is A Plugin?




       “  A set of software components that
          adds specific abilities to a larger
          software application
          https://secure.wikimedia.org/wikipedia/en/wiki/Plug-in_(computing)




                                  CONFIDENTIAL                                 5
What Is A Plugin?


 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




                            CONFIDENTIAL               6
What Is A Plugin?




 http://blog.springsource.com/2010/06/01/whats-a-plugin-oriented-architecture/


                                     CONFIDENTIAL                                7
Application Directory Structure




           CONFIDENTIAL           8
Plugin Directory Structure




           CONFIDENTIAL      9
The Background


 Grails is designed to wire
  different libraries together and
  make them easy to use

 Can be seen as “platform for
  runtime configuration”

 Without well defined system, de-
  coupling those components was
  hard

                         CONFIDENTIAL   10
Extension Points


 The Build System
 Spring Application Context
 Dynamic method registration
 Auto Reloading
 Container Config (web.xml)
 Adding new Artefact Types




                          CONFIDENTIAL   11
Types of Plugin

 New functionality
  • Datasources, UI Performance, etc.
 Wrapper
  • Spring Security, Searchable, Quartz, etc.
  • Often have many scripts, e.g. Cloud Foundry, Database
  Migration
 UI
 Bug fix
 • http://grails.org/plugin/error-pages-fix, http://grails.org/plugin/aop-reloading-fix
 Resource-only
  • famfamfam

                                         CONFIDENTIAL                                     12
Plugin Architecture




                      CONFIDENTIAL   13
Plugin Goals


   Convention-based approaches
   DRY (Don't Repeat Yourself)
   Required extension points satisfied
   Easy to distribute & install
    • Without additional configuration




                             CONFIDENTIAL   14
What Can A Plugin Do?


 Enhance classes at runtime
 • Add methods, constructors, properties, etc.

 Perform runtime Spring configuration
 Modify web.xml on the fly
 Add new controllers, tag libraries, etc.




                              CONFIDENTIAL       15
A Basic Plugin



    class LoggingGrailsPlugin {
        def version = "0.1”
        def grailsVersion = "1.3 > *"
        def doWithDynamicMethods = {
          for (c in application.allClasses) {
             c.metaClass.getLog = {->
                LogFactory.getLog(c)
             }
          }
        }
    }




                                   CONFIDENTIAL   16
DEMO




CONFIDENTIAL   17
Implementation Details




         CONFIDENTIAL    18
Application Object

 'GrailsApplication' object
 • available with the 'application' variable
 • holds convention information
 Useful methods like:
 • get*Classes
   • Retrieve all GrailsClass instances for particular artifact, e.g.
    getControllerClasses()
 • add*Class(Class clazz)
   • Adds new GrailsClass for specified class,
    e.g. addControllerClass(myClass)
 • get*Class(String name)
   • Retrieves GrailsClass for given name,
    e.g. getControllerClass(name)


                                        CONFIDENTIAL                    19
Grails Artifacts


 Some resource that fulfills a convention
 • controllers, services, etc.

 Represented by the GrailsClass interface
 • http://grails.org/doc/latest/api/org/codehaus/groovy/grails/
  commons/package-summary.html for API of all artifacts

 Add new artifacts via the Artifact API
 • http://grails.org/Developer+-+Artefact+API




                                      CONFIDENTIAL                20
Grails Artifacts


 Design decision: include or generate artifacts?
  • Include is more automatic, no explicit step
  • Including requires workflow to override
  • Generate requires extra step but is more customizable
  • Generation is static – old files can get out of date
 Overriding domain classes?
  • Really only an issue with create-drop and update, not with migrations
 Overriding controllers?
  • “un-map” with UrlMappings
  "/admin/console/$action?/$id?"(controller: "console")
  "/console/$action?/$id?"(controller: "errors", action: "urlMapping")



                                        CONFIDENTIAL                        21
The GrailsClass Interface

 Implemented by Grails artifacts written in Groovy
 • getPropertyValue(String name)
 • newInstance()
 • getName()                ← logical name

 • getFullName()            ← class name including package

 • getShortName()           ← class name without package

 • getPropertyName()        ← class name as property name

 • getClazz()               ← actual java.lang.Class


                              CONFIDENTIAL                   22
Plugin Descriptor

 Metadata
 • version, grailsVersion range, pluginExcludes, dependsOn, etc.

 Lifecycle Closures
                                  ← Modify XML generated for web.xml at
 doWithWebDescriptor              runtime

 doWithSpring                     ← Participate in Spring configuration
                                  ← Post ApplicationContext initialization
 doWithApplicationContext         activities

 doWithDynamicMethods             ← Add methods to MetaClasses

 onChange                         ← Participate in reload events


                              CONFIDENTIAL                                   23
Configuring Spring




  class JcrGrailsPlugin {
    def version = 0.1               Bean name is method name,
    def dependsOn = [core:0.4]      first argument is bean class
      def doWithSpring = {
        jcrRepository(RepositoryFactoryBean) {
           configuration = "classpath:repository.xml"
           homeDir = "/repo"
        }
      }                              Set properties on the bean
  }




                                   CONFIDENTIAL                    24
Advantages Of Spring DSL


 Just Groovy code, so can contain complex logic
 dependent on:

 • environment
 • project conventions
 • anything!

 Easy to specify complex bean definitions
 • thanks to Groovy's neat lists and maps syntax


                            CONFIDENTIAL           25
Overriding Spring Beans


 Use loadAfter to define plugin load order; your beans
 override other plugins' and Grails'

 resources.groovy loads last, so applications can
 redefine beans there
  Import com.mycompany.myapp.MyUserDetailsService
  beans = {
    userDetailsService(MyUserDetailsService) {
      grailsApplication = ref('grailsApplication')
      foo = 'bar'
    }
  }


 BeanPostProcessor/BeanFactoryPostProcessor
                                 CONFIDENTIAL             26
Plugging In Dynamic Methods


                                                  Taken from Grails core, this
 def doWithDynamicMethods = { ctx ->              plugin finds all classes ending
   application                                    with “Codec” and dynamically
      .allClasses                                 creates “encodeAsFoo” methods!
      .findAll { it.name.endsWith("Codec") }
      .each {clz ->
         Object
            .metaClass
            ."encodeAs${clz.name-'Codec'}" = {
               clz.newInstance().encode(delegate)
            }
         }
                                               The “delegate” variable
      }
                                               is equivalent to “this” in
 }
                                               regular methods



                                   CONFIDENTIAL                                27
Reload Events


  Grails apps must be reloadable during
  development

  • Can mean many things
  • Plugin's responsibility

  Plugins can define
  watchedResources
  firing onChange events
  when modified


                              CONFIDENTIAL   28
Example Reloading Plugin



class I18nGrailsPlugin {                           Defines set of files to watch
  def version = "0.4.2"                            using Spring Resource pattern
  def watchedResources =
    "file:../grails-app/i18n/*.properties"
    def onChange = { event ->
      def messageSource =
         event.ctx.getBean("messageSource")
        messageSource?.clearCache()
    }
}
                                                       When one changes, event
                                                       is fired and plugin responds
                                                       by clearing message cache




                                    CONFIDENTIAL                                   29
The Event Object


   event.source
    • Source of the change – either a Spring Resource or a
     java.lang.Class if the class was reloaded
   event.ctx
    • the Spring ApplicationContext
   event.application
    • the GrailsApplication
   event.manager
    • the GrailsPluginManager



                              CONFIDENTIAL                   30
Adding Elements to web.xml

    def doWithWebDescriptor = { xml →

        def contextParam = xml.'context-param'
        contextParam[contextParam.size() - 1] + {
          'filter' {
              'filter-name'('springSecurityFilterChain')
              'filter-class'(DelegatingFilterProxy.name)
          }
        }

        def filterMapping = xml.'filter-mapping'
        filterMapping[filterMapping.size() - 1] + {
           'listener' {
              'listener-class'(HttpSessionEventPublisher.name)
           }
        }
    }

                                     CONFIDENTIAL                31
Dependency Management


   Jar files
   • Prefer BuildConfig.groovy → Maven repos
   • lib directory is ok if unavailable otherwise

   Other plugins
   • def dependsOn = [springSecurityCore: '1.1 > *']

   • def loadAfter = ['controllers']

   Grails
   • def grailsVersion = '1.2.3 > *'


                          CONFIDENTIAL                 32
BuildConfig.groovy

 grails.project.dependency.resolution = {
   inherits 'global'
   log 'warn'

  repositories {
    grailsPlugins()
    grailsHome()
    grailsCentral()

      flatDir name:'myRepo', dirs:'/path/to/repo'

      mavenCentral()
      mavenRepo 'http://download.java.net/maven/2/'
      mavenRepo 'http://my.cool.repo.net/maven/'
  }




                                    CONFIDENTIAL      33
BuildConfig.groovy

    dependencies {
      runtime 'mysql:mysql-connector-java:5.1.13'
      compile group: 'commons-httpclient',
                name: 'commons-httpclient',
                version: '3.1'
      build('net.sf.ezmorph:ezmorph:1.0.4', 'net.sf.ehcache:ehcache:1.6.1') {
        transitive = false
      }
      test('com.h2database:h2:1.2.144') {
        export = false
      }
      runtime('org.liquibase:liquibase-core:2.0.1',
               'org.hibernate:hibernate-annotations:3.4.0.GA') {
        excludes 'xml-apis', 'commons-logging'
      }
    }
}


                                    CONFIDENTIAL                                34
Troubleshooting Dependency Management


   Run grails dependency­report
   • See http://burtbeckwith.com/blog/?p=624 for
    visualization tips

   Increase logging level
   • log 'warn' → 'info', 'verbose', or 'debug'




                         CONFIDENTIAL              35
Scripts


   Gant: http://gant.codehaus.org/
   Groovy + Ant - XML
   Can be used in apps but more common in plugins
   Put in plugin's (or app's) scripts directory
   _Install.groovy
    • runs when you run grails install­plugin or
     when it's transitively installed - don't overwrite!
     might be reinstall or plugin upgrade



                           CONFIDENTIAL                    36
Scripts


   _Uninstall.groovy
    • runs when you run grails uninstall­plugin so
     you can do cleanup, but don't delete user-
     created/edited stuff

   _Upgrade.groovy
    • runs when you run grails upgrade (not when
     you upgrade a plugin)



                            CONFIDENTIAL             37
Scripts

                      eventCreateWarStart = { name, stagingDir →
   _Events.groovy    …
                      }
    • Respond to
                      eventGenerateWebXmlEnd = {
     build events     …
                      }



   Naming convention
    • Prefix with '_' → don't show in grails help
    • Suffix with '_' → 'global' script, i.e. doesn't need
     to run in a project dir (e.g. create­app)

                            CONFIDENTIAL                           38
Scripts


   Reuse existing scripts with includeTargets
    • includeTargets << grailsScript("_GrailsWar")

   Include common code in _*Common.groovy
    • includeTargets << new 
     File("$cloudFoundryPluginDir/scripts/ 
     _CfCommon.groovy")




                          CONFIDENTIAL               39
Testing Scripts


   Put tests in test/cli
   Extend grails.test.AbstractCliTestCase
   stdout and stderr will be in target/cli-output
   http://www.cacoethes.co.uk/blog/groovyandgrails/t
    esting-your-grails-scripts

   Run with the rest with grails test­app or alone
    with grails test­app ­­other



                            CONFIDENTIAL                40
Scripts

                             Typical Structure
  includeTargets << new File(
          "$cloudFoundryPluginDir/scripts/_CfCommon.groovy")

  USAGE = '''
  grails cf-list-files [path] [--appname] [--instance]
  '''

  target(cfListFiles: 'Display a directory listing') {
    depends cfInit

      // implementation of script
  }

  def someHelperMethod() { … }

  setDefaultTarget cfListFiles

                                      CONFIDENTIAL             41
Custom Artifacts


   ControllerMixinArtefactHandler extends
   ArtefactHandlerAdapter

   interface ControllerMixinGrailsClass extends
   InjectableGrailsClass

   DefaultControllerMixinGrailsClass extends
   AbstractInjectableGrailsClass implements
   ControllerMixinGrailsClass




                            CONFIDENTIAL           42
Custom Artifacts



  class MyGrailsPlugin {

      def watchedResources = [
        'file:./grails-app/controllerMixins/**/*ControllerMixin.groovy',
        'file:./plugins/*/grails-app/controllerMixins/**/*ControllerMixin.groovy'
      ]

      def artefacts = [ControllerMixinArtefactHandler]

      def onChange = { event →
        ...
      }
  }




                                      CONFIDENTIAL                                  43
Testing




 CONFIDENTIAL   44
Testing

   Write regular unit and integration tests in test/unit
   and test/integration

   'Install' using inline mechanism in
   BuildConfig.groovy
   • grails.plugin.location.'my­plugin' = '../my­plugin'

   Test scripts as described earlier
   Create test apps programmatically – all of the
   Spring Security plugins do this with bash scripts


                           CONFIDENTIAL                     45
Testing

   Use build.xml or Gradle to create single target that
   tests and builds plugin
   <target name='package' description='Package the plugin'
           depends='test, doPackage, post-package-cleanup'/>

   Use inline plugin or install from zip
   grails install-plugin /path/to/plugin/grails-myplugin-0.1.zip




                                   CONFIDENTIAL                    46
Source Control and Release Management




                CONFIDENTIAL            47
Becoming A Plugin Developer


   Signup at Codehaus xircles
   • http://xircles.codehaus.org/signup &
     http://xircles.codehaus.org/projects/grails-plugins/members
   Talk about your idea on the mailing list
   • http://grails.org/Mailing+lists
   • Summarize your contribution and ask on the dev list
     for your request to be processed - include your xircles
     user name in the request
   Build (and test!) your plugin and run:
    • grails publish-plugin
   Done!

                              CONFIDENTIAL                         48
Source Control and Release Management

   Internal server for jars & plugins is easy with Artifactory or
    Nexus
  repositories {
    grailsPlugins()
    grailsHome()
    mavenRepo "http://yourserver:8081/artifactory/libs-releases-local/"
    mavenRepo "http://yourserver:8081/artifactory/plugins-releases-local/"
    grailsCentral()
  }

   Release with grails publish­plugin ­­repository=repo_name
  grails.project.dependency.distribution = {
    remoteRepository(
        id: "repo_name",
        url: "http://yourserver:8081/artifactory/plugins-snapshots-local/") {
      authentication username: "admin", password: "password"
    }
  }
                                      CONFIDENTIAL                              49
Source Control and Release Management

   Use “release” plugin http://grails.org/plugin/release
   • Will be default in 1.4+, publish-plugin replaces release-plugin
   • Sends tweet from @grailsplugins and email to plugin forum
     http://grails-plugins.847840.n3.nabble.com/
   • Will check code into SVN for you
     • disable with ­­noScm or grails.release.scm.enabled = false




                                     CONFIDENTIAL                      50
Best Practices and Tips




         CONFIDENTIAL     51
Best Practices and Tips


   Delete anything auto-generated that you don't use
    • grails-app/views/error.gsp
    • _Uninstall.groovy and other generated scripts
    • Empty descriptor callbacks

   Exclude files used in development or testing
    • Use def pluginExcludes = [...]
    • src/docs
    • Test artifacts
   Use Ivy + Maven repos in BuildConfig.groovy, not lib dir


                             CONFIDENTIAL                      52
Best Practices and Tips


   Write tests
   Run them often
   Run tests before commit and especially before
    release (use build.xml)

   Create test apps (ideally programmatically)
   Programmatically build inline plugin location:
   def customerName = System.getProperty("customer.name")
   grails.plugin.location."$customerName" = "customer-plugins/$customerName"


                                   CONFIDENTIAL                                53
Best Practices and Tips


   Get to 1.0
    • Initial version 0.1 is just a suggestion
    • People trust 1.0+ more
   Start using source control early
    • Easy to run git init locally and later → github
   Support your plugin!




                          CONFIDENTIAL                  54
Best Practices and Tips


   http://grails.org/doc/latest/guide/12.%20Plug-ins.html
   http://grails.org/doc/latest/guide/4.%20The
    %20Command%20Line.html#4.3%20Hooking%20into
    %20Events

   http://www.grails.org/The+Plug-in+Developers+Guide
   http://blog.springsource.com/2010/05/18/managing-
    plugins-with-grails-1-3/




                               CONFIDENTIAL                  55
Hackergarten




Signup for hackergarten here:

http://bit.ly/gr8_hackergarten



               CONFIDENTIAL      56

More Related Content

What's hot

Micronaut Launchpad
Micronaut LaunchpadMicronaut Launchpad
Micronaut Launchpad
Zachary Klein
 
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
kennethaliu
 
Java 9 Modularity in Action
Java 9 Modularity in ActionJava 9 Modularity in Action
Java 9 Modularity in Action
Sander Mak (@Sander_Mak)
 
Using Magnolia in a Microservices Architecture
Using Magnolia in a Microservices ArchitectureUsing Magnolia in a Microservices Architecture
Using Magnolia in a Microservices Architecture
Magnolia
 
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
VMware Tanzu
 
Spring Boot Revisited with KoFu and JaFu
Spring Boot Revisited with KoFu and JaFuSpring Boot Revisited with KoFu and JaFu
Spring Boot Revisited with KoFu and JaFu
VMware Tanzu
 
Developing modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsDeveloping modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular js
Shekhar Gulati
 
Grails 3.0 Preview
Grails 3.0 PreviewGrails 3.0 Preview
Grails 3.0 Preview
graemerocher
 
Dropwizard Spring - the perfect Java REST server stack
Dropwizard Spring - the perfect Java REST server stackDropwizard Spring - the perfect Java REST server stack
Dropwizard Spring - the perfect Java REST server stack
Jacek Furmankiewicz
 
Gradle - time for a new build
Gradle - time for a new buildGradle - time for a new build
Gradle - time for a new build
Igor Khotin
 
Grails 4: Upgrade your Game!
Grails 4: Upgrade your Game!Grails 4: Upgrade your Game!
Grails 4: Upgrade your Game!
Zachary Klein
 
Enabling White-Box Reuse in a Pure Composition Language
Enabling White-Box Reuse in a Pure Composition LanguageEnabling White-Box Reuse in a Pure Composition Language
Enabling White-Box Reuse in a Pure Composition Language
elliando dias
 
Dropwizard and Friends
Dropwizard and FriendsDropwizard and Friends
Dropwizard and Friends
Yun Zhi Lin
 
Modular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache KarafModular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache Karaf
Ioan Eugen Stan
 
Step by step guide to create theme for liferay dxp 7
Step by step guide to create theme for liferay dxp 7Step by step guide to create theme for liferay dxp 7
Step by step guide to create theme for liferay dxp 7
Azilen Technologies Pvt. Ltd.
 
Getting Groovy with JHipster and Micronaut
Getting Groovy with JHipster and MicronautGetting Groovy with JHipster and Micronaut
Getting Groovy with JHipster and Micronaut
Zachary Klein
 
Developing Plug-Ins for NetBeans
Developing Plug-Ins for NetBeansDeveloping Plug-Ins for NetBeans
Developing Plug-Ins for NetBeans
elliando dias
 
From JavaEE to AngularJS
From JavaEE to AngularJSFrom JavaEE to AngularJS
From JavaEE to AngularJS
Nebrass Lamouchi
 
Faster Java EE Builds with Gradle
Faster Java EE Builds with GradleFaster Java EE Builds with Gradle
Faster Java EE Builds with Gradle
Ryan Cuprak
 
Spring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWSSpring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWS
VMware Tanzu
 

What's hot (20)

Micronaut Launchpad
Micronaut LaunchpadMicronaut Launchpad
Micronaut Launchpad
 
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
Modularizing your Grails Application with Private Plugins - SpringOne 2GX 2012
 
Java 9 Modularity in Action
Java 9 Modularity in ActionJava 9 Modularity in Action
Java 9 Modularity in Action
 
Using Magnolia in a Microservices Architecture
Using Magnolia in a Microservices ArchitectureUsing Magnolia in a Microservices Architecture
Using Magnolia in a Microservices Architecture
 
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchron...
 
Spring Boot Revisited with KoFu and JaFu
Spring Boot Revisited with KoFu and JaFuSpring Boot Revisited with KoFu and JaFu
Spring Boot Revisited with KoFu and JaFu
 
Developing modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsDeveloping modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular js
 
Grails 3.0 Preview
Grails 3.0 PreviewGrails 3.0 Preview
Grails 3.0 Preview
 
Dropwizard Spring - the perfect Java REST server stack
Dropwizard Spring - the perfect Java REST server stackDropwizard Spring - the perfect Java REST server stack
Dropwizard Spring - the perfect Java REST server stack
 
Gradle - time for a new build
Gradle - time for a new buildGradle - time for a new build
Gradle - time for a new build
 
Grails 4: Upgrade your Game!
Grails 4: Upgrade your Game!Grails 4: Upgrade your Game!
Grails 4: Upgrade your Game!
 
Enabling White-Box Reuse in a Pure Composition Language
Enabling White-Box Reuse in a Pure Composition LanguageEnabling White-Box Reuse in a Pure Composition Language
Enabling White-Box Reuse in a Pure Composition Language
 
Dropwizard and Friends
Dropwizard and FriendsDropwizard and Friends
Dropwizard and Friends
 
Modular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache KarafModular Java applications with OSGi on Apache Karaf
Modular Java applications with OSGi on Apache Karaf
 
Step by step guide to create theme for liferay dxp 7
Step by step guide to create theme for liferay dxp 7Step by step guide to create theme for liferay dxp 7
Step by step guide to create theme for liferay dxp 7
 
Getting Groovy with JHipster and Micronaut
Getting Groovy with JHipster and MicronautGetting Groovy with JHipster and Micronaut
Getting Groovy with JHipster and Micronaut
 
Developing Plug-Ins for NetBeans
Developing Plug-Ins for NetBeansDeveloping Plug-Ins for NetBeans
Developing Plug-Ins for NetBeans
 
From JavaEE to AngularJS
From JavaEE to AngularJSFrom JavaEE to AngularJS
From JavaEE to AngularJS
 
Faster Java EE Builds with Gradle
Faster Java EE Builds with GradleFaster Java EE Builds with Gradle
Faster Java EE Builds with Gradle
 
Spring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWSSpring Boot on Amazon Web Services with Spring Cloud AWS
Spring Boot on Amazon Web Services with Spring Cloud AWS
 

Viewers also liked

GR8Conf 2009: Groovy in Fiance Case Study by Jonathan Felch
GR8Conf 2009: Groovy in Fiance Case Study by Jonathan FelchGR8Conf 2009: Groovy in Fiance Case Study by Jonathan Felch
GR8Conf 2009: Groovy in Fiance Case Study by Jonathan Felch
GR8Conf
 
GR8Conf 2011: CodeNarc and GMetrics
GR8Conf 2011: CodeNarc and GMetricsGR8Conf 2011: CodeNarc and GMetrics
GR8Conf 2011: CodeNarc and GMetrics
GR8Conf
 
Idiomatic spock
Idiomatic spockIdiomatic spock
Idiomatic spock
GR8Conf
 
GR8Conf 2011: Grails 1.4 Update by Peter Ledbrook
GR8Conf 2011: Grails 1.4 Update by Peter LedbrookGR8Conf 2011: Grails 1.4 Update by Peter Ledbrook
GR8Conf 2011: Grails 1.4 Update by Peter Ledbrook
GR8Conf
 
Mum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developerMum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developer
GR8Conf
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with Groovy
GR8Conf
 
Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle
GR8Conf
 

Viewers also liked (7)

GR8Conf 2009: Groovy in Fiance Case Study by Jonathan Felch
GR8Conf 2009: Groovy in Fiance Case Study by Jonathan FelchGR8Conf 2009: Groovy in Fiance Case Study by Jonathan Felch
GR8Conf 2009: Groovy in Fiance Case Study by Jonathan Felch
 
GR8Conf 2011: CodeNarc and GMetrics
GR8Conf 2011: CodeNarc and GMetricsGR8Conf 2011: CodeNarc and GMetrics
GR8Conf 2011: CodeNarc and GMetrics
 
Idiomatic spock
Idiomatic spockIdiomatic spock
Idiomatic spock
 
GR8Conf 2011: Grails 1.4 Update by Peter Ledbrook
GR8Conf 2011: Grails 1.4 Update by Peter LedbrookGR8Conf 2011: Grails 1.4 Update by Peter Ledbrook
GR8Conf 2011: Grails 1.4 Update by Peter Ledbrook
 
Mum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developerMum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developer
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with Groovy
 
Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle
 

Similar to GR8Conf 2011: Grails, how to plug in

Build12 factorappusingmp
Build12 factorappusingmpBuild12 factorappusingmp
Build12 factorappusingmp
Emily Jiang
 
Spring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsugSpring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsug
Toshiaki Maki
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusMicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
Emily Jiang
 
Simplify Cloud Applications using Spring Cloud
Simplify Cloud Applications using Spring CloudSimplify Cloud Applications using Spring Cloud
Simplify Cloud Applications using Spring Cloud
Ramnivas Laddad
 
Grails plugin development
Grails plugin developmentGrails plugin development
Grails plugin development
Mohd Farid
 
Cloud Foundry for Spring Developers
Cloud Foundry for Spring DevelopersCloud Foundry for Spring Developers
Cloud Foundry for Spring Developers
Gunnar Hillert
 
Building 12-factor Cloud Native Microservices
Building 12-factor Cloud Native MicroservicesBuilding 12-factor Cloud Native Microservices
Building 12-factor Cloud Native Microservices
Jakarta_EE
 
GradleFX
GradleFXGradleFX
Jetpack, with new features in 2021 GDG Georgetown IO Extended
Jetpack, with new features in 2021 GDG Georgetown IO ExtendedJetpack, with new features in 2021 GDG Georgetown IO Extended
Jetpack, with new features in 2021 GDG Georgetown IO Extended
Toru Wonyoung Choi
 
Digital Forensics and Incident Response in The Cloud Part 3
Digital Forensics and Incident Response in The Cloud Part 3Digital Forensics and Incident Response in The Cloud Part 3
Digital Forensics and Incident Response in The Cloud Part 3
Velocidex Enterprises
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020
Emily Jiang
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020
Emily Jiang
 
Gradle
GradleGradle
04_Azure Kubernetes Service: Basic Practices for Developers_GAB2019
04_Azure Kubernetes Service: Basic Practices for Developers_GAB201904_Azure Kubernetes Service: Basic Practices for Developers_GAB2019
04_Azure Kubernetes Service: Basic Practices for Developers_GAB2019
Kumton Suttiraksiri
 
CICD With GitHub, Travis, SonarCloud and Docker Hub
CICD With GitHub, Travis, SonarCloud and Docker HubCICD With GitHub, Travis, SonarCloud and Docker Hub
CICD With GitHub, Travis, SonarCloud and Docker Hub
Carlos Cavero Barca
 
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
Oleg Shalygin
 
Live Coding 12 Factor App
Live Coding 12 Factor AppLive Coding 12 Factor App
Live Coding 12 Factor App
Emily Jiang
 
Arquillian & Citrus
Arquillian & CitrusArquillian & Citrus
Arquillian & Citrus
christophd
 
Introduction To Grails
Introduction To GrailsIntroduction To Grails
Introduction To Grails
Christopher Bartling
 
AWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for GovernmentAWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for Government
Amazon Web Services
 

Similar to GR8Conf 2011: Grails, how to plug in (20)

Build12 factorappusingmp
Build12 factorappusingmpBuild12 factorappusingmp
Build12 factorappusingmp
 
Spring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsugSpring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsug
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusMicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
 
Simplify Cloud Applications using Spring Cloud
Simplify Cloud Applications using Spring CloudSimplify Cloud Applications using Spring Cloud
Simplify Cloud Applications using Spring Cloud
 
Grails plugin development
Grails plugin developmentGrails plugin development
Grails plugin development
 
Cloud Foundry for Spring Developers
Cloud Foundry for Spring DevelopersCloud Foundry for Spring Developers
Cloud Foundry for Spring Developers
 
Building 12-factor Cloud Native Microservices
Building 12-factor Cloud Native MicroservicesBuilding 12-factor Cloud Native Microservices
Building 12-factor Cloud Native Microservices
 
GradleFX
GradleFXGradleFX
GradleFX
 
Jetpack, with new features in 2021 GDG Georgetown IO Extended
Jetpack, with new features in 2021 GDG Georgetown IO ExtendedJetpack, with new features in 2021 GDG Georgetown IO Extended
Jetpack, with new features in 2021 GDG Georgetown IO Extended
 
Digital Forensics and Incident Response in The Cloud Part 3
Digital Forensics and Incident Response in The Cloud Part 3Digital Forensics and Incident Response in The Cloud Part 3
Digital Forensics and Incident Response in The Cloud Part 3
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020
 
Gradle
GradleGradle
Gradle
 
04_Azure Kubernetes Service: Basic Practices for Developers_GAB2019
04_Azure Kubernetes Service: Basic Practices for Developers_GAB201904_Azure Kubernetes Service: Basic Practices for Developers_GAB2019
04_Azure Kubernetes Service: Basic Practices for Developers_GAB2019
 
CICD With GitHub, Travis, SonarCloud and Docker Hub
CICD With GitHub, Travis, SonarCloud and Docker HubCICD With GitHub, Travis, SonarCloud and Docker Hub
CICD With GitHub, Travis, SonarCloud and Docker Hub
 
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
 
Live Coding 12 Factor App
Live Coding 12 Factor AppLive Coding 12 Factor App
Live Coding 12 Factor App
 
Arquillian & Citrus
Arquillian & CitrusArquillian & Citrus
Arquillian & Citrus
 
Introduction To Grails
Introduction To GrailsIntroduction To Grails
Introduction To Grails
 
AWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for GovernmentAWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for Government
 

More from GR8Conf

DevOps Enabling Your Team
DevOps Enabling Your TeamDevOps Enabling Your Team
DevOps Enabling Your Team
GR8Conf
 
Scraping with Geb
Scraping with GebScraping with Geb
Scraping with Geb
GR8Conf
 
How to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and AndroidHow to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and Android
GR8Conf
 
Ratpack On the Docks
Ratpack On the DocksRatpack On the Docks
Ratpack On the Docks
GR8Conf
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean Code
GR8Conf
 
Cut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature pluginsCut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature plugins
GR8Conf
 
Performance tuning Grails applications
 Performance tuning Grails applications Performance tuning Grails applications
Performance tuning Grails applications
GR8Conf
 
Ratpack and Grails 3
 Ratpack and Grails 3 Ratpack and Grails 3
Ratpack and Grails 3
GR8Conf
 
Grails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloudGrails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloud
GR8Conf
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEB
GR8Conf
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPC
GR8Conf
 
The Grails introduction workshop
The Grails introduction workshopThe Grails introduction workshop
The Grails introduction workshop
GR8Conf
 
The Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedThe Groovy Ecosystem Revisited
The Groovy Ecosystem Revisited
GR8Conf
 
Groovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examplesGroovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examples
GR8Conf
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and Groovy
GR8Conf
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual Machine
GR8Conf
 
Grooscript gr8conf
Grooscript gr8confGrooscript gr8conf
Grooscript gr8conf
GR8Conf
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual Machine
GR8Conf
 
Jan reher may 2013
Jan reher may 2013Jan reher may 2013
Jan reher may 2013
GR8Conf
 
Good Form - complex web forms made Groovy
Good Form - complex web forms made GroovyGood Form - complex web forms made Groovy
Good Form - complex web forms made Groovy
GR8Conf
 

More from GR8Conf (20)

DevOps Enabling Your Team
DevOps Enabling Your TeamDevOps Enabling Your Team
DevOps Enabling Your Team
 
Scraping with Geb
Scraping with GebScraping with Geb
Scraping with Geb
 
How to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and AndroidHow to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and Android
 
Ratpack On the Docks
Ratpack On the DocksRatpack On the Docks
Ratpack On the Docks
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean Code
 
Cut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature pluginsCut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature plugins
 
Performance tuning Grails applications
 Performance tuning Grails applications Performance tuning Grails applications
Performance tuning Grails applications
 
Ratpack and Grails 3
 Ratpack and Grails 3 Ratpack and Grails 3
Ratpack and Grails 3
 
Grails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloudGrails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloud
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEB
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPC
 
The Grails introduction workshop
The Grails introduction workshopThe Grails introduction workshop
The Grails introduction workshop
 
The Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedThe Groovy Ecosystem Revisited
The Groovy Ecosystem Revisited
 
Groovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examplesGroovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examples
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and Groovy
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual Machine
 
Grooscript gr8conf
Grooscript gr8confGrooscript gr8conf
Grooscript gr8conf
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual Machine
 
Jan reher may 2013
Jan reher may 2013Jan reher may 2013
Jan reher may 2013
 
Good Form - complex web forms made Groovy
Good Form - complex web forms made GroovyGood Form - complex web forms made Groovy
Good Form - complex web forms made Groovy
 

Recently uploaded

Semantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software DevelopmentSemantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software Development
Baishakhi Ray
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
Matthias Neugebauer
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
Zilliz
 
Keynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive SecurityKeynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive Security
Priyanka Aash
 
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
alexjohnson7307
 
Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17
Bhajan Mehta
 
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
shanihomely
 
Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10
ankush9927
 
LeadMagnet IQ Review: Unlock the Secret to Effortless Traffic and Leads.pdf
LeadMagnet IQ Review:  Unlock the Secret to Effortless Traffic and Leads.pdfLeadMagnet IQ Review:  Unlock the Secret to Effortless Traffic and Leads.pdf
LeadMagnet IQ Review: Unlock the Secret to Effortless Traffic and Leads.pdf
SelfMade bd
 
Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024
siddu769252
 
Redefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI CapabilitiesRedefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI Capabilities
Priyanka Aash
 
kk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdfkk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdf
KIRAN KV
 
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
alexjohnson7307
 
The History of Embeddings & Multimodal Embeddings
The History of Embeddings & Multimodal EmbeddingsThe History of Embeddings & Multimodal Embeddings
The History of Embeddings & Multimodal Embeddings
Zilliz
 
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and DisadvantagesBLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
SAI KAILASH R
 
Finetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and DefendingFinetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and Defending
Priyanka Aash
 
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
sunilverma7884
 
Accelerating Migrations = Recommendations
Accelerating Migrations = RecommendationsAccelerating Migrations = Recommendations
Accelerating Migrations = Recommendations
isBullShit
 
Mastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for SuccessMastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for Success
David Wilson
 
UX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business GoalsUX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business Goals
FIDO Alliance
 

Recently uploaded (20)

Semantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software DevelopmentSemantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software Development
 
Opencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of MünsterOpencast Summit 2024 — Opencast @ University of Münster
Opencast Summit 2024 — Opencast @ University of Münster
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
 
Keynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive SecurityKeynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive Security
 
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
leewayhertz.com-Generative AI tech stack Frameworks infrastructure models and...
 
Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17Mule Experience Hub and Release Channel with Java 17
Mule Experience Hub and Release Channel with Java 17
 
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
Premium Girls Call Mumbai 9920725232 Unlimited Short Providing Girls Service ...
 
Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10
 
LeadMagnet IQ Review: Unlock the Secret to Effortless Traffic and Leads.pdf
LeadMagnet IQ Review:  Unlock the Secret to Effortless Traffic and Leads.pdfLeadMagnet IQ Review:  Unlock the Secret to Effortless Traffic and Leads.pdf
LeadMagnet IQ Review: Unlock the Secret to Effortless Traffic and Leads.pdf
 
Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024Generative AI Reasoning Tech Talk - July 2024
Generative AI Reasoning Tech Talk - July 2024
 
Redefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI CapabilitiesRedefining Cybersecurity with AI Capabilities
Redefining Cybersecurity with AI Capabilities
 
kk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdfkk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdf
 
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
leewayhertz.com-AI agents for healthcare Applications benefits and implementa...
 
The History of Embeddings & Multimodal Embeddings
The History of Embeddings & Multimodal EmbeddingsThe History of Embeddings & Multimodal Embeddings
The History of Embeddings & Multimodal Embeddings
 
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and DisadvantagesBLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
 
Finetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and DefendingFinetuning GenAI For Hacking and Defending
Finetuning GenAI For Hacking and Defending
 
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
Girls call Kolkata 👀 XXXXXXXXXXX 👀 Rs.9.5 K Cash Payment With Room Delivery
 
Accelerating Migrations = Recommendations
Accelerating Migrations = RecommendationsAccelerating Migrations = Recommendations
Accelerating Migrations = Recommendations
 
Mastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for SuccessMastering OnlyFans Clone App Development: Key Strategies for Success
Mastering OnlyFans Clone App Development: Key Strategies for Success
 
UX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business GoalsUX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business Goals
 

GR8Conf 2011: Grails, how to plug in

  • 1. Grails: How To Plug In Burt Beckwith SpringSource CONFIDENTIAL © 2010 SpringSource, A division of VMware. All rights reserved
  • 2. Agenda  What Is A Plugin?  Implementation Details  Testing  Source Control and Release Management  Best Practices and Tips CONFIDENTIAL 2
  • 3. My Plugins  Acegi  Flex Scaffold (major rework, not yet released)  App Info  SpringMVC  BlazeDS  Spring Security Core  Cloud Foundry  Spring Security ACL  Cloud Foundry UI  Spring Security App Info  CodeNarc  Spring Security Kerberos  Console  Database Reverse Engineering  Spring Security LDAP  Database Migrations  Spring Security Open ID  Datasources  Spring Security CAS  Dynamic Controller  Spring Security UI  Dynamic Domain Class (core code)  Twitter  FamFamFam  UI Performance  Flex CONFIDENTIAL 3
  • 4. What Is A Plugin? CONFIDENTIAL 4
  • 5. What Is A Plugin? “ A set of software components that adds specific abilities to a larger software application https://secure.wikimedia.org/wikipedia/en/wiki/Plug-in_(computing) CONFIDENTIAL 5
  • 6. What Is A Plugin?  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 CONFIDENTIAL 6
  • 7. What Is A Plugin? http://blog.springsource.com/2010/06/01/whats-a-plugin-oriented-architecture/ CONFIDENTIAL 7
  • 9. Plugin Directory Structure CONFIDENTIAL 9
  • 10. The Background  Grails is designed to wire different libraries together and make them easy to use  Can be seen as “platform for runtime configuration”  Without well defined system, de- coupling those components was hard CONFIDENTIAL 10
  • 11. Extension Points  The Build System  Spring Application Context  Dynamic method registration  Auto Reloading  Container Config (web.xml)  Adding new Artefact Types CONFIDENTIAL 11
  • 12. Types of Plugin  New functionality • Datasources, UI Performance, etc.  Wrapper • Spring Security, Searchable, Quartz, etc. • Often have many scripts, e.g. Cloud Foundry, Database Migration  UI  Bug fix • http://grails.org/plugin/error-pages-fix, http://grails.org/plugin/aop-reloading-fix  Resource-only • famfamfam CONFIDENTIAL 12
  • 13. Plugin Architecture CONFIDENTIAL 13
  • 14. Plugin Goals  Convention-based approaches  DRY (Don't Repeat Yourself)  Required extension points satisfied  Easy to distribute & install • Without additional configuration CONFIDENTIAL 14
  • 15. What Can A Plugin Do?  Enhance classes at runtime • Add methods, constructors, properties, etc.  Perform runtime Spring configuration  Modify web.xml on the fly  Add new controllers, tag libraries, etc. CONFIDENTIAL 15
  • 16. A Basic Plugin class LoggingGrailsPlugin { def version = "0.1” def grailsVersion = "1.3 > *" def doWithDynamicMethods = { for (c in application.allClasses) { c.metaClass.getLog = {-> LogFactory.getLog(c) } } } } CONFIDENTIAL 16
  • 18. Implementation Details CONFIDENTIAL 18
  • 19. Application Object  'GrailsApplication' object • available with the 'application' variable • holds convention information  Useful methods like: • get*Classes • Retrieve all GrailsClass instances for particular artifact, e.g. getControllerClasses() • add*Class(Class clazz) • Adds new GrailsClass for specified class, e.g. addControllerClass(myClass) • get*Class(String name) • Retrieves GrailsClass for given name, e.g. getControllerClass(name) CONFIDENTIAL 19
  • 20. Grails Artifacts  Some resource that fulfills a convention • controllers, services, etc.  Represented by the GrailsClass interface • http://grails.org/doc/latest/api/org/codehaus/groovy/grails/ commons/package-summary.html for API of all artifacts  Add new artifacts via the Artifact API • http://grails.org/Developer+-+Artefact+API CONFIDENTIAL 20
  • 21. Grails Artifacts  Design decision: include or generate artifacts? • Include is more automatic, no explicit step • Including requires workflow to override • Generate requires extra step but is more customizable • Generation is static – old files can get out of date  Overriding domain classes? • Really only an issue with create-drop and update, not with migrations  Overriding controllers? • “un-map” with UrlMappings "/admin/console/$action?/$id?"(controller: "console") "/console/$action?/$id?"(controller: "errors", action: "urlMapping") CONFIDENTIAL 21
  • 22. The GrailsClass Interface  Implemented by Grails artifacts written in Groovy • getPropertyValue(String name) • newInstance() • getName() ← logical name • getFullName() ← class name including package • getShortName() ← class name without package • getPropertyName() ← class name as property name • getClazz() ← actual java.lang.Class CONFIDENTIAL 22
  • 23. Plugin Descriptor  Metadata • version, grailsVersion range, pluginExcludes, dependsOn, etc.  Lifecycle Closures ← Modify XML generated for web.xml at doWithWebDescriptor runtime doWithSpring ← Participate in Spring configuration ← Post ApplicationContext initialization doWithApplicationContext activities doWithDynamicMethods ← Add methods to MetaClasses onChange ← Participate in reload events CONFIDENTIAL 23
  • 24. Configuring Spring class JcrGrailsPlugin { def version = 0.1 Bean name is method name, def dependsOn = [core:0.4] first argument is bean class def doWithSpring = { jcrRepository(RepositoryFactoryBean) { configuration = "classpath:repository.xml" homeDir = "/repo" } } Set properties on the bean } CONFIDENTIAL 24
  • 25. Advantages Of Spring DSL  Just Groovy code, so can contain complex logic dependent on: • environment • project conventions • anything!  Easy to specify complex bean definitions • thanks to Groovy's neat lists and maps syntax CONFIDENTIAL 25
  • 26. Overriding Spring Beans  Use loadAfter to define plugin load order; your beans override other plugins' and Grails'  resources.groovy loads last, so applications can redefine beans there Import com.mycompany.myapp.MyUserDetailsService beans = { userDetailsService(MyUserDetailsService) { grailsApplication = ref('grailsApplication') foo = 'bar' } }  BeanPostProcessor/BeanFactoryPostProcessor CONFIDENTIAL 26
  • 27. Plugging In Dynamic Methods Taken from Grails core, this def doWithDynamicMethods = { ctx -> plugin finds all classes ending application with “Codec” and dynamically .allClasses creates “encodeAsFoo” methods! .findAll { it.name.endsWith("Codec") } .each {clz -> Object .metaClass ."encodeAs${clz.name-'Codec'}" = { clz.newInstance().encode(delegate) } } The “delegate” variable } is equivalent to “this” in } regular methods CONFIDENTIAL 27
  • 28. Reload Events  Grails apps must be reloadable during development • Can mean many things • Plugin's responsibility  Plugins can define watchedResources firing onChange events when modified CONFIDENTIAL 28
  • 29. Example Reloading Plugin class I18nGrailsPlugin { Defines set of files to watch def version = "0.4.2" using Spring Resource pattern def watchedResources = "file:../grails-app/i18n/*.properties" def onChange = { event -> def messageSource = event.ctx.getBean("messageSource") messageSource?.clearCache() } } When one changes, event is fired and plugin responds by clearing message cache CONFIDENTIAL 29
  • 30. The Event Object  event.source • Source of the change – either a Spring Resource or a java.lang.Class if the class was reloaded  event.ctx • the Spring ApplicationContext  event.application • the GrailsApplication  event.manager • the GrailsPluginManager CONFIDENTIAL 30
  • 31. Adding Elements to web.xml def doWithWebDescriptor = { xml → def contextParam = xml.'context-param' contextParam[contextParam.size() - 1] + { 'filter' { 'filter-name'('springSecurityFilterChain') 'filter-class'(DelegatingFilterProxy.name) } } def filterMapping = xml.'filter-mapping' filterMapping[filterMapping.size() - 1] + { 'listener' { 'listener-class'(HttpSessionEventPublisher.name) } } } CONFIDENTIAL 31
  • 32. Dependency Management  Jar files • Prefer BuildConfig.groovy → Maven repos • lib directory is ok if unavailable otherwise  Other plugins • def dependsOn = [springSecurityCore: '1.1 > *'] • def loadAfter = ['controllers']  Grails • def grailsVersion = '1.2.3 > *' CONFIDENTIAL 32
  • 33. BuildConfig.groovy grails.project.dependency.resolution = { inherits 'global' log 'warn' repositories { grailsPlugins() grailsHome() grailsCentral() flatDir name:'myRepo', dirs:'/path/to/repo' mavenCentral() mavenRepo 'http://download.java.net/maven/2/' mavenRepo 'http://my.cool.repo.net/maven/' } CONFIDENTIAL 33
  • 34. BuildConfig.groovy dependencies { runtime 'mysql:mysql-connector-java:5.1.13' compile group: 'commons-httpclient', name: 'commons-httpclient', version: '3.1' build('net.sf.ezmorph:ezmorph:1.0.4', 'net.sf.ehcache:ehcache:1.6.1') { transitive = false } test('com.h2database:h2:1.2.144') { export = false } runtime('org.liquibase:liquibase-core:2.0.1', 'org.hibernate:hibernate-annotations:3.4.0.GA') { excludes 'xml-apis', 'commons-logging' } } } CONFIDENTIAL 34
  • 35. Troubleshooting Dependency Management  Run grails dependency­report • See http://burtbeckwith.com/blog/?p=624 for visualization tips  Increase logging level • log 'warn' → 'info', 'verbose', or 'debug' CONFIDENTIAL 35
  • 36. Scripts  Gant: http://gant.codehaus.org/  Groovy + Ant - XML  Can be used in apps but more common in plugins  Put in plugin's (or app's) scripts directory  _Install.groovy • runs when you run grails install­plugin or when it's transitively installed - don't overwrite! might be reinstall or plugin upgrade CONFIDENTIAL 36
  • 37. Scripts  _Uninstall.groovy • runs when you run grails uninstall­plugin so you can do cleanup, but don't delete user- created/edited stuff  _Upgrade.groovy • runs when you run grails upgrade (not when you upgrade a plugin) CONFIDENTIAL 37
  • 38. Scripts eventCreateWarStart = { name, stagingDir →  _Events.groovy … } • Respond to eventGenerateWebXmlEnd = { build events … }  Naming convention • Prefix with '_' → don't show in grails help • Suffix with '_' → 'global' script, i.e. doesn't need to run in a project dir (e.g. create­app) CONFIDENTIAL 38
  • 39. Scripts  Reuse existing scripts with includeTargets • includeTargets << grailsScript("_GrailsWar")  Include common code in _*Common.groovy • includeTargets << new  File("$cloudFoundryPluginDir/scripts/  _CfCommon.groovy") CONFIDENTIAL 39
  • 40. Testing Scripts  Put tests in test/cli  Extend grails.test.AbstractCliTestCase  stdout and stderr will be in target/cli-output  http://www.cacoethes.co.uk/blog/groovyandgrails/t esting-your-grails-scripts  Run with the rest with grails test­app or alone with grails test­app ­­other CONFIDENTIAL 40
  • 41. Scripts Typical Structure includeTargets << new File( "$cloudFoundryPluginDir/scripts/_CfCommon.groovy") USAGE = ''' grails cf-list-files [path] [--appname] [--instance] ''' target(cfListFiles: 'Display a directory listing') { depends cfInit // implementation of script } def someHelperMethod() { … } setDefaultTarget cfListFiles CONFIDENTIAL 41
  • 42. Custom Artifacts  ControllerMixinArtefactHandler extends ArtefactHandlerAdapter  interface ControllerMixinGrailsClass extends InjectableGrailsClass  DefaultControllerMixinGrailsClass extends AbstractInjectableGrailsClass implements ControllerMixinGrailsClass CONFIDENTIAL 42
  • 43. Custom Artifacts class MyGrailsPlugin { def watchedResources = [ 'file:./grails-app/controllerMixins/**/*ControllerMixin.groovy', 'file:./plugins/*/grails-app/controllerMixins/**/*ControllerMixin.groovy' ] def artefacts = [ControllerMixinArtefactHandler] def onChange = { event → ... } } CONFIDENTIAL 43
  • 45. Testing  Write regular unit and integration tests in test/unit and test/integration  'Install' using inline mechanism in BuildConfig.groovy • grails.plugin.location.'my­plugin' = '../my­plugin'  Test scripts as described earlier  Create test apps programmatically – all of the Spring Security plugins do this with bash scripts CONFIDENTIAL 45
  • 46. Testing  Use build.xml or Gradle to create single target that tests and builds plugin <target name='package' description='Package the plugin' depends='test, doPackage, post-package-cleanup'/>  Use inline plugin or install from zip grails install-plugin /path/to/plugin/grails-myplugin-0.1.zip CONFIDENTIAL 46
  • 47. Source Control and Release Management CONFIDENTIAL 47
  • 48. Becoming A Plugin Developer  Signup at Codehaus xircles • http://xircles.codehaus.org/signup & http://xircles.codehaus.org/projects/grails-plugins/members  Talk about your idea on the mailing list • http://grails.org/Mailing+lists • Summarize your contribution and ask on the dev list for your request to be processed - include your xircles user name in the request  Build (and test!) your plugin and run: • grails publish-plugin  Done! CONFIDENTIAL 48
  • 49. Source Control and Release Management  Internal server for jars & plugins is easy with Artifactory or Nexus repositories { grailsPlugins() grailsHome() mavenRepo "http://yourserver:8081/artifactory/libs-releases-local/" mavenRepo "http://yourserver:8081/artifactory/plugins-releases-local/" grailsCentral() }  Release with grails publish­plugin ­­repository=repo_name grails.project.dependency.distribution = { remoteRepository( id: "repo_name", url: "http://yourserver:8081/artifactory/plugins-snapshots-local/") { authentication username: "admin", password: "password" } } CONFIDENTIAL 49
  • 50. Source Control and Release Management  Use “release” plugin http://grails.org/plugin/release • Will be default in 1.4+, publish-plugin replaces release-plugin • Sends tweet from @grailsplugins and email to plugin forum http://grails-plugins.847840.n3.nabble.com/ • Will check code into SVN for you • disable with ­­noScm or grails.release.scm.enabled = false CONFIDENTIAL 50
  • 51. Best Practices and Tips CONFIDENTIAL 51
  • 52. Best Practices and Tips  Delete anything auto-generated that you don't use • grails-app/views/error.gsp • _Uninstall.groovy and other generated scripts • Empty descriptor callbacks  Exclude files used in development or testing • Use def pluginExcludes = [...] • src/docs • Test artifacts  Use Ivy + Maven repos in BuildConfig.groovy, not lib dir CONFIDENTIAL 52
  • 53. Best Practices and Tips  Write tests  Run them often  Run tests before commit and especially before release (use build.xml)  Create test apps (ideally programmatically)  Programmatically build inline plugin location: def customerName = System.getProperty("customer.name") grails.plugin.location."$customerName" = "customer-plugins/$customerName" CONFIDENTIAL 53
  • 54. Best Practices and Tips  Get to 1.0 • Initial version 0.1 is just a suggestion • People trust 1.0+ more  Start using source control early • Easy to run git init locally and later → github  Support your plugin! CONFIDENTIAL 54
  • 55. Best Practices and Tips  http://grails.org/doc/latest/guide/12.%20Plug-ins.html  http://grails.org/doc/latest/guide/4.%20The %20Command%20Line.html#4.3%20Hooking%20into %20Events  http://www.grails.org/The+Plug-in+Developers+Guide  http://blog.springsource.com/2010/05/18/managing- plugins-with-grails-1-3/ CONFIDENTIAL 55
  • 56. Hackergarten Signup for hackergarten here: http://bit.ly/gr8_hackergarten CONFIDENTIAL 56