Grails External Configuration. Can't access to external variable. Getting always [:] - grails

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"

Related

Jenkinsfile syntax error: No such property

I'm trying to test a binary with latest commit id in Jenkins. Error happens at send slack message stage:
def kResPath = "/tmp/res.json" // global variable, where json file is dumped to; declared at the very beginning of Jenkinsfile
def check_result_and_notify(tier, result) {
def kExpected = 3
def kSuccessSlackColor = "#00CC00"
message = "Test ${tier} result: ${result}\n"
def test_result = readJSON file: kResPath
// 0 means index, "benchmarks", "real-time" is the key
real_time = test_result["benchmarks"][0]["real_time"]
if (real_time > kExpected) {
message += String.format("real time = %f, expected time = %f", real_time, kExpected)
}
slackSend(color: ${kSuccessSlackColor}, message: message.trim(), channel: "test-result")
}
The json file looks like:
{
"benchmarks": [
{
"real_time": 4,
},
{
"real_time": 5,
}
],
}
The error message I've received is hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: kResPath for class: WorkflowScript
Can someone tell me what's wrong with my code?
Is there any way I could test it locally so that I don't need to commit it every single time? I googled and find it needs server id and password, which I don't think accessible to me :(
Your kResPath variable is undefined in the scope of that function or method (unsure which based on context). You can pass it as an argument:
def check_result_and_notify(tier, result, kResPath) {
...
}
check_result_and_notify(myTier, myResult, kResPath)
and even specify a default if you want:
def check_result_and_notify(tier, result, kResPath = '/tmp/res.json')

war specific configuration file

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!

Jenkins Pipeline Execute Multiple FreeStyleProjects in Parallel [duplicate]

The script is not iterating through all the values of the 'modules' array.
class Module {
public String name = '';
public Boolean isCustom = false;
public Module(String name, Boolean custom){
this.name = name;
this.isCustom = custom;
}
}
//creates array from the ext_module env var
modules = [];
EXT_MODULE.split(',').each {
modules.add(new Module(it, false));
}
println modules;
modules.each {
println "MODULE NAME ::::: ${it.name}"
if(it.isCustom)
{
println "install custom";
} else {
println "install non custom";
}
};
This is the result of the run. The array shows 4 elements, but the code inside the .each black only executes once.
Running: Print Message
[Module#71f09325, Module#e1ddb41, Module#7069a674, Module#1f68f952]
Running: Print Message
MODULE NAME ::::: puppetlabs-ntp
Running: Print Message
install non custom
Running: End of Workflow
Finished: SUCCESS
The messages "Running: Print Message" and "Running: End of Workflow" indicate that you are using the new workflow plugin: https://wiki.jenkins-ci.org/display/JENKINS/Workflow+Plugin. This plugin currently has a bug causing at least some Groovy iterations involving a closure to be aborted after one iteration: https://issues.jenkins-ci.org/browse/JENKINS-26481
The workaround is to simply use an old school for loop (code below).
Also, NonCPS is another workaround.
There is an open issue for this matter. See here: https://issues.jenkins-ci.org/browse/JENKINS-26481
Update, Oct 24th, 2016
/**
* Dumps environment varibles to the log, using an old school for loop.
*/
import com.cloudbees.groovy.cps.NonCPS
def version = '1.0'
#NonCPS
def dumpEnvVars() {
def str = "Dumping build environment variables...\n"
for (Map.Entry<String, String> entry : currentBuild.build().environment) {
str += " ${entry.key} = ${entry.value}\n"
}
echo str
}
return this;
As of yesterday, the new Pipeline plugin was delivered in version 2.0 and correct this problem.
.each closures now work, but .collect still only iterate once.

create grails custom ResourceMapper

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

Groovy Script - Logback configuration unawaited behaviour

I want to use Logback as my logging framework within Grails. therefore I set up everything in place to work but my implementation fails on the configuration file itself. the reason is, as I guess, somewhere whithin the scoping of Groovy Script but I'm not able to figure it out...
if I define my String properties without any identifier which I want to use later I get a warning that it may not be accessed. For example:
LOG_DIR = 'c:/temp/myproject/logs/'
BACKUP_DIR = LOG_DIR + 'backup/'
appender('F_MAIN', RollingFileAppender) {
file = LOG_DIR + 'test.log'
rollingPolicy(FixedWindowRollingPolicy) {
fileNamePattern = BACKUP_DIR + 'test.%d{yyyy-MM-dd}.%i.log.zip'
// .... and so on
}
}
I get the following error message from Logback, which I'm pretty sure is indicating that both LOG_DIR and BACKUP_DIR can not be reached:
13:33:32,036 |-ERROR in ch.qos.logback.classic.gaffer.AppenderDelegate#6fd00b - Appender [F_MAIN] of type [ch.qos.logback.core.rolling.RollingFileAppender] has no appplicable [LOG_DIR] property
13:33:32,068 |-ERROR in ch.qos.logback.classic.gaffer.ComponentDelegate#788ac3 - Component of type [ch.qos.logback.core.rolling.FixedWindowRollingPolicy] has no appplicable [BACKUP_DIR] property
I also tried the following approach by declaring both variables with the #Field tag, but it still does not work:
#Field String LOG_DIR = 'c:/temp/myproject/logs/'
#Field String BACKUP_DIR = LOG_DIR + 'backup/'
appender('F_MAIN', RollingFileAppender) {
file = LOG_DIR + 'test.log'
rollingPolicy(FixedWindowRollingPolicy) {
fileNamePattern = BACKUP_DIR + 'test.%d{yyyy-MM-dd}.%i.log.zip'
// .... and so on
}
}
what am I doing wrong here?
oh my!
after searching and a lot of trial/error I found the solution and it was so close and definitely seems obvious now: I had to declare both variables with def, so now they are visible throughout the whole script ;)
For example, this is working code:
def LOG_DIR = 'c:/temp/myproject/logs/'
def BACKUP_DIR = LOG_DIR + 'backup/'
appender('F_MAIN', RollingFileAppender) {
file = LOG_DIR + 'test.log'
rollingPolicy(FixedWindowRollingPolicy) {
fileNamePattern = BACKUP_DIR + 'test.%d{yyyy-MM-dd}.%i.log.zip'
// .... and so on
}
}
now, I'm also able to use a function like this within my script:
def createFilename(String directory, String name, boolean isBackupFile) {
String filename = ''
if(isBackupFile) {
filename = "${directory}backup/MyProject-${name}.%d{yyyy-MM-dd}.%i.log.zip"
} else {
filename = "${directory}MyProject-${name}.log"
}
return filename
}
def fileAppenderLog = createFilename(LOG_DIR, 'output', false)
def fileAppenderLogBackup = createFilename(LOG_DIR, 'output', true)
appender('F_MAIN', RollingFileAppender) {
file = fileAppenderLog
rollingPoliciy(FixedWindowRollingPolicy) {
fileNamePattern = fileAppenderLogBackup
// .... and so on
}
}
which is pretty useful, I think :), especially if you want to declare a bunch of different logfiles and even if you want to declare temporary logfiles which are created when Logback is rescanning this file ...

Resources