Machine specific config

26 views
Skip to first unread message

Colin Harrington

unread,
Nov 11, 2009, 11:27:02 AM11/11/09
to groo...@googlegroups.com
Hey Guys,

I seem to remember a way for a user to have their own machine specific configuration for Grails (overriding Config.groovy selectively)

Anyone know where that would have been or what mechanism that would be?

Thank you,

Colin Harrington
colin.ha...@gmail.com

Ted Naleid

unread,
Nov 11, 2009, 11:35:07 AM11/11/09
to groo...@googlegroups.com
I'm not aware of any built-in way to do this.  I had a blog post a little while ago that demonstrated a technique that you might be able to leverage to do something like this, but there's still some leg work that'd need to be done to make it happen:


I've primarily used this method with the DataSource.groovy file.  We use it where we have a domain plugin that has all of our domain classes and a DataSourceBase.groovy file with our database configuration information in it.  Then all of the different applications that we install that domain plugin in will just call out to the DataSourceBase.groovy class so that we only have our database configuration in one place, rather than replicated for every app we use.

Not exactly the same, but a related problem.

HTH,
Ted

Scott Vlaminck

unread,
Nov 11, 2009, 11:46:44 AM11/11/09
to groo...@googlegroups.com
In Config.groovy, I've used grails.config.location:

http://grails.org/doc/1.1/guide/3.%20Configuration.html#3.1.1%20Built%20in%20options

e.g.
grails.config.locations = [ "file:${userHome}/override-config.groovy"]

The ${userHome} part obviously points to the user's home directory.
You could also access something in the project directory that was
ignored by your version control.

Scott


-------------------------------------------------
Scott Vlaminck // sc...@refactr.com
Refactr LLC // http://refactr.com
mobile // 612-386-9382
-------------------------------------------------

Ted Naleid

unread,
Nov 11, 2009, 11:49:06 AM11/11/09
to groo...@googlegroups.com
Cool!  I didn't know about that.  

Colin Harrington

unread,
Nov 11, 2009, 11:58:39 AM11/11/09
to groo...@googlegroups.com
Thank you Scott!

That is exactly what I was looking for!

~ Colin

Colin Harrington

unread,
Nov 12, 2009, 12:50:45 PM11/12/09
to groo...@googlegroups.com
Ted,

I actually needed the grails.config.locations and the ability to override properties in the Datasource.  How did you end up calling out to your DataSourceBase.groovy?  At what level did you do that?

~ Colin

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the "Groovy Users of Minnesota" group.

To post to this group, send email to groo...@googlegroups.com
To unsubscribe from this group, send email to groovymn-u...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/groovymn?hl=en
-~----------~----~----~----~------~----~------~--~---



Ted Naleid

unread,
Nov 12, 2009, 1:19:56 PM11/12/09
to groo...@googlegroups.com
On Thu, Nov 12, 2009 at 11:50 AM, Colin Harrington <colin.ha...@gmail.com> wrote:
Ted,

I actually needed the grails.config.locations and the ability to override properties in the Datasource.  How did you end up calling out to your DataSourceBase.groovy?  At what level did you do that?

~ Colin


Our setup is similar to what you saw at Carol.  We have a "domain" local plugin with all of our domain object in it that's installed into various applications (admin, portal, batch, imports, report).

That gives us a lot more flexibility in security as well as how we deploy and load balance the app across various application servers.

In the domain plugin, we have a file at grails-app/conf/DataSourceBase.groovy  that looks like a normal DataSource.groovy file.  Ex:

grails-app/conf/DataSourceBase.groovy

dataSource {
  pooled = true
  driverClassName = "com.mysql.jdbc.Driver"
}
hibernate {
     // hibernate settings
}
// environment specific settings
environments {
development {
dataSource {
//dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:mysql://localhost/mySchemaName"
username = "myDbUsername"
password = "myDbPassword"
}
}
        // ... other environments
}

Then, in domain, and in every other application that we install domain in, we modified the original DataSource.groovy file to look like this:

import com.warmhealth.domain.config.ComposedConfigScript

class DataSource extends ComposedConfigScript {
    def run() {
        includeScript( DataSourceBase )
    }
}

And in domain/src/groovy/com/warmhealth/domain/ComposedConfigScript.groovy, we have this:

package com.warmhealth.domain.config


public abstract class ComposedConfigScript extends Script {
    def includeScript(scriptClass) {
        def scriptInstance = scriptClass.newInstance()
        scriptInstance.metaClass = this.metaClass
        scriptInstance.binding = new ConfigBinding(this.getBinding().callable)
        scriptInstance.&run.call()
    }
}

This allows us to define our database connection info in a single place (DataSourceBase) and have that automatically pulled in for all of the apps that we actually use it in.

We aren't currently overriding any of the values on an app by app basis, but you should be able to do that using the technique outlined in this blog post:


HTH,
-Ted

Robert Fischer

unread,
Nov 12, 2009, 1:32:11 PM11/12/09
to groo...@googlegroups.com
I regularly allow system properties to specify names

dataSource {
username = System.properties["db.login.name"] ?: "some default"
password = System.properties["db.login.pass"] ?: "some other default"
}

Using Properties#load(InputStream), you could allow another file to override it:

