15.7 Hooking into Runtime Configuration - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 2.3.8
15.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 calleddoWithSpring
which is assigned a block of code. For example the following snippet is from one of the core Grails plugins that provides i18n support:import org.springframework.web.servlet.i18n.CookieLocaleResolver import org.springframework.web.servlet.i18n.LocaleChangeInterceptor import org.springframework.context.support.ReloadableResourceBundleMessageSourceclass I18nGrailsPlugin { def version = "0.1" def doWithSpring = { messageSource(ReloadableResourceBundleMessageSource) { basename = "WEB-INF/grails-app/i18n/messages" } localeChangeInterceptor(LocaleChangeInterceptor) { paramName = "lang" } localeResolver(CookieLocaleResolver) } }
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 theWEB-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
:def doWithWebDescriptor = { webXml -> def mappingElement = webXml.'servlet-mapping' def lastMapping = mappingElement[mappingElement.size() - 1] lastMapping + { 'servlet-mapping' { 'servlet-name'("grails") 'url-pattern'("*.dispatch") } } }
<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: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'('/*') } } }
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 adoWithApplicationContext
closure property.class SimplePlugin { def name = "simple" def version = "1.1" def doWithApplicationContext = { appCtx -> def sessionFactory = appCtx.sessionFactory // do something here with session factory } }