Unified configuration refactor
Objective
There is a requirement for provided pre-init configuration settings that can be picked up by plugins during load time. There are also a number of other disparate configuration points in Grails 0.5.5 that should be rationalized before the 1.0 release:
- DataSources - are classes needlessly, and hence require a file per environment
- Bootstrap - currently does not provide per-environment support out of the box, and does not provide a means to configure spring beans or metaclasses etc
- resources.xml - ugly XML that should be handled akin to doWithSpring in plugins, as per previous comment on Bootstrap
There has also been a previous proposal to reorganize conf/ into per-environment directories. This is probably overkill, especially with the requirement for "common" configuration also that is always executed.
Proposal
The crux of it is quite simple:
- Favour a environment-aware DSLs over per-environment class files.
- Use script files instead of classes where performance will not be an issue (scripts perform poorly in a multithreaded environment so are unsuitable for supply closures to EMCs for example)
- Supply doWithXXX functionality for application bootstrapping in the same way it is done for plugins
Property configuration file
Here properties are defined that are accessible to plugins and the application, and spring beans, based on current environment.
// Top-level assignments apply to all environments grails.webflow.stateless = true env { development { resources.URL = "http://localhost:8088" smtp { mail.host = 'smtp.myisp.com' mail.auth.user = 'server' } } production { resources.URL = "http://localhost:80/resources" smtp.mail.host = 'localhost' } }
Datasource configuration file
Replacing XXXXDataSource.groovy we have single file DataSource.groovy:
// Applies to all envs pooling = true env { dev { dbCreate = "create-drop" // one of 'create', 'create-drop','update' url = "jdbc:hsqldb:mem:devDB" driverClassName = "org.hsqldb.jdbcDriver" username = "sa" password = "" } production { dbCreate = "update" // one of 'create', 'create-drop','update' url = "jdbc:mysql://localhost/appDB" driverClassName = "com.mysql.jdbc.Driver" username = "admin" password = "secret" } }
Bootstrap
ApplicationBootstrap will remain a class, as it may affect metaclasses and hence performance is a consideration.
Q: How to factor environments in here? Should 'env' not be used here too, for consistency?
class ApplicationBootstrap {
def init = { ServletContext sc ->
dev {
...
}
production {
...
}
}
def destroy = {
}
def doWithSpring = {
dev {
...
}
production {
...
}
}
def doWithApplicationContext = {
}
}
Two-phase configuration
Configuration will occur in two phases, first the config will be built-up into an evaluatable "config" object which can be inspected by plugins:
if(!config.dataSource?.driverClassName) // configure default driver
Finally after plug-in initialisation configuration values will be set on bean definitions in a similar way to PropertyOverrideConfigurator
Related Issues
http://jira.codehaus.org/browse/GRAILS-729
http://jira.codehaus.org/browse/GRAILS-289
Comments (1)
Jun 20, 2007
Peter Ledbrook says:
How would custom plugins add their own configuration files? Would they need to r...How would custom plugins add their own configuration files? Would they need to register an artefact handler, or would there be a naming convention on the files to ensure that Grails loads them?