Adding methods to class and use them in other groovy code - groovy

I'm very new to Groovy. I have a class where I'm adding methods using metaClass. Here is the code I have for Parser.groovy:
PrivateClass.metaClass.convertDDTToMap { obj,fileLocation ->
}
where PrivateClass is a class coming from a jar. Now in other file named Hack.groovy I have the following code:
class Hack extends PrivateClass
{
//.. code
convertDDTToMap(param,param)
}
when I run Hack.groovy, I get the exception that the method convertDDTToMap is not there.
However Parser.groovy is in the same classpath and it gets compiled. But its not adding the method.
Where I'm making the mistake?

Parser.groovy being compiled only is doing nothing, the code there needs to be called. For example using new Parser().run()

Related

How to declare a constructor or extends a class of a groovy script?

I am working on a shared library for Jenkins, and I want to access some utilities methods between some classes, but not all of them, thus I have established some statements:
I would like to avoid using static methods, since it does not access pipeline steps directly, and passing the pipeline instance every call would be a pain;
I would like to avoid a singleton as well, or prefixing every method call with the util class' instance;
Since it is not supposed to be shared between all classes I would like to avoid putting every method as a file on vars/ special directory, but I would like a similar behavior;
Despite extending the class would be a anti-pattern, it would be acceptable, though I would like to avoid the verbose Java syntax for declaring the class the same name as the file, once it is implicit in groovy;
This question does solve my problem partially, although there are issues with serialization, I noted that when I use checkpoint and some build is resumed from some stage, the instance loses all extra methods.
This other question would have helped me fix the serialization issue, however the author seems the have solved the root cause of his problem using a way that is not the original question titled for.
Is there a way to extends a implicit script class in groovy without using the class NameOfFile extends SomeOtherClass { put every thing inside this block } syntax? And without working with inner-class?
Or else, is there a way to declare a constructor using the script groovy syntax analogue as the previous question?
Or even, is there a way to change the serialization behavior to install the extra methods again after unserializing?
Appendix
The script syntax works more-or-less like this:
Consider the content of file src/cicd/pipeline/SomePipeline.groovy:
package cicd.pipeline
// there is no need to wrap everything inside class SomePipeline,
// since it is implicit
def method() {
// instance method, here I can access pipeline steps freely
}
def static otherMethod() {
// static method, here it is unable to access pipeline steps
// without a instance
}
#groovy.transform.Field
def field
def call() {
// if the class is used as method it will run
this.method()
SomePipeline.otherMethod() // or simply otherMethod() should work
this.field = 'foo'
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
}
// any code other than methods or variables with #Field
// annotation will be inside a implicit run method that is
// triggered likewise main method but isn't a static one
def localVar = 'foo'
println "It will not execute on constructor since it is on run: $localVar"
println "Method: ${org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Throwable()).stackTrace[0].methodName}"
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
If I was going to use the Java verbose syntax I would have to wrap almost everything inside a class SomePipeline which is implicit in groovy, this is the script syntax I want to keep.
I realised that this.getClass().superclass.canonicalName when outside Jenkins pipeline is groovy.lang.Script and when inside pipeline is org.jenkinsci.plugins.workflow.cps.CpsScript and based on this resource I was able to elaborate the following solution:
abstract class CustomScript extends org.jenkinsci.plugins.workflow.cps.CpsScript {
public CustomScript() {
// do something here, it will always execute regardless
// serialization, and before everything
}
}
#groovy.transform.BaseScript CustomScript baseScript
That is it, worked as expected! Of course you can elaborate this solution better in order to reduce repeating and avoid inner-classes, but I will leave it for your imagination.

GroovyClassLoader doesn't work properly with cyrillic symbols

I created a simple interface and groovy script that implements this interface.
class groovyClass implements MySimpleInterface {
#Override
String description (){
return "Описание";
}
}
But when I call this function from groovy class loader I get just a couple of unknown symbols (like this :Широкая СЌР) instead of my cyrillic one.
I'm using Intellij Idea
Also, when I'm writing it directly new Label ("Описание") it works just fine, but when I'm requesting it from groovy class loader it doesn't work

Mocking Matcher with non native class

