I'm trying to run stages from 2 class instances with parallel but i'm getting this error: "roovy.lang.MissingFieldException: No such field" from one of them, but if i'm running one of them it ok.
the groovy classes are in src folder and i'm using them with library and creating an instance for each of them.
this is my parallel code from the jenkins file:
def parallelStagesMap = pipelineDailyStages.collectEntries {
def name = it.getSetupname()
echo "name: " + name
["${name}" : it.generateStage(name)]
}
these are the classes:
package stages
class DSmall extends DStages implements Serializable{
def local_mx
def local_g
def local_agent
DamSmall(environment, local_setupname, local_rp_launch_id, local_ssbuild, local_catagry, local_runners, local_artifactstodownload, local_resourcepool, local_mngnetwork, local_datastore, local_vmfolder, local_dcap_deploy, local_remotedebugport, local_m, local_g, local_agentoracle){
super(environment, local_setupname, local_rp_launch_id, local_ssbuild, local_catagry, local_runners, local_artifactstodownload, local_resourcepool, local_mngnetwork, local_datastore, local_vmfolder, local_deploy, local_remotedebugport)
this.local_m = local_m
this.local_g = local_g
this.local_agent = local_agent
}
def generateStage(a){
return {
this.environment.stage("stage: ${a}") {
this.environment.echo "This is da."
}
}
}
}
class DaSmall extends DStages implements Serializable{
def local_m
def local_agent
def local_oracletemplate
def local_oracle_start_db
DasSmall(environment, local_setupname, local_rp_launch_id, local_ssbuild, local_catagry, local_runners, local_artifactstodownload, local_resourcepool, local_mngnetwork, local_datastore, local_vmfolder, local_dcap_deploy, local_remotedebugport, local_mxs, local_agent, local_oracletemplate, local_oracle_start_db){
super(environment, local_setupname, local_rp_launch_id, local_ssbuild, local_catagry, local_runners, local_artifactstodownload, local_resourcepool, local_mngnetwork, local_datastore, local_vmfolder, local_deploy, local_remotedebugport)
this.local_mxs = local_mxs
this.local_agentoracle = local_agentoracle
this.local_oracletemplate = local_oracletemplate
this.local_oracle_start_db = local_oracle_start_db
}
def generateStage(a){
return {
this.environment.stage("stage: ${a}") {
this.environment.echo "This is da."
}
}
}
}
Finally I found a solution, I created the class instances from another groovy file that sits in vars folder(not from the jenkins file)
Related
I don't understand why we don't need to add quotes to the name of gradle task when we declare it
like:
task hello (type : DefaultTask) {
}
I've tried in a groovy project and found that it's illegal, how gradle makes it works.
And I don't understand the expression above neither, why we can add (type : DefaultTask), how can we analyze it with groovy grammar?
As an example in a GroovyConsole runnable form, you can define a bit of code thusly:
// Set the base class for our DSL
#BaseScript(MyDSL)
import groovy.transform.BaseScript
// Something to deal with people
class Person {
String name
Closure method
String toString() { "$name" }
Person(String name, Closure cl) {
this.name = name
this.method = cl
this.method.delegate = this
}
def greet(String greeting) {
println "$greeting $name"
}
}
// and our base DSL class
abstract class MyDSL extends Script {
def methodMissing(String name, args) {
return new Person(name, args[0])
}
def person(Person p) {
p.method(p)
}
}
// Then our actual script
person tim {
greet 'Hello'
}
So when the script at the bottom is executed, it prints Hello tim to stdout
But David's answer is the correct one, this is just for example
See also here in the documentation for Groovy
A Gradle build script is a Groovy DSL application. By careful use of "methodMissing" and "propertyMissing" methods, all magic is possible.
I don't remember the exact mechanism around "task ". I think this was asked in the Gradle forum (probably more than once).
Here is the code that make the magic possible and legal.
// DSL class - Gradle Task
class Task {
def name;
}
// DSL class - Gradle Project
class Project {
List<Task> tasks = [];
def methodMissing(String name, def args) {
if(name == "task"){
Task t = new Task(name:args[0])
tasks << t
}
}
def propertyMissing(String name) {
name
}
}
// gradle build script
def buildScript = {
task myTask
println tasks[0].name
}
buildScript.delegate = new Project()
// calling the script will print out "myTask"
buildScript()
I have the simple Greeting example in xtext. So the DSL is defined like this:
grammar org.xtext.example.mydsl.Tests with org.eclipse.xtext.common.Terminals
generate tests "http://www.xtext.org/example/mydsl/Tests"
Model:
greetings+= Greeting*;
Greeting:
'Hello' name=ID '!';
Moreover, I have the following validator:
#Check
def checkGreetingStartsWithCapital(Greeting greeting) {
if (!Character.isUpperCase(greeting.name.charAt(0))) {
warning('Name should start with a capital',
TestsPackage.Literals.GREETING__NAME,
-1,
INVALID_NAME)
}
}
If I write the validator like this and have an expression like
"Hello world!"
in my model, the "world" is marked, i.e. there is this yellow line under it. What do I have to do if I want to mark only the keyword so in this case only the "Hello"?
I tried quite a few things and I can only manage to either mark the whole line "Hello world!" or just the "world".
Thank you!
have a look at the other methods for reporting a warning/error. there is one that takes an offset and length. you can use the node model to get them for the keyword
class MyDslValidator extends AbstractMyDslValidator {
public static val INVALID_NAME = 'invalidName'
#Inject extension MyDslGrammarAccess
#Check
def checkGreetingStartsWithCapital(Greeting greeting) {
if (!Character.isUpperCase(greeting.name.charAt(0))) {
val node = NodeModelUtils.findActualNodeFor(greeting)
for (n : node.asTreeIterable) {
val ge = n.grammarElement
if (ge instanceof Keyword && ge == greetingAccess.helloKeyword_0) {
messageAcceptor.acceptWarning(
'Name should start with a capital',
greeting,
n.offset,
n.length,
INVALID_NAME
)
}
}
}
}
}
I found another very simple solution I haven't thought of that includes changing the DSL a bit, i.e. add the keyword as a attribute.
Greeting:
keyword='Hello' name=ID '!';
Then the validator works as in the question:
#Check
def checkGreetingStartsWithCapital(Greeting greeting) {
if (!Character.isUpperCase(greeting.name.charAt(0))) {
warning('Name should start with a capital',
TestsPackage.Literals.GREETING__KEYWORD,
-1,
INVALID_NAME)
}
}
I want to define a singleton method, but it needs to be private. The best I can come up with is below:
def initialize
define_singleton_method(name) { ... }
self.singleton_class.send(:private, name)
end
Is there a way without having to use send to do this?
I overlooked class_eval:
define_singleton_method(name) { ... }
self.singleton_class.class_eval { private name }
I'm working on an XML export for a Ruby project and I'm looking for an elegant way to implement it. The goal of this XML file is to export all data inside a project container and there is several models (about 20) sharing some common properties (for example a name and a description).
Currently, the XML export looks like an awful thing like that:
def export_project(p)
#xml project {
#xml.name p.name
#xml.description p.description
#xml.itemAs {
p.item_as.each {|item_a|export_itemA(item_a)
}
#xml.itemBs {
p.item_Bs.each {|item_B|export_itemB(item_b)
}
#xml.itemCs {
p.item_cs.each {|item_c|export_itemC(item_c)
}
}
end
def export_itemA(a)
#xml.itemA {
#xml.name a.name
}
end
def export_itemB(b)
#xml.itemB {
#xml.description b.description
}
end
def export_itemC(c)
#xml.itemC {
#xml.name c.name
#xml.description c.description
}
end
Which is pretty ugly (well, it's bearrable with 4 types, but the reality is 480 lines of mess ...)
What I'd like would be something like that (considered there is a magic mapping between a model and an exporter):
module Named
def export
#xml.name #context.name
end
end
module Described
def export
#xml.description #context.description
end
end
class ProjectExporter < ModelExporter
include Named
include Described
def export
#xml.project {
super
#xml.itemAs {
export_items(p.item_as)
}
#xml.itemBs {
export_items(p.item_Bs)
}
#xml.itemCs {
export_items(p.item_cs)
}
}
end
class ItemAExporter < ModelExporter
include Named
def export
#xml.itemA {
super
}
end
end
class ItemBExporter < ModelExporter
include Described
def export
#xml.itemB {
super
}
end
end
class ItemCExporter < ModelExporter
include Named
include Described
def export
#xml.itemC {
super
}
end
end
The problem with this method is that "super" will only call the export method of one of the module, not all of them.
I'm pretty suer the module and super approach is not the correct one, but I'm unable to find something more suitable. Any idea ?
Cheers and thanks,
Vincent
We have a class like this in a Grails 2.4.3 application (migrated from 2.3.8):
#Validateable
class Foo {
Integer noDefault;
Integer withDefault = 1;
static constraints = {
noDefault(nullable:false)
withDefault(nullable:false)
}
}
This class is being instantiated in a complex configuration mechanism using a Map like this:
[
noDefault: 0,
withDefault: 2
]
(In fact the Map is part of a huge one, but the class constructor sees this small one.) Formerly the class worked if we omitted the withDefault entry from the config map, using the default value which is not null. In Grails 2.4.3, however, it tells me that this field cannot be null. I can fix it by letting it be null in the constraint, but it lets setting the explicite value null (and overwrite the default value), which causes problem during operation.
Do you know some workaround, which preserves the semantics and correct operation?
Thanx in advance, best regards: Balázs
What you are describing is not consistent with what I would expect and not consistent with the behavior I am seeing. The project at https://github.com/jeffbrown/validatedefaults contains the following code.
At https://github.com/jeffbrown/validatedefaults/blob/master/src/groovy/demo/Foo.groovy
// src/groovy/demo/Foo.groovy
package demo
import grails.validation.Validateable
#Validateable
class Foo {
Integer noDefault;
Integer withDefault = 1;
static constraints = {
noDefault(nullable:false)
withDefault(nullable:false)
}
}
The test at https://github.com/jeffbrown/validatedefaults/blob/master/test/unit/demo/FooSpec.groovy passes:
// test/unit/demo/FooSpec.groovy
package demo
import spock.lang.Specification
import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin
#TestMixin(GrailsUnitTestMixin)
class FooSpec extends Specification {
void 'test validating default values'() {
given:
def map = [noDefault: 0]
def foo = new Foo(map)
expect:
foo.validate()
}
}
When I run the app I get the same behavior.
// grails-app/conf/BootStrap.groovy
import demo.Foo
class BootStrap {
def init = { servletContext ->
def map = [noDefault: 0]
def foo = new Foo(map)
// this prints true...
println "Foo is valid? : ${foo.validate()}"
}
def destroy = {
}
}
I hope that helps.