Grails
  1. Grails
  2. GRAILS-7926

Declarative plugin configuration values and defaults, and ability for plugins to configure other plugins

    Details

    • Type: New Feature New Feature
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.3.7, 2.0-M1
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      Problem:

      1. Plugins use any config prefix they like which means the user cannot work them out themselves.
      2. The user cannot tell what config options are available to them without reading all the docs, and it is easy for Plugin authors to forget to document them
      3. Plugins cannot easily configure other plugins.
      4. Plugins cannot easily supply default configuration to the application (without merging with or writing to Config.groovy)

      Proposal:

      • A doWithConfigOptions convention on plugins that uses a DSL to declare the available config options on the plugin, default values for each, custom validators and any other useful metadata.
      • Automatic merging of plugin default values defined in the dWCO DSL into main application config if application does not define a value
      • Automatic merging of one or more external XXXPluginConfig.groovy files containing only config values for declared plugin options
      • A doWithConfig convention on plugins that allows the plugin to change application-wide configuration settings, or plugin-namespaced config options, with access to the existing config object to read existing values
      • Support for legacy configuration options in plugins, where the old options supplied by the application are copied into the new plugin-namespaced values so that the plugin reads only the new config values
      • Setting of plugin-namespaced config values in implied dependency order, such that plugins can configure other plugins without explicitly having a loadBefore
      • Cause accesses to undeclared plugin namespaced config options to fail fast, thus preventing usage of undocumented config by plugin authors.

      I've already implemented most of this locally - the parts are not yet implemented.

      Example:

        def doWithConfigOptions = { 
              'guest.roles'(defaultValue:['ROLE_GUEST'], validator: { v -> 
                  (v == null || !(v instanceof List)) ? 'A role list is required' : null
              })
              'post.login.url'(defaultValue:[uri:'/'])
              'post.login.always_default'(defaultValue:true)
        }
      
        def doWithConfig = { config ->
      
              application {
                  grails.plugins.springsecurity.interceptUrlMap = [
                     '/admin/**':     ['ROLE_ADMIN'],
                     '/**':           ['ROLE_USER']
                  ]
              
                  grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
      
                  grails.plugins.springsecurity.successHandler.defaultTargetUrl = 
                      config.plugin.springFreshSecurity.post.login.url
              }
      
              someOtherPlugin {
                  // Here is where we set x.y = z with automatic namespacing to plugin.<pluginName>.x.y
                  // and automatically setting these per plugin before that plugin has doWithXXX called
                  x.y = z
              }
          }
      
      

      Risks:

      Implementing this in core would mean that the plugin ecosystem may upgrade to this and then no longer support older grails releases any more.

      My suggestion is that this is implemented as a plugin that works with at least the 1.3.x line.

        Activity

        Marc Palmer created issue -
        Marc Palmer made changes -
        Field Original Value New Value
        Description Problem:

        # Plugins use any config prefix they like which means the user cannot work them out themselves.
        # The user cannot tell what config options are available to them without reading all the docs.
        # Plugins cannot easily configure other plugins.
        # Plugins cannot easily supply default configuration to the application (without merging with or writing to Config.groovy)

        Proposal:

        * A doWithConfigOptions convention on plugins that uses a DSL to declare the available config options on the plugin, default values for each, custom validators and any other useful metadata.
        * Automatic merging of plugin default values defined in the dWCO DSL into main application config if application does not define a value
        * Automatic merging of one or more external XXXPluginConfig.groovy files containing only config values for declared plugin options
        * A doWithConfig convention on plugins that allows the plugin to change application-wide configuration settings, or plugin-namespaced config options, with access to the existing config object to read existing values
        * (-) Support for legacy configuration options in plugins, where the old options supplied by the application are copied into the new plugin-namespaced values so that the plugin reads only the new config values
        * (-) Setting of plugin-namespaced config values in implied dependency order, such that plugins can configure other plugins without explicitly having a loadBefore

        I've already implemented most of this locally - the parts (-) are not yet implemented.

        Example:

        {code}
          def doWithConfigOptions = {
                'guest.roles'(defaultValue:['ROLE_GUEST'], validator: { v ->
                    (v == null || !(v instanceof List)) ? 'A role list is required' : null
                })
                'post.login.url'(defaultValue:[uri:'/'])
                'post.login.always_default'(defaultValue:true)
          }

          def doWithConfig = { config ->

                application {
                    grails.plugins.springsecurity.interceptUrlMap = [
                       '/admin/**': ['ROLE_ADMIN'],
                       '/**': ['ROLE_USER']
                    ]
                
                    grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap

                    grails.plugins.springsecurity.successHandler.defaultTargetUrl =
                        config.plugin.springFreshSecurity.post.login.url
                }

                someOtherPlugin {
                    // Here is where we set x.y = z with automatic namespacing to plugin.<pluginName>.x.y
                    // and automatically setting these per plugin before that plugin has doWithXXX called
                    x.y = z
                }
            }

        {code}
        Problem:

        # Plugins use any config prefix they like which means the user cannot work them out themselves.
        # The user cannot tell what config options are available to them without reading all the docs.
        # Plugins cannot easily configure other plugins.
        # Plugins cannot easily supply default configuration to the application (without merging with or writing to Config.groovy)

        Proposal:

        * A doWithConfigOptions convention on plugins that uses a DSL to declare the available config options on the plugin, default values for each, custom validators and any other useful metadata.
        * Automatic merging of plugin default values defined in the dWCO DSL into main application config if application does not define a value
        * Automatic merging of one or more external XXXPluginConfig.groovy files containing only config values for declared plugin options
        * A doWithConfig convention on plugins that allows the plugin to change application-wide configuration settings, or plugin-namespaced config options, with access to the existing config object to read existing values
        * (-) Support for legacy configuration options in plugins, where the old options supplied by the application are copied into the new plugin-namespaced values so that the plugin reads only the new config values
        * (-) Setting of plugin-namespaced config values in implied dependency order, such that plugins can configure other plugins without explicitly having a loadBefore

        I've already implemented most of this locally - the parts (-) are not yet implemented.

        Example:

        {code}
          def doWithConfigOptions = {
                'guest.roles'(defaultValue:['ROLE_GUEST'], validator: { v ->
                    (v == null || !(v instanceof List)) ? 'A role list is required' : null
                })
                'post.login.url'(defaultValue:[uri:'/'])
                'post.login.always_default'(defaultValue:true)
          }

          def doWithConfig = { config ->

                application {
                    grails.plugins.springsecurity.interceptUrlMap = [
                       '/admin/**': ['ROLE_ADMIN'],
                       '/**': ['ROLE_USER']
                    ]
                
                    grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap

                    grails.plugins.springsecurity.successHandler.defaultTargetUrl =
                        config.plugin.springFreshSecurity.post.login.url
                }

                someOtherPlugin {
                    // Here is where we set x.y = z with automatic namespacing to plugin.<pluginName>.x.y
                    // and automatically setting these per plugin before that plugin has doWithXXX called
                    x.y = z
                }
            }

        {code}

        Risks:

        Implementing this in core would mean that the plugin ecosystem may upgrade to this and then no longer support older grails releases any more.

        My suggestion is that this is implemented as a plugin that works with at least the 1.3.x line.
        Marc Palmer made changes -
        Description Problem:

        # Plugins use any config prefix they like which means the user cannot work them out themselves.
        # The user cannot tell what config options are available to them without reading all the docs.
        # Plugins cannot easily configure other plugins.
        # Plugins cannot easily supply default configuration to the application (without merging with or writing to Config.groovy)

        Proposal:

        * A doWithConfigOptions convention on plugins that uses a DSL to declare the available config options on the plugin, default values for each, custom validators and any other useful metadata.
        * Automatic merging of plugin default values defined in the dWCO DSL into main application config if application does not define a value
        * Automatic merging of one or more external XXXPluginConfig.groovy files containing only config values for declared plugin options
        * A doWithConfig convention on plugins that allows the plugin to change application-wide configuration settings, or plugin-namespaced config options, with access to the existing config object to read existing values
        * (-) Support for legacy configuration options in plugins, where the old options supplied by the application are copied into the new plugin-namespaced values so that the plugin reads only the new config values
        * (-) Setting of plugin-namespaced config values in implied dependency order, such that plugins can configure other plugins without explicitly having a loadBefore

        I've already implemented most of this locally - the parts (-) are not yet implemented.

        Example:

        {code}
          def doWithConfigOptions = {
                'guest.roles'(defaultValue:['ROLE_GUEST'], validator: { v ->
                    (v == null || !(v instanceof List)) ? 'A role list is required' : null
                })
                'post.login.url'(defaultValue:[uri:'/'])
                'post.login.always_default'(defaultValue:true)
          }

          def doWithConfig = { config ->

                application {
                    grails.plugins.springsecurity.interceptUrlMap = [
                       '/admin/**': ['ROLE_ADMIN'],
                       '/**': ['ROLE_USER']
                    ]
                
                    grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap

                    grails.plugins.springsecurity.successHandler.defaultTargetUrl =
                        config.plugin.springFreshSecurity.post.login.url
                }

                someOtherPlugin {
                    // Here is where we set x.y = z with automatic namespacing to plugin.<pluginName>.x.y
                    // and automatically setting these per plugin before that plugin has doWithXXX called
                    x.y = z
                }
            }

        {code}

        Risks:

        Implementing this in core would mean that the plugin ecosystem may upgrade to this and then no longer support older grails releases any more.

        My suggestion is that this is implemented as a plugin that works with at least the 1.3.x line.
        Problem:

        # Plugins use any config prefix they like which means the user cannot work them out themselves.
        # The user cannot tell what config options are available to them without reading all the docs, and it is easy for Plugin authors to forget to document them
        # Plugins cannot easily configure other plugins.
        # Plugins cannot easily supply default configuration to the application (without merging with or writing to Config.groovy)

        Proposal:

        * A doWithConfigOptions convention on plugins that uses a DSL to declare the available config options on the plugin, default values for each, custom validators and any other useful metadata.
        * Automatic merging of plugin default values defined in the dWCO DSL into main application config if application does not define a value
        * Automatic merging of one or more external XXXPluginConfig.groovy files containing only config values for declared plugin options
        * A doWithConfig convention on plugins that allows the plugin to change application-wide configuration settings, or plugin-namespaced config options, with access to the existing config object to read existing values
        * (-) Support for legacy configuration options in plugins, where the old options supplied by the application are copied into the new plugin-namespaced values so that the plugin reads only the new config values
        * (-) Setting of plugin-namespaced config values in implied dependency order, such that plugins can configure other plugins without explicitly having a loadBefore
        * (-) Cause accesses to undeclared plugin namespaced config options to fail fast, thus preventing usage of undocumented config by plugin authors.

        I've already implemented most of this locally - the parts (-) are not yet implemented.

        Example:

        {code}
          def doWithConfigOptions = {
                'guest.roles'(defaultValue:['ROLE_GUEST'], validator: { v ->
                    (v == null || !(v instanceof List)) ? 'A role list is required' : null
                })
                'post.login.url'(defaultValue:[uri:'/'])
                'post.login.always_default'(defaultValue:true)
          }

          def doWithConfig = { config ->

                application {
                    grails.plugins.springsecurity.interceptUrlMap = [
                       '/admin/**': ['ROLE_ADMIN'],
                       '/**': ['ROLE_USER']
                    ]
                
                    grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap

                    grails.plugins.springsecurity.successHandler.defaultTargetUrl =
                        config.plugin.springFreshSecurity.post.login.url
                }

                someOtherPlugin {
                    // Here is where we set x.y = z with automatic namespacing to plugin.<pluginName>.x.y
                    // and automatically setting these per plugin before that plugin has doWithXXX called
                    x.y = z
                }
            }

        {code}

        Risks:

        Implementing this in core would mean that the plugin ecosystem may upgrade to this and then no longer support older grails releases any more.

        My suggestion is that this is implemented as a plugin that works with at least the 1.3.x line.
        Burt Beckwith made changes -
        Workflow Grails [ 62342 ] Grails2 [ 63988 ]
        Show
        Daniel Henrique Alves Lima added a comment - http://grails.1312388.n4.nabble.com/Plugins-and-their-default-configuration-td3658265.html http://jira.grails.org/browse/GRAILS-7775
        Hide
        Daniel Henrique Alves Lima added a comment - - edited

        Hi Marc.

        In regard to the "Grails Platform Plugin" (https://github.com/Grailsrocks/grails-plugin-platform) can you keep the "Theming API" detached from the "Configuration API"? Because I'm using Grails for non-web applications and the non-web specific plugins (such as GPars or Quartz) were not supposed to inherit the Theming API when using the Configuration API. Or won't the Theming API affect applications like that (= running out of a web container)?

        Thanks in advance.

        Best regards,

        Daniel.

        Show
        Daniel Henrique Alves Lima added a comment - - edited Hi Marc. In regard to the "Grails Platform Plugin" ( https://github.com/Grailsrocks/grails-plugin-platform ) can you keep the "Theming API" detached from the "Configuration API"? Because I'm using Grails for non-web applications and the non-web specific plugins (such as GPars or Quartz) were not supposed to inherit the Theming API when using the Configuration API. Or won't the Theming API affect applications like that (= running out of a web container)? Thanks in advance. Best regards, Daniel.
        Burt Beckwith made changes -
        Workflow Grails2 [ 63988 ] jira [ 77990 ]
        Burt Beckwith made changes -
        Workflow jira [ 77990 ] Grails2 [ 80126 ]
        Peter Ledbrook made changes -
        Last Reviewed 01/Jan/10
        Peter Ledbrook made changes -
        Workflow Grails2 [ 80126 ] jira [ 88708 ]
        Peter Ledbrook made changes -
        Workflow jira [ 88708 ] Grails2 [ 96869 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            Marc Palmer
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Last Reviewed:

              Development