在grails脚本中创建域类的实例 [英] Creating an instance of a domain class inside a grails script

查看:449
本文介绍了在grails脚本中创建域类的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在grails 2.3.6脚本中创建一个域类的实例:

  def player = new玩家(名称:Bob)
player.save()

但是我不断得到一个例外

  java.lang.NoClassDefFoundError:games / player 

我已经尝试了我在互联网上找到的所有不同的引导技巧,但并没有真正改变结果:



我尝试导入:

  import gaming.Player 

我尝试加载引导脚本:

  includeTargets<<< grailsS​​cript(_ 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<<< grailsS​​cript(_ GrailsInit)
includeTargets<<< grailsS​​cript(_ GrailsBootstrap)
includeTargets<<< grailsS​​cript(_ 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; 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}
}
}

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<<< grailsS​​cript(_ GrailsInit)
includeTargets<<< grailsS​​cript(_ 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. When grails run-script is used following targets are run by default: checkVersion, configureProxy, bootstrap. And finally the script run-script is run.

run-script runs your custom script in GroovyShell by providing ApplicationContext and grailsApplication 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 because run-script always depends on bootstrap target and would always try to bring tomcat up while running script as the plugin scope in build which would result in Error loading plugin manager: TomcatGrailsPlugin. The workaround is also mentioned in the defect but here is a groovier implementation. Change in BuildConfig.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 using classLoader 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