I have a job dsl script in which i am locating a directory. However it is trying to find that directory from / and not looking inside workspace.
Also i tried to print the current working directory, its displaying / only
String workingDir = System.getProperty("user.dir");
println "current directory is "
println workingDir;
Output :
current directory is
/
Just fixed it.
I was using "user.dir" which is by default "/" directory(manage jenkins -> system information -> system properties)
I added this and it worked
workingDir = "${WORKSPACE}" + "/some_directory"
I am using Grail 2.2.4,
in conf/spring/resources.xml, I try to import a file as ${realm}-config.properties, where realm is a vm arguement, I tried to set vm arguements in BuildConfig.groovy as below
grails.tomcat.jvmArgs = ["-Dstage=dev","-Drealm=app"]
But it doesn't seem to pick up. I get below error,
class path resource [${realm}-config.properties] cannot be opened because it does not exist
What is the right way to set vm arguements in grails 2.2.4 ?
Maybe try to load your config via environment variable handled in conf/Config.groovy
def ENV_NAME = "MY_CONFIG"
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)
}
I have read the documentation here, which gives the structure, but does not offer any help on how to create the actual logic.
I want to build a very simple script which does a clean, creates the war, creates a zip of the sources (without the target directory, and without any svn dirs), and creates a tar (idealy gzipped) of the migrations dir so this can be used with liquibase. Each of these 3 artifacts should have the app version in their name (like the existing "grails war" does.
The project structure looks like this:
svn
main-app
grails-app
migrations
target
:
exploded-plugin-1
grails-app
:
exploded-plugin-2
grails-app
:
This is how far I have got:
includeTargets << grailsScript("_GrailsInit")
target(packageUs: "Creates war, zips source, tars liquibase scripts") {
depends(clean, war-us, zip-source, tar-liquibase)
}
setDefaultTarget(packageUs)
target ("war-us" : "creates war") {
ant.war() // this was a guess at calling the existing war - it doesnt work
}
target ("zip-source" : "zips sources") {
// cd to top dir of project, i.e. above the app.
}
target ("tar-liquibase":"produces tar of migrations dir") {
// tar up the migrations dir
// name it with the app-version
// put it in the target dir along side the war etc.
}
target ("clean") {
// call the default clean some how, or cd to target dir, and delete everything
}
The above script was originally created with "grails create-script package-us"
Sadly, not even this works, it produces the following error:
| Error Error executing script PackageUs: No signature of method: org.codehaus.gant.GantBinding$_initializeGantBinding_closure5.doCall() is applicable
for argument types: (java.lang.String, PackageUs$_run_closure5) values: [clean, PackageUs$_run_closure5#5ed0b4e3]
I could not find any example scripts nor documentation beyond the very basic overview in the link.
I cant even get ant.echo() to work - intellij says there is only one ant.echo function which takes a LinkedHashmap, a String and a Closure, but the ant documentation says echo only takes a "message" string. What should the linkedhashmap, string and closure be? I have tried minimum 30 different variations, none work.
Update 1: What I have got working so far
includeTargets << grailsScript("_GrailsInit")
target(packageUs: "Creates war, zips source, tars liquibase scripts") {
depends(clean, "war-us", "zip-source")
}
setDefaultTarget(packageUs)
target ("war-us" : "creates war") {
ant.echo(message:"hello") // this compiles and runs, but does nothing.
println "hello there" // this does work.
// ant.war(?)
}
// puts in it wrong dir, and doen't have app version in name, but at least it zips the right content!
target ("zip-source" : "zips sources") {
ant.delete(file: 'sources.zip') // dont know how to add this to the clean cycle
ant.zip(destfile: 'sources.zip', basedir: '..', excludes: "**/*.zip **/target/** **.idea **/.classpath **/.iml")
}
What I havent figured out:
How to get hold of app.version so it can put put in file names. e.g this: println "creating war for $app.version" does not work
how to build the war. It is not possible to put it in the depdends list, and ant.war("myfile.war") does not work unfortunately. Other strategies might be running this script on the war building event, which is not ideal, as wars are built frequiently without needing this, or perhaps to call "grails war" by calling a shell command.
Update 2 - Can't produce a "prod" war
With help from Ashraf Purno, we have a script (below) which creates a war, zips the sources and tar.gz the liquibase files and produces our package of them. However, it has one major flaw, the war that is created is always the "dev" version, in that when you deploy it to a tomcat, it tires to use the dev datasource, and dev environment. There seems to be no way to change this in the build scirpt, and setting the environment to be prod on the command line which calls the script (e.g. "grails prod myscript") also has no influence - it also produces a dev version of the war (which is of no use)
includeTargets << grailsScript("_GrailsInit")
includeTargets << grailsScript("_GrailsClean")
includeTargets << grailsScript("War")
target(warpack: "Creates war, zips source, tars liquibase scripts") {
depends(cleanAll, cleanRealyAll, war, "zip-source", "tar-liquibase", "package-all")
}
setDefaultTarget(warpack)
target ("cleanRealyAll" : "Cleans stuff that clean-all wont touch") {
println "wiping the target dir"
ant.delete(dir: "target")
ant.mkdir(dir: "target")
}
target ("zip-source" : "zips sources") {
println "zipping sources for ${metadata.'app.version'}"
String zipFile = "target/sources-${metadata.'app.version'}.zip"
ant.delete(file: zipFile)
ant.zip(destfile: zipFile, basedir: '..', excludes: "**/*.zip **/target/** **.idea **/.classpath **/.iml")
}
target ("tar-liquibase":"produces tar of migrations dir") {
println "tarring liquibase for ${metadata.'app.version'}"
String tarFile = "target/migrations-${metadata.'app.version'}.tar"
String gzipfile = "target/migrations-${metadata.'app.version'}.tar.gz"
ant.tar(destfile:tarFile, basedir: "grails-app/migrations")
ant.gzip(src: tarFile, destfile : gzipfile )
ant.delete(file: tarFile)
}
target ("package-all":"puts it all together in one file, relies on externally running 'grails war' first") {
println "creating package for ${metadata.'app.version'}"
String packageFile = "target/ourpackage-${metadata.'app.version'}.tar"
ant.delete(file: packageFile)
ant.tar (destfile: packageFile, basedir:"target", includes: "*.war *.zip *.gz" )
}
After a bit googling and peeking through grails core scripts I managed to create a script which does the things you mentioned in your question. Here it is
import grails.util.Metadata
includeTargets << grailsScript("_GrailsInit")
includeTargets << grailsScript("_GrailsClean")
includeTargets << grailsScript("_GrailsWar")
target(pack: "Creates war, zips source, tars liquibase scripts") {
depends(cleanAll, war)
String appVersion = Metadata.current[Metadata.APPLICATION_VERSION],
zipFileName = "${basedir}/target/sources-${appVersion}.zip",
tarFileName = "${basedir}/target/migrations-${appVersion}.tar.gz"
println "Creating Sources Zip"
ant.delete(file: zipFileName)
ant.zip(destfile: zipFileName, basedir: basedir, excludes: "**/target/** **/.idea/** **/.classpath/** **/.iml/**")
println "Creating Migrations Tar Ball"
ant.delete(file: tarFileName)
ant.tar(destfile: tarFileName, basedir: "${basedir}/grails-app/migrations")
}
setDefaultTarget(pack)
I have put all the tasks in a single target just for simplicity. You can divide them in several targets and add them to depends if you want. I have used Grails 2.5.1 for testing this script.
You can take a look here http://mrhaki.blogspot.com/2014/05/grails-goodness-run-groovy-scripts-in.html for some available props/configs in scripts.
i have code in config.groovy
def ENV_NAME = "/home/myFolder"
if(System.getenv("ENV_NAME")) {
println( "Including configuration file: " + System.getenv("ENV_NAME"));
grails.config.locations << "file:" + System.getenv("ENV_NAME")
} else {
println "No external configuration file defined."
}
When I run, the result is "No external configuration file defined."
What do I miss?
Presumably that there isn't an environment variable named ENV_NAME defined at the point when you ran the app.
This seems pretty strange, but when grails builds a war file it doesn't generate a log4j.properties or log4j.xml file.
Instead it has the following in WEB-INF/web.xml
web.xml:
<listener>
<listener-class>org.codehaus.groovy.grails.web.util.Log4jConfigListener</listener-class>
</listener>
and apparently "grails Log4j DSL configures logging in-memory". The problem here is - log4j isn't automatically exposed to JMX for us to dynamically change and there's no log4j file generated by grails. But Config.groovy is a compiled file.
There's got to be an easy way to manage this without rebuilding the war?
One option suggested is go through to spring and configure logging there:
resources.groovy:
beans = {
log4jConfigurer(org.springframework.beans.factory.config.MethodInvokingFactoryBean)
{
targetClass = "org.springframework.util.Log4jConfigurer"
targetMethod = "initLogging"
arguments = ["classpath:myapp/log4j.properties"]
}
}
then shift the configuration in the DSL to the configured file.
Can anyone advise the 'groovy' way to dynamically change logging configuration without rebuilding the WAR file each time. Using grails-1.3.7. Cutting the DSL out doesn't seem the right way.
Thanks
You may have an external config file that is searched for by your application at startup time.
You would have a MyExternalConfig.groovy file somewhere in your production environment. For example:
log4j = {
def catalinaBase = System.properties.getProperty('catalina.base')
if (!catalinaBase) catalinaBase = '.'
def logDirectory = "${catalinaBase}/logs"
appenders {
rollingFile name:"infoLog", maxFileSize:'900KB', file:"${logDirectory}/${appName}Info.log", maxBackupIndex:10, layout:pattern(conversionPattern: '%d{DATE} %p %c - %m%n'), threshold: org.apache.log4j.Level.INFO
rollingFile name:"erroLog", maxFileSize:'900KB', file:"${logDirectory}/${appName}Erro.log", maxBackupIndex:10, layout:pattern(conversionPattern: '%d{DATE} %p %c - %m%n'), threshold: org.apache.log4j.Level.ERROR
}
root {
info 'infoLog', 'erroLog'
additivity = false
}
error erroLog:"StackTrace"
error erroLog: 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'net.sf.ehcache.hibernate'
warn infoLog: 'org.mortbay.log'
info infoLog: "grails.app"
}
Then in your Config.groovy file, that belongs to your grails project in conf folder, you put this as the last thing of the file:
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 configuration file defined."
}
This will look for external configurations files to add to your grails.config.locations attribute of your Config.groovy. First it looks for it as a System Environment variable (I use it this way), if it does not find, then it looks for a command line parameter (so you could add it when you start your tomcat app, as a parameter to startup.sh).
To configure your system environment variabble, just do this before starting tomcat:
MY_EXTERNAL_CONFIG="/home/tomcat/configs/MyExternalConfig.groovy"
export MY_EXTERNAL_CONFIG
--- start tomcat here ---
That's it.