How to use beanshell
beanshell Manual:
http://www.beanshell.org/manual/bshmanual.html
You can simply omit the types of variables that you use (both primitives and objects).
Beanshell automatically converts them to properly type before execute any operations. BeanShell will only signal an error if you attempt to misuse the actual type of the variable.
take one method for an example:
add(a, b) {
return a + b;
}
Interpreter bsh = new Interpreter();
bsh.eval("print(add(1,2))");
bsh.eval("print(add(\"Oh \",\"baby\"))");
bsh.eval("print(add(\"1\",2))");
add(a, b) {
c=5;
return a + b;
}
@gt | > |
@lt | < |
@lteq | <= |
@gteq | >= |
@or | || |
@and | && |
@bitwise_and | & |
...
It is very useful when containing beanshell inside XML.
Demo 1:
import bsh.Interpreter;
Interpreter i = new Interpreter(); // Construct an interpreter
i.eval("print(5>4)"); // it will output: true
i.eval("print(\"5>4\")"); // it will output: 5>4
i.eval("print(5@gt4)"); // it will output: true
i.eval("print(\"5@gt4\")"); // it will output: 5@gt4
Inside XML, we can use the beanshell like following:
if(a @gt b) {
//...
}
(Image from http://www.beanshell.org/images/embeddedmode.gif)
First, you should add beanshell library into your application classes path. For the moment, it is bsh-1.3.0.jar.
import bsh.Interpreter;
Interpreter i = new Interpreter(); // Construct an interpreter
The Interprete eval() method accepts a script as a string and interprets it, optionally returning a result. The string can contain any normal BeanShell script text with any number of Java statements. The Interpreter maintains state over any number of eval() calls, so you can interpret statements individually or all together.
TIt is not necessary to add a trailing ";" semi-colon at the end of the evaluated string. BeanShell always adds one at the end of the string.
i.eval("foo=\"Foo\""); // it will set a loostly typed varialbe foo with initial value "Foo".
i.eval("for (i=0;i<5;i++) print(i);") // it will display: 0 1 2 3 4
is not same as:
i.eval("for (i=0;i<5;i++)")
i.eval("print(i);") // it will display: 5
Eash script string inside eval() should be a entire operation. Follwoing invocation will cause error:
i.eval("for (i=0;i<5;i++) {")
i.eval("print(i);")
i.eval("}")
You can use set(String name, Object value) to set variables into beanshell interpreter.
For example, you have a beanshell script:
c = 5;
foo () {
c = a + b;
//print(c);
return c;
}
You can set a and b like following:
i.set("a", 1);
i.set("b", "2");
Then you can perform an operation by invoke eval():
i.eval("foo()");
Now you can get value of c by invoke get():
i.get("c"); // you will get "12".
unset(variable) used to remove a variable from the current scope. (Return it to the "undefined" state).
clear() used to Clear all variables, methods and imports from the current scope. It is not embedded in Interpreter class for the moment.
The Interpreter source() method can be used to read a script from an external file:
i.source("/opt/tmp/mybeanshell.bsh");
source("beanshell script file") will read and interprete specified beanshell script file. You can use it to valid and test your beanshell script.
It is very important to import classes that will be referenced inside beanshell script. By default, beanshell interpreter import common Java core and extension packages for us. They are, in the order in which they are imported:
Two BeanShell package classes are also imported by default:
You can define classes import in bean shell scipt:
import com.gemalto.wgu.*;
Alternatively, you can also import classes through eval():
i.eval("import com.gemalto.wgu.*");
Here I would like to list four different approaches on how to invoke script in Java Application.
Write your function in beanshell script file as global definition without define special method, in this case, your function code will be loaded and executed when interpreter source scripting file.
myfile.bsh:
c = 5 + 6;
print(c);
Interpreter.source("myfile.bsh"); // it will execute "c= 5 + 6" and print "11" directly.
2--> Script Methods and eval(): define your function in script method and call it in your application through eval()
Define your function inside a methods, then invoke method by eval(). If there are some other parameters, you can set("parametername", object_instance ) them.
myfile.bsh:
displayPlainPage(BufferedReader in, PrintStream out) throws IOException { String line; while ((line = in.readLine()) != null) { out.println(line); } }
Interpreter bsh = new Interpreter();
bsh.source("myfile.bsh");
bsh.set("in", BufferedReader Instance);
bsh.set("out", PrintStream Instance);
bsh.eval("displayPlainPage(in, out)"); // it will execute your function code.
Please be note: eval() will return result in "Object" instance to java context.
Interpreter bsh = new Interpreter();
bsh.eval("myObj.displayPlainPage(in, out)");
You can define any java interface for your function:
public inteface IDisplayLog{
public void displayPlainPage(BufferedReader in, PrintStream out) throws IOException;
}
Then write a script method implement this API and return the object instance with explicity cast:
myfile.bsh:
Thanks to its lightly, no need compile, compliant with Java and loosely typed variables (which will be automatically gurranted by beanshell), you can use beanshell to make your application really flexible.
When your application meets one or some of following factors:
Please try beanshell to see if it can solve your issue and save time.
From beanshell manual: http://www.beanshell.org/manual/embeddedmode.html, you can see some general advice on when to use beanshell:
In fact, some tools had already embedded beanshell support to provide flexible customized features.
For myself, I am using Jmeter and OsWorkflow engine. Both of them had embedded beanshell support. For example, we can use beanshell in workflow defintion:
<step id="2" name="XXX"> <actions> <action id="1001" name="Action 1" view="Action 1"> <pre-functions> <function type="beanshell" name="XXX"> <arg name="script"> import java.util.*; // Business logical in beanshell. transientVars.put("_simMenuTargetNode", SIMServiceTargetPath); </arg> </function> </pre-functions> <results> //... </results> </action> </actions> </step>