Execute Groovy script within Grails context, updated for Grails 1.3.1
Quite often it is needed to execute Groovy script within a Grails application context (including access to domain objects, controllers, services, etc). Unfortunately there is no such built-in functionality in Grails.
However Ted Naleid has written run-script
Gant script to do this and published on his blog.
We used it in our project and it worked flawlessly. However it stopped working with upgrade to Grails 1.3.1 and even grabbing the latest version from bitbucket haven’t helped.
So I looked into the sources of built-in Grails scripts, including run-test
and hacked run-script
a little bit to make it run fine.
You can grab/fork the resulting script on github.
Also, please vote for inclusion of run-script
functionality into main Grails distribution in JIRA
Using the script is easy. Just store it in src/scripts/
folder of your Grails app with RunScript.groovy
filename.
Then you’ll be able to run your scripts as following:
grails run-script path/to/script1/Script1.groovy path/to/script2/Script2.groovy ...
The script itself is:
import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU
import org.springframework.orm.hibernate3.SessionFactoryUtils
import org.springframework.orm.hibernate3.SessionHolder
import org.springframework.transaction.support.TransactionSynchronizationManager
includeTargets << grailsScript("_GrailsBootstrap")
includeTargets << grailsScript("_GrailsRun")
includeTargets << grailsScript("_GrailsSettings")
includeTargets << grailsScript("_GrailsClean")
target('default': "Execute the specified script after starting up the application environment") {
depends(checkVersion, configureProxy, packageApp, classpath)
runScript()
}
target(runScript: "Main implementation that executes the specified script after starting up the application environment") {
parseArguments()
if (argsMap["params"].size() == 0) {
event("StatusError", ["Required script name parameter is missing"])
System.exit 1
}
compile()
loadApp()
configureApp()
configureHibernateSession()
argsMap["params"].each { scriptFile ->
executeScript(scriptFile, classLoader)
}
}
def configureHibernateSession() {
// without this you'll get a lazy initialization exception when using a many-to-many relationship
def sessionFactory = appCtx.getBean("sessionFactory")
def session = SessionFactoryUtils.getSession(sessionFactory, true)
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session))
}
def executeScript(scriptFile, classLoader) {
File script = new File(scriptFile)
if (script.exists()) {
def shell = new GroovyShell(classLoader, new Binding(ctx: appCtx, grailsApplication: grailsApp))
shell.evaluate(script.text)
} else {
event("StatusError", ["Designated script doesn't exist: $scriptFile"])
}
}