grails 2.5 does not read properties from home dir when added to grails.config.locations - grails

At the top of config.groovy is this line (now uncommented):
grails.config.locations = [ "file:${userHome}/.grails/${appName}-config.properties"]
So we created a properties file on windows in our home dir /.grails, which contains these lines for the database migration plugin:
contents of c:\Users\me\.grails\myapp-config.properties:
grails.plugin.databasemigration.updateOnStartContexts=XXX
grails.plugin.databasemigration.updateOnStart=true
we restart the app, it completely ignores these values.
If however, we change to a groovy file thusly:
grails.config.locations = [ "file:${userHome}/.grails/${appName}-config.groovy"]
And create the following file: c:\Users\me.grails\myapp-config.groovy
grails.plugin.databasemigration.updateOnStartContexts = 'XXX'
grails.plugin.databasemigration.updateOnStart = true
It works perfectly. It seems it is not possible to use property files with the database migration plugin at least.
However, we need to be able to change these values on production (tomcat + war), which we assume cannot compile groovy files, so wont work.
Luckily, the below part does actually work:
if (System.properties["${appName}.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.config.location"]
}
But we would really like to get the home dir version working, so we dont have to worry about system properties and command line arguments in our dev environments.
Any ideas?

change the path separator for windows from / to \
try to put the complete path in locations to check the file can be read

Related

Grails external config file path

I'am about to set up a external config file. So I'm using the grails plugin
compile "org.grails.plugins:external-config:1.1.1"
I create the application.groovy that looks like this
grails.config.locations = [
"/Users/username/application.properties"
]
And my application.config file is exactly in this place. By creating a normal file i have access to it and can read out of it.
In my file i have three key value pairs like
firstkey=first
secondkey=second
thirdkey=third
Still this keys does not get added to my config file.
In the class which is placed in the src directory i am able to call the config like this
Holders.config
//No result on calling one of the keys
Holders.config.thirdkey
Has anyone an idea what I have to do additional
grails.config.locations takes spring resource patterns
Try
grails.config.locations = [
"file:///Users/username/application.properties"
]
If the file is in the home directory of the user under which the app is running. You can even use
grails.config.locations = [
"~/application.properties"
]
The examples are already there in docs here
You can enable debug log level for logger grails.plugin.externalconfig. And it will log messages if any of your configured external config file is not found.
logger("grails.plugin.externalconfig", DEBUG, ["STDOUT"])

Grails - Images located in a different path when running from a war

I've been developing an Grails application that uses some FileResources located in this directory:
MyGrailsApplication\web-app\images
I'm able to get this directory through grails naturally through GrailsResourceUtils.WEB_APP_DIR. However, when I convert my Grails project into a .war file and deploy it to a tomcat server, that code does not work - the path gets messed up.
Through some debug statements, I was able to find a hacky work-around to this (essentially, do a code modification right before I make the war):
// BELOW 2 LINES WORK IN THE WAR FILE, BUT NOT WITH THE RUN-APP CMD
new FileResource(new File("../webapps/InstanceChecker-0.1/images/ok.png"))
new FileResource(new File("../webapps/InstanceChecker-0.1/images/http404.png"))
// BELOW 2 LINES WORK WITH RUN-APP, BUT NOT IN THE WAR
new FileResource(new File(GrailsResourceUtils.WEB_APP_DIR + "/images/ok.png"))
new FileResource(new File(GrailsResourceUtils.WEB_APP_DIR + "/images/http404.png"))
Is there a way to cleanly get the image path both in run-app and also when its deployed as a .war? Are there some best practices that I'm missing out on here?
Edit: Perhaps I'm not putting the images in an ideal directory? I'm open to advice on that as well.
For get a resource file you can use this:
def basePath = grailsApplication.mainContext.servletContext.getRealPath('images')
Check if end with "/":
basePath = basePath.endsWith("/") ? basePath : basePath + "/"
And then:
new FileResource(new File(basePath+"fileName"))
Remember to inject grailsApplication in your controller/service
you can (also) utilize grail's linkGenerator like
final headerImage = new Image(null, new ExternalResource(Grails.get(LinkGenerator).resource(dir: "images", file: "logo.png")))

