4

I am doing an application with Grails 2.5.3 version. I want to outsource the database code and the section of Log4j.

The code of Log4j is in a external .groovy file. This file won't be modified by user so it is not necessary to be a properties file in /classes dir. The best in the case of database code is to have several features in a external properties file because will continue being a properties file in /classes dir. Also, DataSource.groovy exists with the rest of the configuration.

Then, I have only achieved to work Log4j conf with:

grails.config.locations = ["file:./grails-app/conf/LogConfig.groovy"]

With classpath doesn't work though I put the file in /grails-app/conf dir. This doesn't work:

grails.config.locations = ["classpath:LogConfig.groovy"]

Also, I have added both cases (run-app and war mode). However, when I run grails prod war and deploy Tomcat, Logconfig.groovy is not recognize.

grails.config.locations = ["file:./grails-app/conf/LogConfig.groovy",
"classpath:LogConfig.groovy"]

And in the case of database code, I didn't achieve to work the .properties file. This file I put in grails-app/conf and its contain is:

# DB properties
dataSource.username = xxx
dataSource.password = xxx
dataSouce.driverClassName = xxx
environments.development.dataSource.url = jdbc:mysql://localhost/xxx
environments.test.dataSource.url = jdbc:mysql://localhost/xxx
environments.production.dataSource.url = jdbc:mysql://localhost/xxx

I have read many tutorial and blogs and I don't know how I can do it to work.

Thanks for the help.

Jesús Iglesias
  • 140
  • 2
  • 12

2 Answers2

5

How we do it in the development and production mode.

your-application/
    conf/
        dev/
        qa/
        prod/
    grails-app/
        conf/
          Config.groovy

Config.groovy in the grails-app directory:

environments {

    development {
        grails.logging.jul.usebridge = true

        grails.config.locations = [
          "file:conf/dev/XXXConfig.groovy",
          "file:conf/dev/XXXDataSource.groovy",
          "file:conf/dev/XXXLog4JConfig.groovy",
          "file:conf/dev/plugins/XXXSecurityConfig.groovy",
        ]        
    }
    production {
        grails.logging.jul.usebridge = false

        grails.config.locations = [
          "classpath:XXXConfig.groovy",
          "classpath:XXXDataSource.groovy",
          "classpath:XXXLog4JConfig.groovy",
          "classpath:plugins/XXXSecurityConfig.groovy",
        ]
    }
}

For deployments in the application server (Tomcat, Websphere etc) you have to just ADD THE DIRECTORY WHERE CONFIGURATION FILES ARE TO THE CLASSPATH. When you have your configuration file directory in the classpath everything works fine.

For example we run Tomcat and have startup scripts that do export configuration -directory to the classpath.

For Grails 3.x I wrote support for this grails.config.locations because they removed the feature and I don't want to change how we do the configs. So put your grails.config.locations -configurations to the application.groovy in the grails-app/conf -directory.

import org.grails.core.io.DefaultResourceLocator
import org.springframework.core.env.Environment
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.core.env.MapPropertySource

class ApplicationConfigurationLoader {

    private ApplicationConfigurationLoader() {}

    public static load(GrailsAutoConfiguration application, Environment environment) {
        if (application && environment) {
            DefaultResourceLocator resourceLocator = new DefaultResourceLocator()
            def applicationGroovy = application.getClass().classLoader.getResource('application.groovy')
            if (applicationGroovy) {
                def applicationConfiguration = new ConfigSlurper(grails.util.Environment.current.name).parse(applicationGroovy)
                for (String configLocation in applicationConfiguration.grails.config.locations) {
                    def configurationResource = resourceLocator.findResourceForURI(configLocation)
                    if (configurationResource) {
                        def config = new ConfigSlurper(grails.util.Environment.current.name).parse(configurationResource.getURL())
                        environment.propertySources.addFirst(new MapPropertySource(configLocation, config))
                    }
                }
            }
        }
    }
}

And in your grails-app/init -folder you have your Application.groovy

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration

import org.springframework.core.env.Environment
import org.springframework.context.EnvironmentAware

import com.bcbmedical.bfw.core.util.ApplicationConfigurationLoader

class Application extends GrailsAutoConfiguration implements EnvironmentAware {
    static void main(String[] args) {
        GrailsApp.run(Application, args)
    }

    @Override
    void setEnvironment(Environment environment) {
        ApplicationConfigurationLoader.load(this, environment)
    }

}
  • Thanks. I got to resolve it but forgot to comment the solution here. I didn't know the difference between file and classpath and for this reason I didn't understand the operation. However, the properties file does not work, it only works the groovy file. – Jesús Iglesias Feb 09 '16 at 16:59
  • Both `.properties` and `.groovy` files work for me. Thanks Sami for the wonderful workaround! – ilPittiz Mar 08 '16 at 12:02
  • @Sami http://stackoverflow.com/questions/42839975/classpath-property-file-in-grails-app-is-not-being-used I have the exact situation as the original poster, but your solution doesn't seem to work, possibly? Would appreciate it if you took a look. – jbu Mar 16 '17 at 17:25
0

In our team we usually put in conf/Config.groovy:

def ENV_NAME = "PROJECT_NAME_CONFIG"

grails.config.locations = [EventHandlers]

if (System.getenv(ENV_NAME)) {
    println "Loading configuration file founded in environment variable - " + System.getenv(ENV_NAME)
    grails.config.locations << "file:" + System.getenv(ENV_NAME)
}
else if (System.getProperty(ENV_NAME)) {
    println "Loading configuration from property: " + System.getProperty(ENV_NAME)
    grails.config.locations << "file:" + System.getProperty(ENV_NAME)
}

and specify environment variable with specific name PROJECT_NAME_CONFIG, with path to dev config f.e.:

export PROJECT_NAME_CONFIG=/home/user/Documents/work/my_project/My_Project_Config.groovy

export PATH="$PATH:$PROJECT_NAME_CONFIG"

example My_Project_Config.groovy:

environments {
    development {

        dataSource {
            username = "root"
            password = "password"
            
            logSql = true
            dbCreate = "update"
            url = "jdbc:mysql://localhost/my_project?useUnicode=yes&characterEncoding=UTF-8&autoReconnect=true"
        }
    }
}
Community
  • 1
  • 1
Michal_Szulc
  • 4,097
  • 6
  • 32
  • 59
  • Thanks for replying me. Yes, this is a possible solution. But I don't search to put the files in a external path of the project. I want to put inside of the project. And in this case: "classpath:" doesn't work in no case (.groovy and .properties) and with "file:" only works with .groovy files. – Jesús Iglesias Jan 21 '16 at 10:53
  • Ok, so why don't you put my example database configuration My_Project_Config.groovy in ./conf folder and add to Config.groovy: grails.config.locations = ["file:./grails-app/conf/My_Project_Config.groovy"]? – Michal_Szulc Jan 21 '16 at 11:04
  • I can't put a .groovy file into my project, because it always will be compiled as ".class" file. Then, in the case of Log4j is possible but in the case of DataBase code is not possible because the user couldn't modify the configuration easily. – Jesús Iglesias Jan 21 '16 at 12:04