def configFile = new File(System.properties["myapp.config.file"] ?: "default.config")
configFile.createNewFile() // aka "touch()": see API
def props = new Properties(System.properties)
props.load(new BufferedInputStream(new FileInputStream(configFile)))
dataSource {
username = props["db.login.name"] ?: "some default"
password = props["db.login.pass"] ?: "some other default"
}

Or even, I suppose...

def configFile = new File(System.properties["myapp.config.file"])
def props = new Properties()
props.load(new BufferedInputStream(new FileInputStream(configFile)))
dataSource {
props.each { k, v ->
delegate."$k" = v
}
}

Although I haven't tried that last stunt.

~~ Robert Fischer, Smokejumper IT Consulting.
Enfranchised Mind Blog http://EnfranchisedMind.com/blog

Grails Expert Retainer Services
http://smokejumperit.com/grails-retainer/
> --

Colin Harrington

unread,
Nov 25, 2009, 4:01:38 PM11/25/09
to groo...@googlegroups.com
Thanks for the help!  This is what I ended up finding out:

Grails 1.1.1 create-app generates a Config.groovy with this as the first few lines that would have told me what I need to know if I actually took the time to read it:
// locations to search for config files that get merged into the main config
// config files can either be Java properties files or ConfigSlurper scripts

// grails.config.locations = [ "classpath:${appName}-config.properties",
//                             "classpath:${appName}-config.groovy",
//                             "file:${userHome}/.grails/${appName}-config.properties",
//                             "file:${userHome}/.grails/${appName}-config.groovy"]

// if(System.properties["${appName}.config.location"]) {
//    grails.config.locations << "file:" + System.properties["${appName}.config.location"]
// }
It helps to be able to read :-)
*Robert checkout the last 3 lines - it already does what you were suggesting - cool eh?

So in my case all I had to do was put this in Config.groovy:
if (new File("${userHome}/.grails/${appName}-config.groovy").exists()){
    grails.config.locations = ["file:${userHome}/.grails/${appName}-config.groovy"]
}

which allowed me to override properties by doing something like this in my ~/.grails/${appName}-config.groovy :
username = "sa"
password = "sekret"

// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "create-drop" // use your imagination...
        }
    }
}

I also ran across a little gem that you can do the same type of config merging with your BuildConfig.groovy by implementing a ~/.grails/settings.groovy file. (yes its hardcoded rather than a config.locations property in BuildConfig.groovy - see BuildSettings.groovy for more)

Now I really wish there was a way to set defaults for things like server.port in the configs.

~ Colin Harrington
colin.ha...@gmail.com

Robert Fischer

unread,
Nov 25, 2009, 6:05:20 PM11/25/09
to groo...@googlegroups.com
Nifty!

~~ Robert.
> server.port in the configs <http://jira.codehaus.org/browse/GRAILS-1861>.
>
> ~ Colin Harrington
> colin.ha...@gmail.com <mailto:colin.ha...@gmail.com>
>
>
>
> On Thu, Nov 12, 2009 at 12:32 PM, Robert Fischer
> <robert....@smokejumperit.com
> <mailto:robert....@smokejumperit.com>> wrote:
>
> I regularly allow system properties to specify names
>
> dataSource {
> username = System.properties["db.login.name
> <http://db.login.name>"] ?: "some default"
> password = System.properties["db.login.pass"] ?: "some other default"
> }
>
> Using Properties#load(InputStream), you could allow another file
> to override it:
>
> def configFile = new File(System.properties["myapp.config.file"]
> ?: "default.config")
> configFile.createNewFile() // aka "touch()": see API
> def props = new Properties(System.properties)
> props.load(new BufferedInputStream(new FileInputStream(configFile)))
> dataSource {
> username = props["db.login.name <http://db.login.name>"] ?: "some
> default"
> password = props["db.login.pass"] ?: "some other default"
> }
>
> Or even, I suppose...
>
> def configFile = new File(System.properties["myapp.config.file"])
> def props = new Properties()
> props.load(new BufferedInputStream(new FileInputStream(configFile)))
> dataSource {
> props.each { k, v ->
> delegate."$k" = v
> }
> }
>
> Although I haven't tried that last stunt.
>
> ~~ Robert Fischer, Smokejumper IT Consulting.
> Enfranchised Mind Blog http://EnfranchisedMind.com/blog
>
> Grails Expert Retainer Services
> http://smokejumperit.com/grails-retainer/
>
>
> Ted Naleid wrote:
> > On Thu, Nov 12, 2009 at 11:50 AM, Colin Harrington
> > <colin.ha...@gmail.com <mailto:colin.ha...@gmail.com>
> <mailto:colin.ha...@gmail.com
> <mailto:groo...@googlegroups.com>
> > To unsubscribe from this group, send email to
> > groovymn-u...@googlegroups.com
> <mailto:groovymn-u...@googlegroups.com>
> > For more options, visit this group at
> > http://groups.google.com/group/groovymn?hl=en
>
> --
> You received this message because you are subscribed to the
> "Groovy Users of Minnesota" group.
>
> To post to this group, send email to groo...@googlegroups.com
> <mailto:groo...@googlegroups.com>
> To unsubscribe from this group, send email to
> groovymn-u...@googlegroups.com
> <mailto:groovymn-u...@googlegroups.com>
Reply all
Reply to author
Forward
0 new messages