I am trying to write a #test in Junit using mockito and powermock. I have no issue stubbing methods that have no parameters. However when I try telling mockedBank to return true no matter what is passed into latePay, I get java.lang.NullPointerException. latePay is a final method that is why I am using powermock. Any suggestions are much appreciated.
BankGenerator mockedBank = PowerMockito.mock(BankGenerator.class);
when(mockedBank.latePay(Matchers.any(MoneyCalculator.class))).thenReturn(true);
Have you added the correct annotations to your class containing the tests?
For example:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithFinalMethod.class)
public class ClassContainingUnitTests {
...
}
I have used PowerMock with EasyMock in the past, and forgetting to include these annotations sometimes resulted in strange results.
For further reference, check here:
http://www.codeproject.com/Articles/806508/Using-PowerMockito-to-Mock-Final-and-Static-Method
Hope this helps.

Jmeter BSF using Groovy, Import one script's function to another

I use groovy in my Jmeter BSF, and sometimes I have functions that are used frequently enough to be moved to some script which I than can use as a library.
My approach was to create a file, say "library.groovy", and add there some function
public void function()
{
println("hello!");
}
and then use the following code in my BSF script
import library.groovy;
function();
Both files lie in the same dir, but script refuses to locate library. I also tried to explicitly wrap this function into class but I took no effect as well.
Can anyone suggest a solution for this?
Update:
I tried almost all possible solutions described in the internet. And everything that works in groovy console or Eclipse does not in Jmeter. Probably that is because of BSF. Anyone knows some workarounds?
I just had this problem, and solved it in a way that seems, to me, nicer-looking. It is basically winstaan74's answer, but with the extra bits needed to make it work.
You have your function's groovy file, named say: MyJmeterFunctions.groovy:
package My.JmeterFunctions
public class MyHelloClass {
public void hello() {
println("Hello!");
}
}
Then you compile this from the terminal:
$groovyc -d myJmeterFunctions myJmeterFunctions.groovy
and turn it into a .jar inside the /lib folder of your jmeter install, with all the other .jar files that came with jmeter
$jar cvf /<>/apache-jmeter-2.8/lib/myJmeterFunctions.jar -C myJmeterFunctions .
Now, restart jmeter. It won't know about your new .jar until you do.
Lastly you have the script that you want to run the hello() function from, which your jmeter BSF assertion/listener/ whatever points to:
import My.JmeterFunctions.*
def my_hello_class_instance = new MyHelloClass();
my_hello_class_instance.hello();
And this is what worked for me. If you'd rather organize you .jar into a different folder than jmeter's /lib, I believe you can run jmeter using (from here):
$jmeter -Jsearch_paths=/path/to/yourfunction.jar
But I haven't tried that myself.
I ended up having 2 files like below:
"MyHelloClass.groovy"
public class MyHelloClass {
public void hello() {
println("Hello!");
}
}
And "HelloScript.groovy"
try {
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(new File("../GroovyScripts/MyHelloClass.groovy"));
GroovyObject helloClass = (GroovyObject) groovyClass.newInstance();
helloClass.hello();
}
catch (Throwable e) {
println(e.toString());
}
Then I can run "HelloScript.groovy" in BSF from Jmeter.
I think you'll need to wrap your helper methods in a class, and then import that class. So, your helper methods file should contain..
package library
class UsefulFunctions {
static function() {
println 'hello'
}
}
And then in your test script, say
import static library.UsefulFunctions.*
function()
Now, this is just scratching the surface, but I hope it'd be enough to get you started.

Is there any way to use groovy and java code for the same class?

I mainly program in groovy, but occasionally it's too slow. So I write a separate .java class, and put the code that needs to run faster in a java method and call that java method from my groovy code.
This causes me to end up with two separate files and two separate classes. Is there any way I could embed a java method right into the groovy file, maybe marking it with an annotation to indicate that it is java?
This is the idea behind groovy++. Marking a class or method with the #Typed annotation will cause it to use static typing instead of dynamic typing, while still retaining a lot of goodness of groovy.
While not exactly java, typed groovy++ methods generally perform about the same as java would.
More information on groovy++ is available at: https://code.google.com/p/groovypptest/wiki/Welcome
You don't need to do anything special.
Just write the Java class behind the groovy class. 99% of all Java source is valid groovy source as well.
class GroovyClass {
def a;
def doSomething(x,y) { return x*y; }
}
class JavaClass {
SomeType someVar;
public JavaClass() { /* ... */ } // some contructor
public void doit(String a, int b) {} // full typed method, that is java
}
Groovy++ is somethign completely different.
The JavaClass needs to have everything fully typed to be "Java" however your problem can be solved far easyer if you just use types in the relevant groovy methods.
class AnotherGroovyClass {
// typed
public Result someMethod(SomeArg arg1, SomeOtherArg arg2) {
}
def someVariable; // untyped
}
If you think the lack of speed comes from the dynamic nature of groovy then just use full types at the relevant points.

Resources