I would like to run different versions of my Grails (2.3.5) app at the same time in the same tomcat using different DBs.
At the moment I am having an external configuration file where I specify my DB configurations.
The filename is hardcoded:
<tomcat-home>/conf/sc.conf
"sc.war" is the name of my war-file. As I now want/need to run multiple versions I would like to make the name of the conf file variable.
<tomcat-home>/conf/<warfilename>.conf
Is there a way to get the war-file-name at runtime?
I am open for other ways to solve my problem. Thanks for your help.
You just need to give applicationBaseDir path into external config file
applicationBaseDir = ""
println "Bootstrapping application"
println ">>>>>>>>Environment >>>>>"+GrailsUtil.environment
Environment.executeForCurrentEnvironment {
development {
println "Keeping applicationBaseDir "+grailsApplication.config.applicationBaseDir+" as is."
}
production {
//Following code finds your project path and set applicationBaseDir
Process findPresentWorkingDirectory = "pwd".execute()
def pwd = findPresentWorkingDirectory.text
def pwdTokens = pwd.tokenize("/")
pwdTokens.pop()
applicationBaseDir = pwdTokens.join("/")
println ">>>> applicationBaseDir "+applicationBaseDir
applicationBaseDir = "/"+applicationBaseDir+"/webapps/applicationDir/"
println 'grailsApplication.config.applicationBaseDir '+applicationBaseDir
}
}
Or you directly set applicationBaseDir in external config file
applicationBaseDir = "/home/tomcat/webapps/applicationDir/"
Now, to refer specific external config file add into your project file Config.groovy file following code
environments {
development {
String codeSystemClassFilePath = AnyDomainClassNameFromYourApplication.class.getProtectionDomain().getCodeSource().getLocation().getPath()
// Here AnyDomainClassNameFromYourApplication change to your application domain class name e.g.I have domain class Student then I replace it with Student
def arrayWithLastValueAsProjectName = codeSystemClassFilePath.split('/target/classes/')[0].split('/')
String projectName = arrayWithLastValueAsProjectName[arrayWithLastValueAsProjectName.size()-1]
println "App name in dev==>"+projectName
grails.logging.jul.usebridge = true
grails.config.locations = [
"file:${userHome}/grails/${projectName}.groovy"
]
grails.assets.storagePath = ""
}
production {
String codeSystemClassFilePath = AnyDomainClassNameFromYourApplication.class.getProtectionDomain().getCodeSource().getLocation().getPath()
def arrayWithLastValueAsProjectName = codeSystemClassFilePath.split('/WEB-INF/classes/')[0].split('/')
String projectName = arrayWithLastValueAsProjectName[arrayWithLastValueAsProjectName.size()-1]
println "App name in production==>"+projectName
grails.logging.jul.usebridge = false
grails.config.locations = [
"file:${userHome}/grails/${projectName}.groovy"
]
}
}
//here grails/ is my default folder use to store exernal-config-files
I hope this helps you!
Related
I have some keys that i want to keep in the config file. I have two different keys, one for use in development setting and another for use when the environment is set to production. Now, in grails we extract these property values from config file using
grailsApplication.config.[name of the property in config file]
is it possible to have conditional setting on config file that will return the right key depending on whether the environment is set to production or development? I appreciate any help! Thanks!
We use the approach of separate external config files for different environments and then include them in "config.groovy" depending on the environments like below
environments {
test {
grails.logging.jul.usebridge = true
grails.config.locations = ["file:${userHome}/.grails/${appName}-config-TEST.groovy"]
}
development {
grails.logging.jul.usebridge = true
grails.config.locations = ["file:${userHome}/.grails/${appName}-config-DEV.groovy"]
}
production {
grails.logging.jul.usebridge = false
grails.config.locations = ["file:${userHome}/.grails/${appName}-config-PROD.groovy"]
}
}
But if you want common file for all the environments then you can use the "Environment" available in "grails.util" package like below
package asia.grails.myexample
import grails.util.Environment
class SomeController {
def someAction() {
if (Environment.current == Environment.DEVELOPMENT) {
// insert Development environment specific key here
} else
if (Environment.current == Environment.TEST) {
// insert Test environment specific key here
} else
if (Environment.current == Environment.PRODUCTION) {
// insert Production environment specific key here
}
render "Environment is ${Environment.current}"
}
}
I am trying to read a string in from an external config file, but am for some reason only getting an empty object. Here is the config file (DirectoryConfig.groovy)
directory {
logDirectory = "c:\\opt\\tomcat\\logs\\"
}
And the code that retrieves the directory (from a controller):
String dirName = grailsApplication.config.directory.logDirectory
File directory = new File(dirName)
For some reason, dirName always ends up being "{}", and as a result the file cannot be read. What am I doing wrong here?
Creating DirectoryConfig.groovy in your grails-app/conf/ directory will not work by convention.
You should consider implementing solution that is recommended for externalizing Grails configuration - delivering .groovy or .properties files from classpath or filesystem. Take a look at commented code in Config.groovy:
// grails.config.locations = [ "classpath:${appName}-config.properties",
// "classpath:${appName}-config.groovy",
// "file:${userHome}/.grails/${appName}-config.properties",
// "file:${userHome}/.grails/${appName}-config.groovy"]
It's very common way to provide configuration files that depend on runtime property:
// if (System.properties["${appName}.config.location"]) {
// grails.config.locations << "file:" + System.properties["${appName}.config.location"]
// }
I often use something like this (it's part of the Config.groovy file):
grails.config.locations = []
grails.project.config.type = "classpath"
grails.project.config.extension = "groovy"
environments {
development {
grails.project.config.file = "development-config.${grails.project.config.extension}"
}
test {
grails.project.config.file = "test-config.${grails.project.config.extension}"
}
}
if (System.properties["grails.config.type"]) {
grails.project.config.type = System.properties["grails.config.type"]
}
if (System.properties["grails.config.file"]) {
grails.project.config.file = System.properties["grails.config.file"]
}
grails.config.locations << "${grails.project.config.type}:${grails.project.config.file}"
By default it assumes that there is e.g. development-config.groovy file in the classpath, but I can simply change it by setting -Dgrails.config.file=/etc/development.properties -Dgrails.config.type=file in Java runtime so it uses /etc/development.properties file instead of the default one.
If you would like to run your example in the simplest way, you will have to do:
1) put your DirectoryConfig.groovy in the classpath source e.g. src/java (attention: it wont work if you put your file in src/groovy)
2) define in your Config.groovy:
grails.config.locations = [
"classpath:DirectoryConfig.groovy"
]
3) re-run your application. grailsApplication.config.directory.logDirectory should now return the value you expect.
For more information about externalizing configuration go to http://grails.org/doc/latest/guide/conf.html#configExternalized
I started working with an existing Grails project and this is the part of the config file (Config.groovy) that deals with external configuration files:
grails.config.locations = [];
def defaultConfigFile = "${basedir}/configs/BombayConfig.groovy"
def defaultDatasourceFile = "${basedir}/configs/BombayDataSource.groovy"
if(File.separator == "\\") {
defaultConfigFile = defaultConfigFile.replace('/', '\\')
defaultDatasourceFile = defaultDatasourceFile.replace('/', '\\')
}
String PROJECT_NAME = "BOMBAY"
String CONFIG_ENV = "${PROJECT_NAME}_CONFIG_LOCATION"
String DATASOURCE_ENV = "${PROJECT_NAME}_DATASOURCE_LOCATION"
def externalConfig = System.getenv(CONFIG_ENV)
def externalDataSource = System.getenv(DATASOURCE_ENV)
if (externalConfig && new File(externalConfig).isFile()) {
grails.config.locations << "file:" + externalConfig
}
else {
grails.config.locations << "file:" + defaultConfigFile
}
if (externalDataSource && new File(externalDataSource).isFile()) {
grails.config.locations << "file:" + externalDataSource
}
else {
grails.config.locations << "file:" + defaultDatasourceFile
}
I have some default files in configs folder, but in the server the files that are being used reside in:
/home/someusername/configuration/
which doesn't look like the default path, and there are no environment variables pointing to that path as the configuration suggests.
I also tried to look for a configs folder linked to the other configuration folder, but didn't find anything.
I'm lost here; how else can configuration files be specified to Grails?
Edit:
To clarify on things, the server is running and works, I just want to figure out how it's picking up the configuration files from the above specified path.
I think the intention is that you use the grails.config.locations[] entry. The following is commented out in my Config.groovy
// grails.config.locations = [ "classpath:${appName}-config.properties",
// "classpath:${appName}-config.groovy",
// "file:${userHome}/.grails/${appName}-config.properties",
// "file:${userHome}/.grails/${appName}-config.groovy"]
So can't you specify something like this:
grails.config.locations = [ "file:${userHome}/configuration" ]
to pickup the files in that folder?
if(File.separator == "\\") {
defaultConfigFile = defaultConfigFile.replace('/', '\\')
defaultDatasourceFile = defaultDatasourceFile.replace('/', '\\')
}
This will probably cause problems - grails.config.locations is a list of URLs, not native file paths, so you definitely do want forward, not backward slashes. Instead try something like
File defaultConfigFile = new File(basedir, "configs/BombayConfig.groovy")
// and the same for datasource
// ...
File externalConfig = System.getenv(CONFIG_ENV) ? new File(System.getenv(CONFIG_ENV)) : null
if (externalConfig?.isFile()) {
grails.config.locations << externalConfig.toURI().toString()
}
else {
grails.config.locations << defaultConfigFile.toURI().toString()
}
In case you are struggling with external configs and you
have specifies external configs like so in Config.groovy
grails.config.locations = []
if(System.properties["${appName}.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.config.location"]
}
if(System.properties["${appName}.datasource.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.datasource.config.location"]
}
and your set environment is something like this
export GRAILS_OPTS="$GRAILS_OPTS -DAppName.config.location=dev-config/Config.groovy"
export GRAILS_OPTS="$GRAILS_OPTS -DAppName.datasource.config.location=dev-config/DataSource.groovy"
and dev configs are not being picked up, then you need to look into your fork settings in BuildConfig.groovy and turn them off like so
grails.project.fork = [
test: false,
run: false,
]
This way, when application is forked, your system properties will not be lost.
I created the following resource mapper using the instructions from the resources plugin:
import org.grails.plugin.resource.mapper.MapperPhase
import org.apache.commons.logging.LogFactory
class VersionResourceMapper {
def phase = MapperPhase.MUTATION
def log = LogFactory.getLog(this.class)
static defaultIncludes = [ '/js/**' ]
def map(resource, config) {
def query = [v:'1.01']
resource.actualUrl = resource.actualUrl + '?' + query.collect { it }.join('&')
//resource.updateActualUrlFromProcessedFile()
if (log.debugEnabled) log.debug "Modified URL: ${resource.actualUrl}"
log.info "Modified URL: ${resource.actualUrl}"
}
}
The file is located in grails-app/resourceMappers
My class never even gets called. I have a debug breakpoint set which is never hit. Is there some other configuration that has to be set?
remove this line
static defaultIncludes = [ '/js/**' ]
and check if your breakpoint is hit. It looks like it is just not finding the js directory.
If that works change the above line to
static defaultIncludes = [ 'js/**' ]
I'm pretty sure that you need to change
def phase = MapperPhase.MUTATION
to
static phase = MapperPhase.MUTATION
I can't have my 'folder' external variable working. Always I'm getting [:].
I'm developing on Grails under Windows (this is why the external configuration file looks like file:C:\path\to/file).
I'm using external configuration in another project without problems, in the same way that I'm showing below.
I have this:
Config.groovy:
environments {
development {
grails.config.locations = [ "file:${userHome}/.grails/${appName}-config.groovy" ]
}
}
myApp-config.groovy:
stats.feed.wsdl.folder = '/static'
Controller and Service:
class WsdlController {
def wsdlService
def index = {
wsdlService.getEventsSchedule()
}
}
class WsdlService {
def grailsApplication
def getEventsSchedule = {
println "Locations: ${grailsApplication.config.grails.config.locations}"
println "Folder: ${grailsApplication.config.stats.feed.wsdl.folder}"
}
}
Console:
Locations: [file:C:\Users\myUser/.grails/myApp-config.groovy]
Folder: [:]
Any clue?
Thanks!
Updated!
This is the whole myApp-config.groovy:
println 'Start'
stats.feed.wsdl.folder = "/stats"
println 1
stats.feed.wsdl.folder.events = "${stats.feed.wsdl.folder}/events"
println 2
stats.feed.wsdl.folder.teams = "${stats.feed.wsdl.folder}/teams"
println 'End'
This is not working, the console shows:
Start
1
But if I change the variable names, it works.
println 'Start'
stats.feed.wsdl.folder = "${playcall.static.resources.folder}/stats"
println 1
stats.feed.wsdl.events.folder = "${stats.feed.wsdl.folder}/events"
println 2
stats.feed.wsdl.teams.folder = "${stats.feed.wsdl.folder}/teams"
println 'End'
Console:
Start
1
2
End
You create a property and declared this as a string:
stats.feed.wsdl.folder = "/stats"
In that way you isnt't able to add subproperties. So, to keep something close to what you want, you can do this:
stats.feed.wsdl.folder.base = "/stats"
stats.feed.wsdl.folder.events = "${stats.feed.wsdl.folder.base}/events"
stats.feed.wsdl.folder.teams = "${stats.feed.wsdl.folder.base}/teams"