在grails脚本中创建域类的实例 [英] Creating an instance of a domain class inside a grails script
问题描述
我正在尝试在grails 2.3.6脚本中创建一个域类的实例:
def player = new玩家(名称:Bob)
player.save()
但是我不断得到一个例外
java.lang.NoClassDefFoundError:games / player
我已经尝试了我在互联网上找到的所有不同的引导技巧,但并没有真正改变结果:
我尝试导入:
import gaming.Player
我尝试加载引导脚本:
includeTargets<<< grailsScript(_ GrailsBootstrap)
我已经尝试依赖于我设法找到的每个任务: p>
depend(configureProxy,packageApp,classpath,loadApp,configureApp,compile,bootstrap)
/ pre>
我甚至在运行时加载了类:
ApplicationHolder.application.getClassForName(gaming.Player)
有趣的是,最后一行不'bar bar这表明grails可以找到我的课程,但是当我真的去使用它时,选择忽略它。
编辑。根据要求,这里是脚本的当前版本
import gaming.Player
import org。 codehaus.groovy.grails.commons.ApplicationHolder
includeTargets<<< grailsScript(_ GrailsInit)
includeTargets<<< grailsScript(_ GrailsBootstrap)
includeTargets<<< grailsScript(_ GrailsClasspath)
def handleHeaderLine(line){
def retval = []
line.each {
if(!it.equals(Game名称)&!it.equals(总共份数)){
println(创建播放器)+ b $ b def player = new Player(name:it)
player.save
retval<<< it
} else {
retval<<< null
}
}
return retval;
}
def handleGameLine(header,line){
println(Creating Game:+ line [0])
for(int i = 1; i < line.length - 1; i ++){
if(!header [i] .equals(Total of of Copies)){
def count = line [i] ==? 0:Integer.parseInt(line [i]);
(int j = 0; j< count; j ++){
println创建+头[0] +由+头[i]
} b $ b}
}
}
target(loadAssets:脚本的描述在这里!){
depends(configureProxy,packageApp,classpath, loadApp,configureApp,compile,bootstrap)
ApplicationHolder.application.getClassForName(gaming.Player)
def tsv = new File(...)
def header = null;
tsv.eachLine {
def line = it.split(\t)
if(header == null){
header = handleHeaderLine(line)
println标题
} else {
handleGameLine(标题,行)
}
}
}
setDefaultTarget(loadAssets)
解决方案你不必做所有的锅炉板运行脚本时的环境。
运行脚本
为你做的。当grails run-script
用于默认运行的目标:checkVersion,configureProxy,bootstrap
。最后运行脚本运行脚本
。
运行脚本运行您的自定义脚本
GroovyShell
通过提供ApplicationContext
和grailsApplication
作为绑定到shell。所以你最终会得到你的脚本,如下所示,就好像它是用Groovy控制台/ shell编写的://脚本/player/PlayerScript.groovy
def handleHeaderLine(line){
def retval = []
line.each {
if(!it.equals(Game Name)& ;&!it.equals(Total of of Copies)){
println(Creating Player:+ it)
def player = new Player(name:it)
player .save(flush:true)
retval<< it
} else {
retval<<< null
}
}
return retval
}
def handleGameLine(header,line){
println(Creating Game:+行[0])
for(int i = 1; iif(!header [i] .equals(Total of of Copies)) {
def count = line [i] ==? 0:Integer.parseInt(line [i]);
(int j = 0; j< count; j ++){
println创建+头[0] +由+头[i]
} b $ b}
}
}
def tsv = new File(...)
def header = null
tsv.eachLine {
def line = it.split(\t)
if(header == null){
header = handleHeaderLine(line)
println header
} else {
handleGameLine(header,line)
}
}
然后使用
运行脚本
如下:grails run-脚本脚本/播放器/ PlayerScript.groovy
这将默认在dev环境中运行脚本。如果你想要其他环境,然后用作
grails测试运行脚本脚本/播放器/ PlayerScript.groovy
但是
由于主要错误在最新版本的grails中,您将无法以上述方式运行脚本,因为运行脚本
始终取决于bootstrap
目标,并将始终尝试将tomcat
up同时在build
中运行脚本作为插件范围,这将导致加载插件管理器:TomcatGrailsPlugin 时出错。解决方法也在缺陷中提及,但这里是一个groovier实现。更改BuildConfig.groovy
as:plugins {
if(!System.getProperty(noTomcat)){
build:tomcat:7.0.52.1
}
....
}
然后发出运行脚本命令:
grails -DnoTomcat = true run-script scripts / player / PlayerScript.groovy
在旁注中,您的脚本未运行的原因是在运行脚本时不会加载类
Player
,以供使用。必须使用classLoader
手动加载,然后从中创建一个实例。例如:includeTargets<<< grailsScript(_ GrailsInit)
includeTargets<<< grailsScript(_ GrailsBootstrap)
target(playerScript:脚本的描述在这里!){
依赖于configureProxy,packageApp,classpath,loadApp,configureApp
def playerClass = classLoader.loadClass(gaming.Player)
//怀疑域类如何行为
//但是普通的POGO应该很好地被使用
def player = playerClass.newInstance([[name:Bob]] as Object [])
player.save(flush:true)
println player
}
setDefaultTarget(playerScript)
I am trying to create an instance of a domain class inside a grails 2.3.6 script:
def player = new Player(name:"Bob") player.save()
But I keep getting an exception
java.lang.NoClassDefFoundError: gaming/Player
I've tried all the different bootstrapping tricks I've managed to find on the internet but they don't really change the result:
I've tried importing:
import gaming.Player
I've tried loading the bootstrap script:
includeTargets << grailsScript("_GrailsBootstrap")
I've tried depending on every task I managed to find:
depends(configureProxy, packageApp, classpath, loadApp, configureApp, compile, bootstrap)
I've even tried loading the class at runtime:
ApplicationHolder.application.getClassForName("gaming.Player")
Interestingly enough, this last line doesn't barf which suggests that grails can find my class, but chooses to ignore the find when I actually go to use it.
Edit. As requested, here is the current version of the script
import gaming.Player import org.codehaus.groovy.grails.commons.ApplicationHolder includeTargets << grailsScript("_GrailsInit") includeTargets << grailsScript("_GrailsBootstrap") includeTargets << grailsScript("_GrailsClasspath") def handleHeaderLine(line) { def retval = [] line.each { if(!it.equals("Game Name") && !it.equals("Total # of Copies")) { println("Creating Player: " + it) def player = new Player(name:it) player.save retval << it } else { retval << null } } return retval; } def handleGameLine(header, line) { println("Creating Game: " + line[0]) for(int i = 1; i < line.length - 1; i++) { if(!header[i].equals("Total # of Copies")) { def count = line[i] == "" ? 0 : Integer.parseInt(line[i]); for(int j = 0; j < count; j++) { println "Creating copy of " + line[0] + " owned by " + header[i] } } } } target(loadAssets: "The description of the script goes here!") { depends(configureProxy, packageApp, classpath, loadApp, configureApp, compile, bootstrap) ApplicationHolder.application.getClassForName("gaming.Player") def tsv = new File("...") def header = null; tsv.eachLine { def line = it.split("\t") if(header == null) { header = handleHeaderLine(line) println header } else { handleGameLine(header, line) } } } setDefaultTarget(loadAssets)
解决方案You do not have to do all the boiler plate effort to bring up the environment while running your script.
run-script
does that for you. Whengrails run-script
is used following targets are run by default:checkVersion, configureProxy, bootstrap
. And finally the scriptrun-script
is run.run-script runs your custom script in
GroovyShell
by providingApplicationContext
andgrailsApplication
as bindings to shell. So what you would end up with your script is shown below as if it is written in Groovy console/shell://scripts/player/PlayerScript.groovy def handleHeaderLine(line) { def retval = [] line.each { if(!it.equals("Game Name") && !it.equals("Total # of Copies")) { println("Creating Player: " + it) def player = new Player(name: it) player.save(flush: true) retval << it } else { retval << null } } return retval } def handleGameLine(header, line) { println("Creating Game: " + line[0]) for(int i = 1; i < line.length - 1; i++) { if(!header[i].equals("Total # of Copies")) { def count = line[i] == "" ? 0 : Integer.parseInt(line[i]); for(int j = 0; j < count; j++) { println "Creating copy of " + line[0] + " owned by " + header[i] } } } } def tsv = new File("...") def header = null tsv.eachLine { def line = it.split("\t") if(header == null) { header = handleHeaderLine(line) println header } else { handleGameLine(header, line) } }
And then use
run-script
as below:grails run-script scripts/player/PlayerScript.groovy
which would by default run the script in dev environment. If you want for other envirnments then use as
grails test run-script scripts/player/PlayerScript.groovy
BUT
Due to a major bug in latest version of grails, you won't be able to run script the above mentioned way becauserun-script
always depends onbootstrap
target and would always try to bringtomcat
up while running script as the plugin scope inbuild
which would result in Error loading plugin manager: TomcatGrailsPlugin. The workaround is also mentioned in the defect but here is a groovier implementation. Change inBuildConfig.groovy
as:plugins { if ( !System.getProperty("noTomcat") ) { build ":tomcat:7.0.52.1" } .... }
and then issue run-script command as:
grails -DnoTomcat=true run-script scripts/player/PlayerScript.groovy
On a side note, the reason your script was not running is that the class
Player
will not be loaded at this time while running script, for use. It has to be loaded manually usingclassLoader
and then create an instance off of it. Something like:includeTargets << grailsScript("_GrailsInit") includeTargets << grailsScript("_GrailsBootstrap") target(playerScript: "The description of the script goes here!") { depends configureProxy, packageApp, classpath, loadApp, configureApp def playerClass = classLoader.loadClass("gaming.Player") //Skeptical about how a domain class would behave //But a normal POGO should be good being used this way def player = playerClass.newInstance([[name: "Bob"]] as Object[]) player.save(flush: true) println player } setDefaultTarget(playerScript)
这篇关于在grails脚本中创建域类的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!