How do I derive physical path of a relative directory inside Config.groovy?

I am trying to set up Weceem using the source from GitHub. It requires a physical path definition for the uploads directory, and for a directory for appears to be used for writing searchable indexes. The default setting for uploads is:
weceem.upload.dir = 'file:/var/www/weceem.org/uploads/'
I would like to define those using relative paths like WEB-INF/resources/uploads. I tried a methodology I have used previously for accessing directories with relative path like this:
File uploadDirectory = ApplicationHolder.application.parentContext.getResource("WEB-INF/resources/uploads").file
def absoluteUploadDirectory = uploadDirectory.absolutePath
weceem.upload.dir = 'file:'+absoluteUploadDirectory
However, 'parentContext' under ApplicationHolder.application is NULL. Can anyone offer a solution to this that would allow me to use relative paths?
look at your Config.groovy you should have (maybe it is commented)
// locations to search for config files that get merged into the main config
// config files can either be Java properties files or ConfigSlurper scripts
// "classpath:${appName}-config.properties", "classpath:${appName}-config.groovy",
grails.config.locations = [
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy"
]
Create Conig file in deployment server
"${userHome}/.grails/${appName}-config.properties"
And define your prop (even not relative path) in that config file.
To add to Aram Arabyan's response, which is correct, but lacks an explanation:
Grails apps don't have a "local" directory, like a PHP app would have. They should be (for production) deployed in a servlet container. The location of that content is should not be considered writable, as it can get wiped out on the next deployment.
In short: think of your deployed application as a compiled binary.
Instead, choose a specific location somewhere on your server for the uploads to live, preferably outside the web server's path, so they can't be accessed directly. That's why Weceem defaults to a custom folder under /var/www/weceem.org/.
If you configure a path using the externalized configuration technique, you can then have a path specific to the server, and include a different path on your development machine.
In both cases, however, you should use absolute paths, or at least paths relative to known directories.
i.e.
String base = System.properties['base.dir']
println "config: ${base}/web-app/config/HookConfig.grooy"
String str = new File("${base}/web-app/config/HookConfig.groovy").text
return new ConfigSlurper().parse(str)
or
def grailsApplication
private getConfig() {
String str = grailsApplication.parentContext.getResource("config/HookConfig.groovy").file.text
return new ConfigSlurper().parse(str)
}

Grails External Config Read Incorrectly on First Load

Grails 1.3.7
I have some configuration located in an external config file. One of the entires looks like this:
site.maintenance.mode = false
I have a filter which checks for certain config settings for specific URLs. When I do a run-app or deploy a WAR into Tomcat and do:
boolean maintenanceMode = grailsApplication.config.site.maintenance.mode
maintenanceMode is coming back true. If I look at the config object in debug mode, this is what I get:
site={maintenance={mode=false, message="<p>Our trail guides are working hard to get the system back on track.</p><p>We're sorry, the account system is down for maintenance at the moment. We'll get it back online as quickly as we can. Thanks for your patience.</p>"}}
I have a controller that I use to reload this config file dynamically and hitting this controller will fix the issue. But I'm curious as to why it is incorrect on first runs and why the discrepency in what is getting put in the maintenanceMode variable vs what is actually in the config object.
Are you using a Java properties file or a Groovy file? If you're using a properties file then I believe Grails will interpret site.maintenance.mode=false the same way as site.maintenance.mode='false' and since Groovy will interpret:
"false".asBoolean() == true
then that would explain why you would see that initial true value.
I just ran a simple test locally to verify this behavior. When I externalize my properties in a file called test.properties then site.maintenance.mode=false initially gets a boolean value of true, when I use a file called test.groovy then it interprets the boolean value of site.maintenance.mode=false as false. I believe this is because when you use a Groovy file Grails uses ConfigurationSlurper to process it but when you use a properties file Grails interprets everything as String name/value pairs.
What I do is to have an external Config.groovy file, for instance: MyConfig.groovy
At the end of the standard grails Config.groovy file, I have the following:
def ENV_NAME = "MY_EXTERNAL_CONFIG"
if(!grails.config.locations || !(grails.config.locations instanceof List)) {
grails.config.locations = []
}
if(System.getenv(ENV_NAME)) {
grails.config.locations << "file:" + System.getenv(ENV_NAME)
} else if(System.getProperty(ENV_NAME)) {
grails.config.locations << "file:" + System.getProperty(ENV_NAME)
} else {
println "No external Configs found."
}
So now you can have a MyConfig.groovy file anywhere in production environment (for example) and then set an Environment system variable to point to this file (or pass it as parameter to startup.sh), before you start tomcat:
MY_EXTERNAL_CONFIG="/home/tomcat/configs/MyConfig.groovy"
export MY_EXTERNAL_CONFIG
That's it. Now you have an external MyConfig.groovy file. The properties in it are accessible from your grails app as they were part of the standard Config.groovy
import org.codehaus.groovy.grails.commons.*
//...
ConfigurationHolder.config.foo.bar.hello

