5

As I am trying to write a Grails Plugin, I stumbled upon two problems:

  • how do I modify one of the configuration files like Config.groovy or DataSource.groovy from witin the _install.groovy script? It is easy to append something to those files, but how do I modify it in a clean way? text.replaceAll()? Or should I create a new config file?
  • how do I get the name of the current application into which the plugin will be installed? I tried to use app.name and appName but both do not work.

Is there maybe somewhere a good tutorial on creating plugins which I haven't found yet?

rdmueller
  • 10,742
  • 10
  • 69
  • 126

3 Answers3

5

Here is an example of editing configuration files from scripts/_Install.groovy.
My plugin copies three files to the target directory.

  • .hgignore is used for version control,
  • DataSource.groovy replaces the default version, and
  • SecurityConfig.groovy contains extra settings.

I prefer to edit the application's files as little as possible, especially because I expect to change the security setup a few years down the road. I also need to use properties from a jcc-server-config.properties file which is customized for each application server in our system.

Copying the files is easy.

println ('* copying .hgignore ')
ant.copy(file: "${pluginBasedir}/src/samples/.hgignore",
         todir: "${basedir}")
println ('* copying SecurityConfig.groovy')
ant.copy(file: "${pluginBasedir}/src/samples/SecurityConfig.groovy",
         todir: "${basedir}/grails-app/conf")
println ('* copying DataSource.groovy')
ant.copy(file: "${pluginBasedir}/src/samples/DataSource.groovy",
         todir: "${basedir}/grails-app/conf")

The hard part is getting Grails to pick up the new configuration file. To do this, I have to edit the application's grails-app/conf/Config.groovy. I will add two configuration files to be found on the classpath.

println ('* Adding configuration files to grails.config.locations');
// Add configuration files to grails.config.locations.
def newConfigFiles = ["classpath:jcc-server-config.properties", 
                      "classpath:SecurityConfig.groovy"]
// Get the application's Config.groovy file
def cfg = new File("${basedir}/grails-app/conf/Config.groovy");
def cfgText = cfg.text
def appendedText = new StringWriter()
appendedText.println ""
appendedText.println ("// Added by edu-sunyjcc-addons plugin");
// Slurp the configuration so we can look at grails.config.locations.
def config = new ConfigSlurper().parse(cfg.toURL());
// If it isn't defined, create it as a list.
if (config.grails.config.locations.getClass() == groovy.util.ConfigObject) {
    appendedText.println('grails.config.locations = []');
} else {
    // Don't add configuration files that are already on the list.
    newConfigFiles = newConfigFiles.grep {
      !config.grails.config.locations.contains(it)
    };
}
// Add each surviving location to the list.
newConfigFiles.each {
    // The name will have quotes around it...
    appendedText.println "grails.config.locations << \"$it\"";
}
// Write the new configuration code to the end of Config.groovy.
cfg.append(appendedText.toString());

The only problem is adding SecurityConfig.groovy to the classpath. I found that you can do that by creating the following event in the plugin's /scripts/Events.groovy.

eventCompileEnd = {
    ant.copy(todir:classesDirPath) {
      fileset(file:"${basedir}/grails-app/conf/SecurityConfig.groovy")
    }
}

Ed.

Big Ed
  • 1,056
  • 9
  • 20
  • that's great code for adding new config files. I still wonder what's the best way to change (for instance) the default dataSource configuration... Maybe I just add a comment to the top of the old file and overwrite the config in my new external files... – rdmueller Mar 21 '12 at 15:20
  • 1
    Thanks. I figure that the default `DataSource.groovy` is not very valuable and easy to replace, so I just overwrite it with my own. – Big Ed Mar 21 '12 at 18:09
3

You might try changing the configuration within the MyNiftyPlugin.groovy file (assuming that your plugin is named my-nifty). I've found that I can change the configuration values within the doWithApplicationContext closure. Here's an example.

def doWithApplicationContext = { applicationContext ->  
  def config = application.config;
  config.edu.mycollege.server.name = 'http://localhost:8080'
  config.edu.mycollege.server.instance = 'pprd'
}

The values you enter here do show up in the grailsApplication.config variable at run time. If it works for you, it will be a neater solution, because it doesn't require changes to the client project.

I must qualify that with the fact that I wasn't able to get Spring Security to work by this technique. I believe that my plugin (which depends on Spring Security) was loaded after the security was initialized. I decided to add an extra file to the grails-app/conf directory.

HTH.

Big Ed
  • 1,056
  • 9
  • 20
1

For modifying configuration files, you should use ConfigSlurper:

def configParser = new ConfigSlurper(grailsSettings.grailsEnv)
configParser.binding = [userHome: userHome]
def config = configParser.parse(new URL("file:./grails-app/conf/Config.groovy"))

If you need to get application name from script, try:

metadata.'app.name'
Andriy Budzinskyy
  • 1,971
  • 22
  • 28
  • problem with the slurper is that if I wannt to add a configuration property at install-time, I would have to slurp the config, modify it and serialize it to disk again. But the serialisation will remove all comments :-( – rdmueller Mar 16 '12 at 18:35