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

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.

Related

How to run a cli script in pimcore

till Now I have been placing all my code within pimcore\cli\startup.php and it's run fine but when I'am trying in another way I getting error like
Class 'Website\ObjectExporter' not found in C:\xampp\htdocs\pimcore\website\var\cli\export-objects.php on line 7
How to run code in this way
For example create an ObjectExporter.php under /website/lib/Website folder with this content:
<?php
namespace Website;
class ObjectExporter
{
public function exportObjects()
{
// Your code
}
}
Then you can either instantiate this class in your controller action or in a CLI script. Controller actions are within /website/controllers folder and they need to be called through http: http://localhost?controller=default&action=default
Example: /website/controllers/DefaultController.php
<?php
class DefaultController extends Website_Controller_Action {
public function defaultAction () {
$this->disableViewAutoRender();
$objectExporter = new Website\ObjectExporter();
$objectExporter->exportObjects();
}
}
(You could also add your whole code directly into action, but that would be a bit ugly solution, it of course depends)
But better and quickest way to approach such tasks is with the CLI scripts.
I like to use the /website/var/cli folder (you need to create it manually, but the /website/var folder is excluded in .htaccess by default which makes it practical for such use cases).
Example: /website/var/cli/export-objects.php
<?php
$workingDirectory = getcwd();
chdir(__DIR__);
include_once("../../../pimcore/cli/startup.php");
chdir($workingDirectory);
$objectExporter = new Website\ObjectExporter();
$objectExporter->exportObjects();
Then just run it by issuing this command in your command line:
php website/var/cli/export-objects.php
This is the standard way of creating CLI scripts in pimcore:
https://www.pimcore.org/wiki/pages/viewpage.action?pageId=16854341
Basically it's just Symfony/Console, which is documented in here detail:
http://symfony.com/doc/current/components/console/introduction.html

Access tied files through groovy in jenkins

I'm building a Jenkins plugin, and am handling the UI components using Groovy. In jelly, you can use "${it.something}" to access information in the java file tied to the jelly file, as shown here:
class:
public String getMyString() {
return "Hello Jenkins!";
}
jelly:
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
xmlns:t="/lib/hudson" xmlns:f="/lib/form">
${it.myString}
</j:jelly>
from https://wiki.jenkins-ci.org/display/JENKINS/Basic+guide+to+Jelly+usage+in+Jenkins.
I'd like to do the same thing in groovy, but can't seem to find an example of how it's done. Any examples?
After even more searching and some luck, I found the correct way to do this. If I was to use the class in my question but wanted to use groovy instead of jelly, the groovy code would look like this (this puts the string in the textbox):
package something.something;
import lib.JenkinsTagLib
import lib.FormTagLib
def f = namespace(lib.FormTagLib)
t=namespace(JenkinsTagLib.class)
f.entry(title:"text", field:"text") {
f.textbox(value:instance?.text)
}

Populating variables in a groovy script from a java program

I know how to call Groovy code from Java code, but can you, while running Groovy script script.groovy, ask a Java program to populate its varabies?
// script.groovy
import static org.mydomain.WiseJavaProgram.*;
pleasePopulateMeWithVariables();
println numberOfLegs // 2
// We didn't declare numberOfLegs in our sript, the Java program set it for us.
I guess maybe for that script.groovy should pass its environment to the pleasePopulateMeWithVariables method, but I haven't found how to do that. Is this even possible?
The case where I want to use such behavior: I have script.groovy, and also an undefined number of groovy scripts of which Java program knows, but of which script.groovy doesn't know, and I want to add what is declared in them to script.groovy. Basically those additional scripts are data, for example descriptions of various products and their features. This is easy if you run a Java program that creates GroovyShell and evaluates in it data-scripts and then script.groovy, but for me it is necessary that we initially call script.groovy, not the Java program.
Just as usual, while asking the question I was one step behind the answer -__-
The "environment" I was searching for is the Script object itself, available from script.groovy simply as this. So:
// script.groovy
import static org.mydomain.WiseJavaProgram.*;
populateWithVariables(this);
println numberOfLegs // 2
// WiseJavaProgram.java
public class WiseJavaProgram {
public static void populateWithVariables(Script script) {
script.evaluate('numberOfLegs = 2');
script.evaluate(new File("another.groovy"));
script.evaluate(new File("yetAnother.groovy"));
}
}

Adding methods to class and use them in other groovy code

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()

using components in Cakephp 2+ Shell

I am trying to implement a task using the cakephp shell for my application. The task involves running a long running process (hence the need to use the shell).
The function requires me to use a function inside a Component called CommonComponent
Unfortunately whenever i try to include the component i get the following error
PHP Fatal error: Class 'Component' not found in /var/www/nginx-test/app/Controller/Component/CommonComponent.php
Here is the CronShell Class which is being called
class CronShell extends AppShell {
public function main() {
$this->out('Hello world.');
// $this->out(phpinfo());
}
public function test()
{
$this->out('Before Import');
App::import('Component', 'Common');
$this->out('Import complete');
// $this->Common=ClassRegistry::init('CommonComponent');
$this->Common =new CommonComponent();
$this->out('Initialization complete');
$this->Common->testCron();
$this->out('FunctionCall complete');
//$this->Common->saveCacheEntry("name","value");
}
}
The CommonComponent class is stored as app/Controller/Component/CommonComponent.php and is as follows
class CommonComponent extends Component
{
function testCron()
{
$this->out('Hello world from Component.');
}
}
Any ideas?
I had to do this recently with MTurk component I wrote. My final solution was using a lib instead of a component. Then I had the component access the lib so I could use the methods from both a component and from shell.
However, here is code that WILL allow you to load a component from a shell.
<?php
App::uses('AppShell', 'Console/Command');
App::uses('ComponentCollection', 'Controller');
App::uses('Controller', 'Controller');
App::uses('MTurkComponent', 'Controller/Component');
class ProcessCompletedTask extends Shell {
public function execute() {
$this->out("Processing...\n");
$collection = new ComponentCollection();
$this->MTurk = new MTurkComponent($collection);
$controller = new Controller();
$this->MTurk->initialize($controller);
$this->MTurk->processHITs();
$this->out("Complete\n");
}
}
What you import into the Shell should be code from within your Apps Lib
the component can also make use of the Lib code - but you'll not need to do a load of tedious stuff
if you set it up right you'll make you app cleaner
if you import the component you'll need to pass it a component collection and so you'd have to make that from witin shell not that your use it (or if you do you must be doing it wrong)
Have you tried App::uses('Component', 'Controller'); at the top of your file, ev. before import of CommonComponent? Then I guess you need to do what sam says, or you could use the $this->Controller->Components->load('CommonComponent') but for that you need to construct the Controller class.
I believe that it is semantically wrong to share functionality between controllers and shells.
If you require common functionality, it is clearer and neater to put it in a separate class, place this class in your vendors folder and then import the code into both the controller and the shell.
In addition, this approach does not prevent you from creating components and tasks that use the core functionality and then share these components and tasks between your controllers and shells.

Resources