Using External Configuration File

I've added the code below to my Config.groovy file, however, in spite of having it I'm not able to access the external configuration properties in the Config.groovy file.
Does anyone how I can access the properties of the external configuration file within the Config.groovy file?
if (System.getProperty("CONFIG")) {
grails.config.locations << "file:" + System.getProperty("CONFIG")
} else {
grails.config.locations << "file:./${appName}-config.properties"
}
Note: I've tried using ${...} like I would in Spring configuration files, ConfigurationHolder.config, and grailsApplication to access the properties but none of these approaches work.
Thanks.
I think this would cause confusion due to the order the config files are loaded. I'm pretty sure at the time the Config.groovy is loaded, the external one hasn't been loaded yet.
So your "CONFIG" property is set in the external file, which is the name of the file that you want to load?
How I usually do this is just list all the files that I could use.
grails.config.locations = [
"file:../app-config/myapp-dataSource.groovy",
"file:../app-config/myapp-config.groovy"
]
environments {
development {
grails.config.locations = [
"file:../myapp-config/myapp-dataSource.groovy",
"file:../myapp-config/myapp-config.groovy",
"file:${userHome}/myapp-config/myapp-dataSource.groovy",
"file:${userHome}/myapp-config/myapp-config.groovy"
]
}
...
}
If the files do not exist they are just skipped. Files I believe are loaded in order, so anything in the ${userHome} dir, will override the previously set values. This is nice for development, as you can have machine local ways of changing settings, and not have to worry about these config changes being checked in.
#Nick Larson,
What you mentioned about CONFIG not loaded is not true. If CONFIG is a JVM parameter, set with -DCONFIG=xxxx, then it is set before config.groovy kicks in.
#Kin1,
You are using file: protocol for accessing the property file. Are you trying to access this in a WAR or EAR file or is it a file based system.
In a WAR or EAR file you need to use classpath: for the file, file: does not work. Also, you have to make sure to actually copy the Groovy file(not compiled class file) in the classpath. We do it on WAR create event and the build process copy the config file into one of the classpath location.
Hope this helps.
Add the below line in config.groovy
grails.config.locations = [ "classpath:grails-app-config.properties"]
environments {
development {
grails.logging.jul.usebridge = true
grails.config.locations = ["file:C:\\conf\\externalfile.groovy"]
}
production {
grails.logging.jul.usebridge = false
grails.config.locations = ["file:/opt/config/externalfile.groovy"]
// TODO: grails.serverURL = "http://www.changeme.com"
}
}
If you want to access any property from external configuration(config.groovy) then just declare the property like
property = property value eg:(ImagePath = "C:\\Users\\Saved Pictures")
access it like grailsApplication.config."property"
eg:(grailsApplication.config.ImagePath)
NOTE: dont use def just a property and its value.

Resources