我正在尝试在grails 2.3.6脚本中创建一个域类的实例:
def player = new Player(name:"Bob")
player.save()
但我一直有异常
java.lang.NoClassDefFoundError: gaming/Player
我已经尝试过我在互联网上设法找到的所有不同的引导技巧,但它们并没有真正改变结果:
我尝试过导入:
import gaming.Player
我已尝试加载引导程序脚本:
includeTargets << grailsScript("_GrailsBootstrap")
我根据我设法找到的每项任务尝试过:
depends(configureProxy, packageApp, classpath, loadApp, configureApp, compile, bootstrap)
我甚至尝试在运行时加载该类:
ApplicationHolder.application.getClassForName("gaming.Player")
有趣的是,这最后一行并不是barf,这表明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 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)
答案 0 :(得分:3)
在运行脚本时,您无需执行所有锅炉板工作来调出环境。 run-script
为你做到了。使用grails run-script
后,默认情况下会运行目标:checkVersion, configureProxy, bootstrap
。最后运行脚本run-script
。
run-script通过提供GroovyShell
和ApplicationContext
绑定到shell来在grailsApplication
中运行自定义脚本。所以你最终会得到你的脚本如下所示,好像它是用Groovy控制台/ 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)
}
}
然后使用run-script
,如下所示:
grails run-script scripts/player/PlayerScript.groovy
默认情况下会在dev环境中运行脚本。如果您想要其他环境,请使用
grails test run-script scripts/player/PlayerScript.groovy
<强> BUT 强>
由于最新版本的grails中有major bug,您将无法以上述方式运行脚本,因为run-script
始终依赖于bootstrap
目标,并且始终会尝试tomcat
1}}运行脚本作为build
中的插件范围,这将导致错误加载插件管理器:TomcatGrailsPlugin 。缺陷中也提到了解决方法,但这里有一个更加实用的实现。将BuildConfig.groovy
更改为:
plugins {
if ( !System.getProperty("noTomcat") ) {
build ":tomcat:7.0.52.1"
}
....
}
然后发出run-script命令:
grails -DnoTomcat=true run-script scripts/player/PlayerScript.groovy
另一方面,您的脚本未运行的原因是,在运行脚本时,此时将不会加载类Player
以供使用。必须使用classLoader
手动加载它,然后创建一个实例。类似的东西:
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)