Java with Beanshell to access fields and object with clean code - java

1). I know how to access the java fields and object in beanshell from my question Use java class fields in beanshell. However, it is not so clean way to implement as I need to first set the java variable in beanshell and then I can use it. However, in Jmeter it provides very clean way of using maps in beanshell similar way as we do in java, but JMeter has developed it's know library (class) which helps to access get/put methods for maps. I want to achieve similar way to access Map in beanshell.
I have checked JMeter for more information and I want to know that, I have created user define variable temp and assign value error, now in BSF process I just write a line vars.put('Name','temp Value') and it has updated value for temp variable. So, the question is I have not created JMeterVariables object vars but still beanshell allows to update values in map without setting any values as mention in your answer. I want to know how this works, need more depth information.
2). I have created my own class in java and in beanshell I am importing this class but it is giving Command not found: BSClass() below is the entire code
Java class
package test;
public class BSClass {
public void BSCMethod(){
System.out.println("I am from BSClass method BSCMethod");
}
}
sample.bsh
import test.BSClass;
c=BSClass();
c.BSCMethod();
print("I am from BeanShell Script");
Calling sample.bsh file java class
package test;
import java.io.FileNotFoundException;
import java.io.IOException;
import bsh.*;
public class DynamicVariable {
public static void main(String[] args) throws FileNotFoundException, IOException, EvalError {
new bsh.Interpreter().source("\\src\\test\\sample.bsh");
}
}
Note:
I don't need help in JMeter, it is to use in core java and beanshell.
All the files are in my project.
BSClass.class is under bin folder of my project
I would appreciate your inputs

