grails shell and closures - grails

Trying to run the following command in grails console:
Family.where() {password =~ "%qw%"}
A very simple query on a stored object. I'm getting back:
ERROR groovy.lang.MissingMethodException:
No signature of method: com.babyboom.Family.where() is applicable for argument types: (groovysh_evaluate$_run_closure1) values: [groovysh_evaluate$_run_closure1#34356294]
Possible solutions: where(groovy.lang.Closure), merge(), every(), grep(), merge(com.babyboom.Family), merge(java.util.Map)
I understand that the closure I created is a different than the expected one.
Couple of questions:
Why there are 2 types of closures ?
Found Why am I getting a "No signature of method"" error when running the closure recursion example in the Groovy shell? tried it and it didn't help, still getting the same error
It works well when using grails console

This is likely a classloader bug with the grails shell. To reproduce, add dependency to BuildConfig.gradle:
runtime "org.grails:grails-datastore-simple:3.1.2.RELEASE"
then run
import org.grails.datastore.mapping.simple.SimpleMapDatastore
import org.grails.datastore.gorm.GormStaticApi
class Bar {}
class Foo extends GormStaticApi<Bar> {
Foo() {
super(Bar, new SimpleMapDatastore(), [], null)
}
}
def f = new Foo()
In grails console yields:
Result: Foo#699c0395
In grails shell yields:
groovy:000> def f = new Foo()
ERROR java.lang.LinkageError:
loader constraint violation: when resolving overridden method "Foo.$getStaticMetaClass()Lgroovy/lang/MetaClass;" the class loader (instance of groovy/lang/GroovyClassLoader$InnerLoader) of the current class, Foo, and its superclass loader (instance of org/codehaus/groovy/grails/cli/support/GrailsRootLoader), have different Class objects for the type ()Lgroovy/lang/MetaClass; used in the signature

Related

Closure as argument in Jenkins shared library function

let's say I have a Configuration class in a Jenkins shared library written like this
class Configuration {
String param1, param2
Closure closure1
}
There's also a helper class like this
class Helper {
String helperMethod(String arg1, Closure closure1) {
// some invocation to closure 1
}
}
Within the var folder there's a dynamic pipeline in a pipeline.groovy file like this:
def call(Configuration config) {
node {
stage {
def helper = new Helper()
helper.helperMethod('foo') { config.closure1 it }
}
}
}
Finally I'm trying to use the shared library in another repo like this,
#Library('my-library')
import com.mylibrary.configuration.Configuration
def baz = { it.toUpperCase() }
def config = new Configuration(
param1: 'foo',
param2: 'bar',
closure1: baz
)
pipeline(config)
The problem is that baz get transformed to org.jenkinsci.plugins.workflow.cps.CpsClosure2 and helperMethod throws a MissingMethodException because of the type mismatch between CpsClosure2 and the expected groovy.lang.Closure
I've tried:
Using the #NonCPS annotation in baz
Strong typing the closure through a functional interface and trying to pass it to the config like closure1: baz as MyStronglyTypedClosure
Removing the closure typing in the helperMethod definition
Using helper.helperMethod('foo', config.closure1) instead of helper.helperMethod('foo') { config.closure1 it }
to no avail :(
Is there any workaround to receive the closure in the configuration so it can be used correctly in the helper class? Thanks in advance
MissingMethodException is usually thrown when you are invoking functions incorrectly or inexistent function, it rarely has to do with CPS closures, which indeed as dagget mentioned, extends standard java closures. I strongly recommend you to use testing frameworks like Spock (with Jenkins extension) to be able to detect errors beforehand.

Jenkins | Use method from an imported java class in a groovy script

I want to be able to use a method from a Jenkins plugin via its java class
Just to point out I'm not a developer or a groovy/java expert - happy to learn!
The java class that my method is part of is com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator
From this I would like to use the method getRepoOwner()
What I've done is set my import and defined a new call to the class:
import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator
def bbSCMNav = new BitbucketSCMNavigator()
When I run this I get the error below:
org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method <init>() to invoke from this list:
public com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator#<init>(java.lang.String)
public com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator#<init>(java.lang.String, java.lang.String, java.lang.String)
I've searched for the error above Could not find which method <init>() to invoke from this list
And I came across this ticket Could not find which method <init>() to invoke from this list on newInstance in groovy closure
Can't say that I entirerly understand the reply if it's helpful to me or not as I say I'm not a developer and groovy and java are relatively new to me but happy to understand if anyone can point me in the right direction with this
The goal of this exercise is to use the method during the run-time of a build to get the output of getRepoOwner() and use that in a variable to construct a URI
This question also seems similar to mine - Calling internal methods of Jenkins plugin (thinBackup)
But I'm not using maven or a pom.xml here
Cheers
Quick Answer
This error Could not find which method < init >() is related to a missing constructor.
Almost all internal jenkins class are ready to use in groovy.
In your case, BitbucketSCMNavigator does not have a default constructor. It have a constructor with one String argument. Check this line
Explanation
I could replicate your error with another internal class org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory:
node {
stage('internal') {
org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory obj =
new org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory();
}
}
hudson.remoting.ProxyException: org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method <init>() to invoke from this list:
private org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory#<init>(org.jenkinsci.plugins.workflow.cps.CpsFlowExecution, boolean, java.lang.ClassLoader, java.util.List)
But, reviewing this class CpsFlowExecution I could see that CpsGroovyShellFactory does not have a default constructor. It have a constructor with one argument : CpsGroovyShellFactory(this)
So, If I instance the constructor with one argument, no errors appear.
node {
stage('internal') {
org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory obj =
new org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory(null);
}
}

Codeception injection fails using page object

I'm new to Codeception, but I'm running into an issue injecting Page Objects. The problem occurs when I add the following construct logic to my page object.
public function __construct(\AcceptanceTester $I) {
$this->tester = $I;
}
... I got this from Login Page object example here: http://codeception.com/docs/06-ReusingTestCode#PageObjects
The error I'm getting is:
[Codeception\Exception\InjectionException]
Failed to inject dependencies in instance of 'MyCest'. Failed to create instance of 'Page\Login'. Failed to create instance of 'AcceptanceTester'. Failed to create instance of 'Codeception\Scenario'. Failed to resolve dependency 'Codeception\TestCase'.
This is how I'm injecting the page in my Cest.
protected function _inject(\Page\Login $login) {
$this->login_page = $login;
}
If I remove the __construct code, the error goes away. Is this a bug in Codeception or am I doing something wrong?
This is the work-around I found...
use \AcceptanceTester;
use Page\Login as LoginPage;
class MyCest {
protected $login_page;
public function _before(AcceptanceTester $I) {
$this->login_page = new LoginPage($I);
}
}
It is expected behaviour.
Your LoginPage constructor should not have any arguments to be instantiated during DI, so your workaround is right way to initialize LoginPage instance with AcceptanceTester instance.
When you specify AcceptanceTester as LoginPage's ctor arg DI mechanism of Codeception tries resolve dependencies recursively in the following way:
LoginPage(AcceptanceTester) -> AcceptanceTester(Scenario) -> Scenario(TestCase) -> TestCase
but TestCase is abstract class so it can not be instantiated.

Grails Camel Routing Plugin Not recognising sendMessage

We have a project that we recently required the use of Camel in. This projects is a Groovy/Grails project and I have installed the Routing 1.4.1 plugin.
I then proceeded to create a new route as specified in the documentation which is shown below:
package some_package
import org.apache.camel.builder.RouteBuilder
class TestRoute extends RouteBuilder {
def grailsApplication
#Override
void configure() {
def config = grailsApplication?.config
// example:
from('seda:input.queue').to('stream:out')
}
}
Then I proceeded to setup a call to this Route in one of my Controllers using the following 'sendMessage' command:
//Camel Testing
def message = "This is some history"
sendMessage("seda:input.queue", message)
However when typing in the IDE the 'sendMessage' method it does say 'Type Not Found' which says to me maybe I am missing an import of something but according to the documentation this should be available to all Controllers and Services.
I added debug and the code hits the sendMessage line however does not get into the routing method.
Can someone please help with this?
Thanks
************UPDATE***********
So I installed everything again from scratch and used an older version of InteliJ and the simple example worked great.
Next I tried a more complex example of calling a service, however the app fails on startup, I have put the Service, Route and sendMessage data below:
Route
from("seda:input.queue").filter {
it.in.body.contains("test")
}.to("bean:TestService?method=printMsg")
Service
def printMsg(msg){
println(msg)
}
sendMessage
def myMessage = "this is a test message"
sendMessage("seda:input.queue", myMessage)
The error I get when running the app is below:
Error 2015-08-07 13:46:46,156 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener - Error initializing the application: groovy.lang.MissingMethodException: No signature of method: org.grails.plugins.routing.processor.PredicateProcessor.to() is applicable for argument types: (java.lang.String) values: [bean:TestService?method=printMsg]
Possible solutions: is(java.lang.Object), any(), use([Ljava.lang.Object;), getAt(java.lang.String), with(groovy.lang.Closure), any(groovy.lang.Closure)
Message: groovy.lang.MissingMethodException: No signature of method: org.grails.plugins.routing.processor.PredicateProcessor.to() is applicable for argument types: (java.lang.String) values: [bean:TestService?method=printMsg]
Possible solutions: is(java.lang.Object), any(), use([Ljava.lang.Object;), getAt(java.lang.String), with(groovy.lang.Closure), any(groovy.lang.Closure)
I hope you can help.
Update
Ok so i removed the filter piece and the application loaded.
However when the sendMessage got run I got the following error:
Message: No bean could be found in the registry for: TestService
I then tried to add the bean manually using the following code but still get the same error:
void configure() {
def config = grailsApplication?.config
SimpleRegistry registry = new SimpleRegistry();
registry.put("TestService", new TestService());
CamelContext context = new DefaultCamelContext(registry);
from("seda:input.queue").to("bean:TestService?method=printMsg")
}
What you need to do is use ProducerTemplate class as follows:
CamelContext context //the Camel Context running your routes
ProducerTemplate template = context.createProducerTemplate()
Object resultBody = template.sendBody("seda:input.queue", "Your body")
println(resultBody) //anything that your route puts in the body
I have managed to fix this and it was down to a missname of the bean.
I found the error by listing all current beans in the context and then changing my call.
Thanks

GORM mapping causes unit test to fail

I get a MissingMethodException when running a unit test due to the following line of code
class SystemNotification {
static mapping = {
read column: 'rd'
}
.
.
}
This is the relevant bit of the resulting stacktrace.
groovy.lang.MissingMethodException: No signature of method:
frontlinesms2.SystemNotification.read() is applicable for argument types: () values: []
Possible solutions: read(java.io.Serializable), load(java.io.Serializable), isRead(), create(), getId(), grep()
at frontlinesms2.SystemNotification._clinit__closure1(SystemNotification.groovy:6)
Removing the read->rd mapping allows the test to pass. Any thoughts on a way around this issue that does not necessitate removing the code? The domain class is from a plugin, if that's relevant. The plugin runs as a standalone app using h2, but the host application uses MySQL, where "read" is a reserved keyword, which is why we do the mapping to begin with.
Hmm so if you want column name change then you have to do following, currently you use read('x') as method:
class SystemNotification {
String read
static mapping = {
read column: 'rd'
}
}
And it is correct that test fails.

Resources