How to use #CompileStatic for pure groovy scripts in JMeter environment? - groovy

I'd like to take advantage of #CompileStatic annotation in my groovy scripts in jmeter environment. It helps a lot to discover issues in compile time.
I already started to use it in my classes but I don't know how to use it in case of plain groovy scripts. For example, I have the script below and there are the log and vars variables which are kind of global variables in JMeter environment. So, eventually they will be used.
If I add the #CompileStatic annotation to the method below IntelliJ paints red everything and compile will fail because the compiler doesn't know what these variables are.
So, the question is how to tell the compiler in a case of a script these variables has type and what type they have, and how an instance will be provided for the script?
I apologize, I'm not a groovy expert at all.
void checkingInputParameters() {
log.info("variable value:" + vars.get("some_variable_name"))
}
checkingInputParameters()

I think you are in the wrong path,
because CompileStatic is a groovy compiler option
let the Groovy compiler use compile time checks in the style of Java then perform static compilation, thus bypassing the Groovy meta object protocol.
JMeter (and I assume your tests in Intellij ) is using a java compiler
I don't think you should mix them for tests.
In JMeter use Cache compiled checkbox/feature
checking Cache compiled script if available

Related

Is there any global flag for Groovy static compilation?

I know that since Groovy 2.0 there are annotations for static compilation.
However it's ease to omit such annotation by accident and still run into troubles.
Is there any way to achieve the opposite compiler behaviour, like compile static all project files by default and compile dynamic only files chosen by purpose with some kind #CompileDynamic annotation for example?
I have found some (I believe recently introduced) feature which allows doing so with Gradle.
In build.gradle file for the project containing groovy sources we need to add following lines:
compileGroovy {
configure(groovyOptions) {
configurationScript = file("$rootDir/config/groovy/compiler-config.groovy")
}
}
or compileTestGroovy { ... for applying the same to test sources. Keep in mind that neither static compilation nor type checking works well with Spock Framework though. Spock by its nature utilizes dynamic 'groovyness' a lot.
Then on a root of the project create folder config/groovy/ and a file named compiler-config.groovy within. The content of the file is as follows:
import groovy.transform.CompileStatic
withConfig(configuration) {
ast(CompileStatic)
}
Obviously path and name of the configurationScript may vary and it's up to you. It shouldn't rather go to the same src/main/groovy though as it would be mixing totally separate concerns.
The same may be done with groovy.transform.TypeChecked or any other annotation, of course.
To reverse applied behaviour on certain classes or methods then #CompileDynamic annotation or #TypeChecked(TypeCheckingMode.SKIP) respectively may be used.
I'm not sure how to achieve the same when no Gradle is in use as build tool. I may update this answer in the future with such info though.
Not at this time, but there is an open Jira issue here you can follow to watch progress for this feature
There was also a discussion about methods for doing this on the Groovy developers list

Groovy script classpath issue with SystemClassLoader

I'm writing a Groovy script which uses third party java code that I can't change.
This code uses (badly, I think) ClassLoader.getSystemClassLoader().getResourceAsStream("/hard/file/path/in/jar/file")
and expect to read a file.
Everything goes well from Java when using java -cp "/path/to/jar/file" ...
However, the third-party code is now to be integrated with a bunch of Groovy code we've already written, so we wanted to run it from groovy.
So we wrote a Groovy script, let it call test.groovy, and ran it as groovy -cp "/path/to/jar/file" test.groovy.
The problem is that code can't access the file resource, as it seems Groovy doesn't load its jars in the System ClassLoader directly.
For proof, with Thread.currentThread().getContextClassLoader().getResourceAsStream("/hard/file/path/in/jar/file") within the Groovy Script, I can read the file, but with ClassLoader.getSystemClassLoader().getResourceAsStream("/hard/file/path/in/jar/file"), I can't.
So, does anyone know how to load the class in System ClassLoader from a Groovy Script without beginning to try some dirty hacks (like metaclassing getSystemClassloader to return the context classloader)?
You could try adding the jar to the system classloader as well when your script runs, like so:
ClassLoader.systemClassLoader.addURL new File( '/path/to/jar/file' ).toURI().toURL()
PS: I assume you mean ClassLoader.getSystemClassLoader() in your question, rather than System.getSystemClassLoader()
You can try to put your jar into %GROOVY_HOME%\lib folder or make a wrapper around your groovy command and modify %CLASSPATH% variable before you start your Groovy process.

How to run a set of dependent groovy scripts without compilation?

I've got a set of groovy scripts (or should I say a groovy app) which has hierarchical java alike package structure and script names the same as class names. All of them are called from the main script (like a java class with main method). I need to call just that particular main script and get all other scripts executed in sequence when needed (or loaded and executed).
Practically, this can be acieved by having all scripts compiled and .class files obtained and put into classpath while running the main script, but that's quite redundant for a scripting (the idea is to have it working without compilation, even though groovy will do it somwhere behind the scene)
How can I achieve it?
Groovy can be used in a scripting environment quite easily - no compile step required. Read this:
http://groovy.codehaus.org/Running
You can write your usual main method etc. and call it like this,
groovy -cp foo/ foo/MyScript.groovy [arguments]
Or if you're in a *nix environment you can give it a shebang like so,
#!/usr/bin/env groovy
println("Hello world")
for (a in this.args) {
println("Argument: " + a)
}
and run it using ./fileName (provided you've marked it as executable)

Is there a "use strict" for Groovy?

I remember from my Perl days the "use strict" statement that cause the runtime to do extra validations. Is there an equivalent for Groovy?
I do not enjoy being bitten during runtime by what can be detected on compilation, like passing too few arguments to a constructor.
Groovy 2.0 now has optional static type checking. If you place a #groovy.transform.TypeChecked annotation on a class or method, groovy will use strict, Java-like static typing rules.
In addition, there's another annotation #groovy.transform.CompileStatic that is similar, except it goes a step further and actually compiles it without dynamic typing. The byte code generated for these classes or methods will be very similar to straight Java.
These annotations can be applied to an individual class or method:
import groovy.transform.TypeChecked
#TypeChecked
class MyClass {
...
}
You can also apply them globally to an entire project without adding annotations to the source files with a compiler config script. The config script should look something like this:
withConfig(configuration) {
ast(groovy.transform.TypeChecked)
}
Run groovy or groovyc with the -configscript command line option:
groovyc -configscript config.groovy MyClass.groovy
There's more information in the Groovy manual:
http://groovy-lang.org/semantics.html#static-type-checking
http://groovy-lang.org/semantics.html#_static_compilation
Is there an equivalent for Groovy?
Not that I know of.
I do not enjoy being bitten during
runtime by what can be detected on
compilation, like passing too few
arguments to a constructor.
Then Groovy is probably the wrong language for you and you should use something like Java or C# instead. Alternatively, there is a version of Groovy, known as Groovy++ which has much stronger type-checking, but I don't consider it sufficiently mature for production use.
IntelliJ (and possibly other IDEs) provides a lot of warnings about dodgy Groovy code. Although these warnings don't prevent compilation, they almost give you the best of both worlds, i.e. the safety of a static language and the flexibility of a dynamic language
No, there is no such thing, and there can't be. Perl's "use strict" only prevents the use of undeclared variables (and some very Perl-specific things that I don't think have equivalents in Groovy).
In dynamic languages like Groovy, "passing too few arguments to a constructor" is fundamentally not something the compiler can detect, because class definitions can be changed at runtime via metaprogramming. Also, you usually don't have the type information necessary to know what class to look at.
If you want maximum compile-time checks, use a statically typed language with no metaprogramming, i.e. Java.

How can create a Junit4 Suite with Groovy?

I have
#RunWith(Suite.class)
#Suite.SuiteClasses( [
First.class,Second.class
])
public class MySuite{
}
But eclipse doesn't give me a "Run As Junit4 Test". All the individual test classes work fine with GUnit, the groovy unit test runner built into eclipse.
Any thoughts?
The only way I found to do this was to create a java class with a #Suite.SuiteClasses annotation as usual. You can put in the .class names of the Groovy classes you have for tests and it works well.
Kind of lame if you don't already have some java code to do it this way but I had a mix of Java and Groovy so it wasn't as big a deal.
The other option is to not use Suites at all and to use name patterns to find and run tests. Both ant and maven support this sort of pattern matching. I find it much easier than making sure I keep the suites up to date and Eclipse can just run all tests in a package if I want to do that.
Thanks for the help.
#Suite.SuiteClasses accepts Class[] as its parameter.
You may try:
#RunWith(Suite.class)
#Suite.SuiteClasses([First.class, Second.class] as Class[])
public class MySuite {
}

Resources