In Beanshell you can add any Object you want including a Map
In JMeter, JMeterVariables is special implementation of Map that is added to Beanshell Interpreter before evaluate and also special Object as JMeterContext is added which even includes JMeterVariables inside. Code:
JMeterContext jmctx = JMeterContextService.getContext();
JMeterVariables vars = jmctx.getVariables();
try {
bshInterpreter.set("ctx", jmctx);//$NON-NLS-1$
bshInterpreter.set("Label", getName()); //$NON-NLS-1$
bshInterpreter.set("prev", jmctx.getPreviousResult());//$NON-NLS-1$
bshInterpreter.set("props", JMeterUtils.getJMeterProperties());
bshInterpreter.set("vars", vars);//$NON-NLS-1$
In your case with map you can do similar as you describe in comment:
bshInterpreter.set("myMap", javaMyMapObject);"
Then in Beanshell get the specific key from map:
myMap.get("aField");
To create class you should use new keyword, call:
c= new BSClass();
instead of c=BSClass();
If you create your own class, Class should be inside jar in relevant package .
The jar should be located in lib folder and not in bin folder, see JMeter's getting started:
Any jar file in such a directory will be automatically included in
user.classpath, jar files in sub directories are ignored. The given
value is in addition to any jars found in the lib directory. All
entries will be added to the class path of the system class loader and
also to the path of the JMeter internal loader.

Related

Use a groovy script from another groovy script

I want to use a 'Util' groovy script inside another groovy script. I don't want to load 'Util' class inside my 'main' groovy script every time. So using evaluate or GroovyShell don't fit my case.
My java application fetches the 'main' groovy script body from a database, parse it and call test() method from 'main' script every time.
java code :
GroovyShell groovyShell = new GroovyShell();
Script parsedScript = groovyShell.parse(scriptBody);
ResultPojo result = (ResultPojo) parsedScript.invokeMethod("test", null);
'main' script
public int test(){
// this will not work at the moment
int result = GroovyUtils.sum();
return result;
}
A 'Util' class will be located in the database too. 'Util' classes will be somehow loaded on application startup and they will be reloaded every X minutes.
class GroovyUtils{
static int sum() {
return 2+1;
}
}
Like i said i don't want to 'parse' the GroovyUtils class inside 'main' script because this is time costly.
Ideally i want to import GroovyUtils script when i need it.
import groovy.GroovyUtils;
public int test(){
int result = GroovyUtils.sum();
return result;
}
But in order to import the script, the script need to be saved in the same folder that the java application runs. The java application is deployed on a remote application server in .war format.
Can i somehow load GroovyUtils dynamically to CLASSPATH without saving it, so i can import it from my 'main' script?
Any suggestions? My main concerns is speed and reloadability.
if you'd like to create a delivery process through the database you can do it by extending GroovyClassLoader and implementing public Class loadClass(name, lookupScriptFiles, preferClassOverScript, resolve) method that will search classes in some table in a database.
Let me simplify your goal and exclude database.
There is a standard behavior of classloaders: search and load classes among the classpath
The GroovyClassLoader allows to add new paths to a classpath at runtime, so it will search additionally classes in specified folder or jar file.
classloader keeps parsed classes in memory and groovy classloader provides protected method to remove class definition by name: removeClassCacheEntry(java.lang.String)
and finally example:
/myprj/classes/util/MyClass.groovy
package util
class MyClass{
def echo(msg){ println msg }
}
code to run main script
//create shell and init classloader just once
GroovyShell gs = new GroovyShell()
gs.getClassLoader().addClasspath("/myprj/classes/")
//forces classloader to recompile on file change
//this is alternative to removeClassCacheEntry
//but in some specific cases this reload will not work
gs.getClassLoader().setShouldRecompile​(true)
Script script = gs.parse('''
import util.MyClass
new MyClass().echo("hello world")
''')
script.run() // prints 'hello world'
//removeClassCacheEntry is alternative to setShouldRecompile​
//you can use it to remove compiled class from this classloader
println gs.getClassLoader().getLoadedClasses() // outputs util.MyClass, and Script1
gs.getClassLoader().removeClassCacheEntry("util.MyClass")
println gs.getClassLoader().getLoadedClasses() // outputs Script1
returning to the database: you could have a daemon thread that scans database for groovy code changes and exports modified sources into a folder that was defined as additional classpath and triggers removeClassCacheEntry for the classloader. So, next access to removed class will force to parse it by GroovyClassLoader.
NOTE: by using dynamic class loading you could have situation when two versions of same class present in memory and they will not be comparible and assignable to each other. So, you could have the error like: could not assign MyClass to MyClass

How can you set the search path for JavaToRascal from Java

We tried to import a test rascal module and a module from the standard library using JavaToRascal.
The test module is stored in C:\Users\Klemens\workspace\RascalInterop\src\MyTest.rsc and contains:
module MyTest
Te java code containing the JavaToRascal invocation is as follows:
import java.io.PrintWriter;
import java.net.URISyntaxException;
import org.rascalmpl.interpreter.JavaToRascal;
import org.rascalmpl.interpreter.load.IRascalSearchPathContributor;
import org.rascalmpl.interpreter.load.StandardLibraryContributor;
import org.rascalmpl.interpreter.load.URIContributor;
import org.rascalmpl.uri.URIUtil;
public class RascalInterop {
public static void main(String[] args) throws URISyntaxException {
JavaToRascal j2r = new JavaToRascal(new PrintWriter(System.out), new PrintWriter(System.err));
IRascalSearchPathContributor modulePath = new URIContributor(URIUtil.createFileLocation("C:\\Users\\Klemens\\workspace\\RascalInterop\\src\\MyTest.rsc"));
j2r.getEvaluator().addRascalSearchPathContributor(modulePath);
try {
j2r.eval("import MyTest;").toString(); // Could not import module MyTest: can not find in search path
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
j2r.getEvaluator().addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
j2r.eval("import IO;").toString(); // null pointer exception
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
The print in the first try block that tries to import our MyTest.rsc module results in:
Could not import module MyTest: can not find in search path
?[Advice](http://tutor.rascal-mpl.org/Errors/Static/ModuleImport/ModuleImport.html)
The second import attempting to import the IO module from the standard library results in:
class java.lang.NullPointerException
Any ideas how to use properly set the search path from a Java program?
We tried to use j2r.getEvaluator().addRascalSearchPathContributor in various ways but did not succeed in loading a MyTest.rsc module from the given directory.
Despite that these API will change in the near future (due to the compilation process and related changes), here's an answer. Two answers actually, one for Rascal files and one for Java code that it needs
For Rascal:
j2r.getEvaluator().addRascalSearchPathContributor
What you used is the correct way of doing things. So if it did not work, please provide more code so we can diagnose what goes wrong. So where is your module? Is it in a jar file or a binary folder? If its in a jar, you need some additional wiring I'm glad to explain.
The Rascal search path is distinguished from the Classpath for Java classes which are used by Rascal. So you have different API for that. We use classloaders to find Java files (such that it also works for situations like OSGI bundles in Eclipse):
Evaluator x = ctx.getEvaluator();
x.addClassLoader(getClass().getClassLoader());
This will make sure that the class loader used to load the current class is also used to load the class linked mentioned in the Rascal file. Of course you can also provide other class loaders. Note that if the libraries you depend on are loaded via OSGI, make sure you get a classloader from a class that is in a bundle that has access to these classes. The simple case is when everything is in the same jar file, then any classloader will do.
I think you should change the path to refer to the src directory instead of the source file:
new URIContributor(URIUtil.createFileLocation("C:\\Users\\Klemens\\workspace\\RascalInterop\\src"));
Also: probably you should use forward slashes without C:\, so /Users/.../src
AFAIK The null pointer exception is expected, evaluating import returns null, and you try to call toString().

Class reference is taken from different jar

There are some classes used in a java program referred from abc package from xyz.jar. The package is imported in the java file.
Also the same class is in other lmn.jar.
So if I delete the jar file from the project, i should be getting the error.
But the class compiles and takes the class from the other lmn.jar.
Eg.
weblogic.jdbc.oci.Blob is a class in weblogic.jar
But if i delete weblogic.jar, it takes it from java.sql.Blob.
I don't want this to happen, the program should display error.
In such a case you can use fully qualified name of class, which will include package name. For example, instead of:
Blob blob = new Blob();
You can write:
weblogic.jdbc.oci.Blob blob = new weblogic.jdbc.oci.Blob();
When importing a class you are also defining the package. So when you import "weblogic.jdbc.oci.Blob" and remove this class from classpath it will not automatically import it from a different package unless you change the import statement as well.
Some IDEs might automatically try to resolve classes and add the missing import statements. Maybe check that.
For one of the case try to use the entire path, ie
For example if you need Blob from weblogic.jar
then try to call weblogic.jdbc.oci.Blob bl = ...

Access classes from package

I'm developing an android test app and i'm going to access all internal class of android.view package. android.view is a package that is present in jar file. I tried by loading package name but it doesn't display the classes if any one tried
this already, please help.
Here's what I tried so far:
public static void main() throws ClassNotFoundException{
Class o =Class.forName("android.view");
Class[] C=o.getDeclaredClasses();
for(int i=0;i<C.length;i++) {
Classname = C[i].getName();
ClassesDisplayActivity.your_array_list3.add(Classname);
Log.i("Ramu","classname "+ C[i].getName());
}
}
}
It is not possible to determine at runtime all of the classes that are in a package using a standard class loader.
You might have some luck with this library though:
https://code.google.com/p/reflections/
Package is not a class. You cannot call Class.forName() for package and access classes that belong to class using getDelcaredClasses().
I do not know what do you really need, so I'd recommend you to explain this in separate question. probably you will receive better solutions.
However if you really need this you have to do the following:
Get your classpath by calling System.getProperty(java.class.path)
split this property to its elements by colon
iterate over the list and read each resource. If resource is jar you can use ZipInputStream, if it is a directory use File class.
filter list of resources you got at #3.
Fortunately you can use 3rd party library named Reflections that helps you to do all this without writing code.

How do I get all the class names and method names of a project?

I have downloaded a huge project written in Java. I wish to know the Classes and Methods of every class that are available in the project (for further analysis). How can I recover this information. Can I try javadoc in eclipse?
I guess you may ask about changing SVN properties.
Follow this step if that so.
press Alt + Shift + Q
Select Show view (view : Outline)
then under that u can see all details
I have wrote a custom doclet to list the classname and its methods:
public class ListClassAndMethods {
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
for(ClassDoc clazz : classes){
System.out.println("Class Name: "+clazz);
System.out.println("--------------------------");
for(MethodDoc methodz :clazz.methods()){
System.out.println(methodz.name());
}
}
return true;
}
}
you need to run create a jar of this class and refer it while creating
a javadoc using Eclipse IDE
I would extract all the class source files (.java) with find (if you're on a *nix implementation) and create an empty NetBeans project with just one package and all the classess inside it. Netbeans will correct the package declaration and you can easily use autogenerate javadoc to get a navigable web archive listing all the classes and public/protected methods.
Of course the code may not run anymore but you'll get what you want in minutes.

Categories