(Quick Reference)

12.7 Hooking into Runtime Configuration - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: null

12.7 Hooking into Runtime Configuration

Grails provides a number of hooks to leverage the different parts of the system and perform runtime configuration by convention.

Hooking into the Grails Spring configuration

First, you can hook in Grails runtime configuration by providing a property called doWithSpring which is assigned a block of code. For example the following snippet is from one of the core Grails plugins that provides i18n support:

Grails ofrece una serie de puntos de extensión donde inyectar código para aprovechar las diferentes partes del sistema y realizar configuración por convención en tiempo de ejecución.

Puntos de extensión en la configuración de Spring de Grails.

En primer lugar, se puede inyectar funcionalidad en la configuración de tiempo de ejecución de Grails usando una propiedad llamada doWithSpring a la que se le asigna un bloque de código. Por ejemplo el siguiente fragmento es de uno de los plugins del núcleo Grails que ofrece soporte para i18n:

import org.springframework.web.servlet.i18n.CookieLocaleResolver
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor
import org.springframework.context.support.ReloadableResourceBundleMessageSource

class I18nGrailsPlugin {

def version = "0.1"

def doWithSpring = { messageSource(ReloadableResourceBundleMessageSource) { basename = "WEB-INF/grails-app/i18n/messages" } localeChangeInterceptor(LocaleChangeInterceptor) { paramName = "lang" } localeResolver(CookieLocaleResolver) } }

This plugin configures the Grails messageSource bean and a couple of other beans to manage Locale resolution and switching. It using the Spring Bean Builder syntax to do so.

Participating in web.xml Generation

Grails generates the WEB-INF/web.xml file at load time, and although plugins cannot change this file directly, they can participate in the generation of the file. A plugin can provide a doWithWebDescriptor property that is assigned a block of code that gets passed the web.xml as an XmlSlurper GPathResult.

Add servlet and servlet-mapping

Consider this example from the ControllersPlugin:

Este plugin configura el bean de Grails messageSource asi como un par de otros beans para gestionar la resolución y el cambio del Locale. Utiliza la sintaxis Spring Bean Builder para hacer esto.

Participar en la generación del fichero web.xml

Grails genera el fichero WEB-INF/web.xml en tiempo de carga, y aunque los plugins no pueden cambiar este fichero directamente, pueden participar en su generación. Un plugin puede contener de una propiedad doWithWebDescriptor que contiene un bloque de código que es pasado al web.xml como un XmlSlurper GPathResult.

Añadir un servlet y un servlet-mapping

Considere este ejemplo perteneciente al ControllersPlugins

def doWithWebDescriptor = { webXml ->

def mappingElement = webXml.'servlet-mapping'

def lastMapping = mappingElement[mappingElement.size() - 1] lastMapping + { 'servlet-mapping' { 'servlet-name'("grails") 'url-pattern'("*.dispatch") } } }

Here the plugin gets a reference to the last <servlet-mapping> element and appends Grails' servlet after it using XmlSlurper's ability to programmatically modify XML using closures and blocks.

Add filter and filter-mapping

Adding a filter with its mapping works a little differently. The location of the <filter> element doesn't matter since order is not important, so it's simplest to insert your custom filter definition immediately after the last <context-param> element. Order is important for mappings, but the usual approach is to add it immediately after the last <filter> element like so:

En este caso, el plugin obtiene una referencia al último elemento <servlet-mapping> y añade el servlet de Grails despues de él usando la habilidad de XmlSlurper para modificar XML usando closures y bloques.

añadir filter y filter-mappings

Este ejemplo para añadir un filtro y su mapeo funciona de manera un poco diferente. El lugar del elemento <filter> no importa dado que el orden no es importante, por lo que es más sencillo insertar nuestra definición de filtro personalizada inmediatamente despues del último elemento <context-param>. Por el contrario el orden si que es importante para los mapeos, pero la aproximación usual es añadir el mapeo inmediatamente despues del último elmento <filter> de esta manera:

def doWithWebDescriptor = { webXml ->

def contextParam = webXml.'context-param'

contextParam[contextParam.size() - 1] + { 'filter' { 'filter-name'('springSecurityFilterChain') 'filter-class'(DelegatingFilterProxy.name) } }

def filter = webXml.'filter' filter[filter.size() - 1] + { 'filter-mapping'{ 'filter-name'('springSecurityFilterChain') 'url-pattern'('/*') } } }

In some cases you need to ensure that your filter comes after one of the standard Grails filters, such as the Spring character encoding filter or the SiteMesh filter. Fortunately you can insert filter mappings immediately after the standard ones (more accurately, any that are in the template web.xml file) like so:

En algúnos casos es necesarkio asegurar que nuestro filtro se inserta despues de uno de los filtros estandar de Grails, como por ejemplo el filtro "character encoding" de Spring o el filtro de SiteMesh. Afortunadamente es posible insertar el mapeo del filtro inmediatamente despues de los estandar (más exactamente, despues de cualquiera definido en la plantilla del web.xml) de esta manera:

def doWithWebDescriptor = { webXml ->
    ...

// Insert the Spring Security filter after the Spring // character encoding filter. def filter = webXml.'filter-mapping'.find { it.'filter-name'.text() == "charEncodingFilter" }

filter + { 'filter-mapping'{ 'filter-name'('springSecurityFilterChain') 'url-pattern'('/*') } } }

Doing Post Initialisation Configuration

Sometimes it is useful to be able do some runtime configuration after the Spring ApplicationContext has been built. In this case you can define a doWithApplicationContext closure property.

Haciendo configuración en la Post Instalación

En determinadas ocasiones es útil ser capaz de realizar configuración en runtime despues de que el ApplicationContext de Spring haya sido construido. En este caso, es posible definir una propidad closure doWithApplicationContext

class SimplePlugin {

def name = "simple" def version = "1.1"

def doWithApplicationContext = { appCtx -> def sessionFactory = appCtx.sessionFactory // do something here with session factory } }