Crear una instancia de una clase de dominio dentro de una secuencia de comandos de Grails
dns bootstrapping (1)
No tiene que hacer todo el esfuerzo de la placa de la caldera para mostrar el entorno mientras ejecuta su secuencia de comandos. run-script
hace por ti. Cuando se usa grails run-script
siguientes objetivos se ejecutan de manera predeterminada: checkVersion, configureProxy, bootstrap
. Y, finalmente, se run-script
el script run-script
.
run-script ejecuta su script personalizado en GroovyShell
al proporcionar ApplicationContext
y grailsApplication
como enlaces al shell. Entonces, lo que terminaría con su script se muestra a continuación como si estuviera escrito en 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)
}
}
Y luego use run-script
siguiente manera:
grails run-script scripts/player/PlayerScript.groovy
que por defecto ejecutaría la secuencia de comandos en el entorno de desarrollo. Si quieres para otros entornos, utiliza como
grails test run-script scripts/player/PlayerScript.groovy
PERO
Debido a un error importante en la última versión de Grails, no podrá ejecutar el script de la manera mencionada anteriormente porque run-script
siempre depende del destino de bootstrap
y siempre intentará llevar a tomcat
mientras ejecuta el script como el alcance del complemento en la build
lo que daría como resultado Error al cargar el administrador de complementos: TomcatGrailsPlugin . La solución alternativa también se menciona en el defecto, pero aquí hay una implementación más completa. Cambie en BuildConfig.groovy
como:
plugins {
if ( !System.getProperty("noTomcat") ) {
build ":tomcat:7.0.52.1"
}
....
}
y luego ejecute el comando run-script como:
grails -DnoTomcat=true run-script scripts/player/PlayerScript.groovy
En una nota lateral, la razón por la que su script no se estaba ejecutando es que la clase Player
no se cargará en este momento mientras se ejecuta el script, para su uso. Tiene que ser cargado manualmente usando classLoader
y luego crear una instancia fuera de él. Algo como:
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)
Intento crear una instancia de una clase de dominio dentro de un script de Grails 2.3.6:
def player = new Player(name:"Bob")
player.save()
Pero sigo recibiendo una excepción
java.lang.NoClassDefFoundError: gaming/Player
He intentado todos los trucos de arranque diferentes que he logrado encontrar en Internet, pero en realidad no cambian el resultado:
Intenté importar:
import gaming.Player
Intenté cargar el script de arranque:
includeTargets << grailsScript("_GrailsBootstrap")
Lo intenté dependiendo de cada tarea que logré encontrar:
depends(configureProxy, packageApp, classpath, loadApp, configureApp, compile, bootstrap)
Incluso he intentado cargar la clase en tiempo de ejecución:
ApplicationHolder.application.getClassForName("gaming.Player")
Curiosamente, esta última línea no descarta lo que sugiere que los griales pueden encontrar mi clase, pero elige ignorar el hallazgo cuando realmente voy a usarlo.
Editar. Según lo solicitado, aquí está la versión actual del 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)