Jmeter custom functions - java

I need to create a custom function in Jmeter, and because of performance issues I can't use beanshell.
I wrote a java class following http://gabenell.blogspot.com/2010/01/custom-functions-for-jmeter.html and http://code4reference.com/2013/06/jmeter-custom-function-implementation/, but when I compile it I can't seem to get Jmeter to recognize it.
My class:
package custom.functions;
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.functions.AbstractFunction;
import org.apache.jmeter.functions.InvalidVariableException;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class Username extends AbstractFunction{
private static final List<String> desc = new LinkedList<String>();
private static final String KEY = "__Username";
private int number = 0;
static {
desc.add("Pass a random value to get a valid username for the system.");
}
public Username() {
super();
}
#Override
public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
throws InvalidVariableException {
try {
return getValue(number);
} catch(Exception e){
throw new InvalidVariableException(e);
}
}
public String getValue(int number){
return "John-Smith";
}
#Override
public synchronized void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
checkParameterCount(parameters, 1, 1);
Object[] values = parameters.toArray();
number = Integer.parseInt(((CompoundVariable) values[0]).execute().trim());
}
#Override
public String getReferenceKey() {
return KEY;
}
#Override
public List<String> getArgumentDesc() {
return desc;
}
}
When I run jar tf custom-functions.jar (to verify that the class file is in the jar):
META-INF/
META-INF/MANIFEST.MF
custom/
custom/functions/
custom/functions/Username.class
I placed the jar in my jmeter lib/ext directory and tried running jmeter by itself and with -Jsearch_paths=../lib/ext/custom-functions.jar, but either way when I open the function helper tool it's not listed, and a simple test plan to verify the function sends instead %24%7B__Username%281%29%7D.
Am I not putting the file in the right place? Is it named incorrectly?

You can put groovy-all.jar on the classpath of Jmeter, and then you will be able to run external .groovy scripts or you can add a JSR223-Groovy Sampler.

My problem was that I had compiled my class using Java 8 instead of Java 7, which was the runtime I was using for jmeter.

Related

How to test a Java Library in Eclipse

I'm looking for a way to test a java library. I never worked before with libraries written by me, and I'm trying to understand how to debug a java project without a main method. In particular, I took a java library that handles barcodes and I'm trying to change its contents. In the example version there is only a bar code, while I need to implement other types of bar codes. Since in the decompiled library imported into Eclipse there is no Main method to debug the content and see any errors. Operationally how can I do in Eclipse that execute the code, instead of each time exporting the jar file and replacing it in the classpath that containing the original library?
I looked for something online, but I didn't find an example tha t explains how to do.
import com.crystaldecisions.reports.common.CrystalResourcesFactory;
import com.crystaldecisions.reports.common.value.FormulaValue;
import com.crystaldecisions.reports.common.value.FormulaValueType;
import com.crystaldecisions.reports.common.value.StringValue;
import com.crystaldecisions.reports.formulas.FormulaFunction;
import com.crystaldecisions.reports.formulas.FormulaFunctionArgumentDefinition;
import com.crystaldecisions.reports.formulas.FormulaFunctionCallException;
import com.crystaldecisions.reports.formulas.FormulaValueReference;
import com.crystaldecisions.reports.formulas.SimpleFormulaFunctionArgumentDefinition;
public abstract class CodeEAN13Base
implements FormulaFunction
{
FormulaFunctionArgumentDefinition[] myArguments = { SimpleFormulaFunctionArgumentDefinition.string };
protected CrystalResourcesFactory resCrystal;
public CodeEAN13Base()
{
this.resCrystal = new CrystalResourcesFactory("Messages");
}
protected final String doTranslation(String inputData,String opz)
// protected final String doTranslation(String inputData)
{
String returnVal = "";
// returnVal = returnVal + translateCharWrapper(inputData);
returnVal = returnVal + translateCharWrapper(inputData,opz);
return returnVal;
}
#Override
public final FormulaValue evaluate(FormulaValueReference[] arguments)
throws FormulaFunctionCallException
{
StringValue dataStringArg = (StringValue)arguments[0].getFormulaValue();
StringValue opzArg =(StringValue)arguments[1].getFormulaValue();
String dataString = dataStringArg.getString();
String opz=opzArg.getString();
String returnVal = doTranslation(dataString,opz);
return StringValue.fromString(returnVal);
}
#Override
public final FormulaFunctionArgumentDefinition[] getArguments()
{
return this.myArguments;
}
#Override
public final FormulaValueType getReturnType()
{
return FormulaValueType.string;
}
protected abstract String translate(String inputData,String opz)
throws InvalidBarcodeDataException;
//protected abstract String translate(String inputData)
//throws InvalidBarcodeDataException;
// private String translateCharWrapper(String inputData)
private String translateCharWrapper(String inputData,String opz)
{
String returnString;
try
{
// returnString = translate(inputData);
returnString = translate(inputData,opz);
} catch (InvalidBarcodeDataException e) {
returnString = "";
}
return returnString;
}
#Override
public void validateArgumentValues(FormulaValueReference[] arguments)
throws FormulaFunctionCallException
{}
}

Eclipse asking me to make this abstract?

I need to produce two separate jar files, both interact with each other but do different things. I have two projects loaded into Eclipse, but both use a lot of the same imports, and so I have them in subfolders under the same workspace.
One of them gets "java class xxxxcould not be found" when I try to run it.
As I attempted to fix that, I was comparing the two projects and noticed that a folder was part of the external build path of the working one, but not the non-working one. I added it to the non-working one and broke the working one.
The one that had been working now has an error on the main class name. I call the program ZSTATEngine, and so the class is
public class ZSTATEngine implements ETOSFilterEngine
Now that name is highlighted and when I mouse over it is says:"the type ZSTATEngine must implement the inherited abstract method ETOSFilterEngine.doFilter(MessageBlock)"
What could have changed? It was working fine before, and nothing in the code itself changed. I don't understand how the referenced libraries work, but it at least appears nothing changed in their structure in the formerly-working project.
Ok some further information: I do actually have a section within that class:
public MessageBlock doFilter(MessageBlock msgBlock)
so I am implementing that method... but that method has an error inside of it now,
"The method addFilteredMessage(MessageBlock) in the type FilterFramework is not applicable or the arguments (MessageBlock) ...
How could that have gone bad? It was working fine too.
Here's the full code:
package com.ibm.tpf.internal;
import java.awt.Color;
/*import java.util.ArrayList;*/
/*import java.util.*;*/
import com.ibm.tpf.etos.TPFFilter.*;
//import com.ibm.tpf.etos.TPFFilter.TernarySwitch;
import com.ibm.tpf.etos.api.*;
/*
import com.ibm.tpf.etos.api.Constants;
import com.ibm.tpf.etos.api.MessageBlock;
*/
import com.ibm.tpf.etos.filter.*;
/*
import com.ibm.tpf.etos.filter.ETOSFilterEngine;
import com.ibm.tpf.etos.filter.FilterConfigurationException;
import com.ibm.tpf.etos.filter.FilterFramework;
import com.ibm.tpf.etos.filter.FilterRuntimeException;
*/
public class ZSTATEngine implements ETOSFilterEngine {
FilterFramework fw = null;
String[] names = null;
public ZSTATEngine(FilterFramework filFW, String[] parms) {
super();
this.fw = filFW;
}
/* AAES0009I 13.45.01 FROM TA 05 : AUTC0000I TOSFCOLOR_GREEN TOSBCOLOR_NONE TOSHOLD_0 TOSSAVE_0 TOSALERT_0 AUTC1111I 12.04.41 OK */
public MessageBlock doFilter(MessageBlock msgBlock) throws FilterRuntimeException {
if(msgBlock.getMsgID().equals("AAES0009I")) { /* only handle messages that start with AAES0009I */
if(msgBlock.getMsg().indexOf("ZUVRT") != -1) { /* if the message contains "ZUVRT" then let it through. We want to react to the result of it, not the ZUVRT itself. */
return msgBlock;
}
if(msgBlock.getMsg().indexOf("AUTC0000I") != -1) { /* search string to see if "AUTC0000I is in it. If it is then do..." */
String myString = msgBlock.getMsg();
Color fColor = Color.WHITE; /* set default colors */
Color bColor = Color.BLACK;
msgBlock.setSuppressed(TernarySwitch.ON); /* suppress original message to display new one */
String[] myStringParts = myString.split("\\s+",13); /* divide message into 13 parts. The 13th part is everything remaining. */
String finalPart = myStringParts[12].toString(); /* print last part to the screen */
MessageBlock mb = new MessageBlock(finalPart, Constants.ETOS_ONE_MSG);
String fColorMsg = myStringParts[7].toString(); /* Process the foreground color portion */
if (!fColorMsg.contains("NONE")) {
fColor = ColorStringInterpreter(fColorMsg);
mb.setForeground(fColor);
}
String bColorMsg = myStringParts[8].toString(); /* Process the background color portion */
if (!bColorMsg.contains("NONE")) {
bColor = ColorStringInterpreter(bColorMsg);
mb.setBackground(bColor);
}
String holdMsg = myStringParts[9].toString(); /* Process the hold message portion */
if (holdMsg.toUpperCase().startsWith("TOS")) { /* if it starts with TOS, grab only the number at the end */
String[] holdPart = holdMsg.split("_",2);
if (holdPart[1].toString().equals("1")) {
mb.setHeld(TernarySwitch.ON);
}
}
else {
if (holdMsg.equals("1")) { /* otherwise, just use the number */
mb.setHeld(TernarySwitch.ON);
}
}
String saveMsg = myStringParts[10].toString(); /* Process the save areas. These have two formats currently: TOSSAVE_X_X_X_X and BBBBBBBBB, where X is a digit 1-32, and B is binary. */
if (saveMsg.toUpperCase().startsWith("TOS")) {
String[] savePart = saveMsg.split("_"); /* handle the multiple digit save areas, and ignore the first split which is TOSSAVE */
if (!savePart[1].toString().equals("0")) {
long areaBits = 0;
for (int i=1; i<savePart.length; i++) {
areaBits |= 1L << Integer.parseInt(savePart[i]);
}
mb.setSave(areaBits);
}
}
else { /* otherwise, just use the binary string directly */
long areaBits = Long.parseLong(myStringParts[10].toString(), 2);
mb.setSave(areaBits);
}
fw.addFilteredMessage(mb); /* this is the command that pieces the whole message together */
}
}
int plusLocation = msgBlock.getMsg().lastIndexOf('+');
if (plusLocation > 0) {
MessageBlock mb1 = new MessageBlock(msgBlock.getMsg(), msgBlock.getFlag());
fw.addFilteredMessage(mb1);
msgBlock.setSuppressed(TernarySwitch.ON);
MessageBlock mb2 = new MessageBlock("", Constants.ETOS_ONE_MSG);
fw.addFilteredMessage(mb2);
}
return msgBlock; /* whatever gets returned is what the system prints */
}
private Color ColorStringInterpreter(String colorMsg) throws FilterRuntimeException {
if (colorMsg.toUpperCase().startsWith("TOS")) { /* if it starts with TOS, then we're using color names */
String[] colorParts = colorMsg.split("_",2);
String colorTxt = colorParts[1].toString().trim();
if (colorTxt.toUpperCase() != "NONE") {
Color finalColor = Colors.fromString(colorTxt);
return finalColor;
}
}
else {
String[] colorParts = colorMsg.split("_",3); /* otherwise we're using RGB values */
String sRed = colorParts[0].toString().trim();
String sGreen = colorParts[1].toString().trim();
String sBlue = colorParts[2].toString().trim();
/*mb = new MessageBlock(sRed, Constants.ETOS_ONE_MSG);*/
int iRed = Integer.parseInt(sRed);
int iGreen = Integer.parseInt(sGreen);
int iBlue = Integer.parseInt(sBlue);
Color finalColor = new Color (iRed, iGreen, iBlue);
return finalColor;
}
return null;
}
public String getName() {
return null;
}
public void modifyState(Object[] newParams) throws FilterConfigurationException, FilterRuntimeException {
}
public boolean isActive() {
return false;
}
public void shutdown() {
}
}
public class ZSTATEngine implements ETOSFilterEngine
According to above code, your class ZSTATEngine is implementing an interface ETOSFilterEngine, which means your class need to implement all the abstract methods of ETOSFilterEngine.
From Java doc:
Interfaces form a contract between the class and the outside world,
and this contract is enforced at build time by the compiler. If your
class claims to implement an interface, all methods defined by that
interface must appear in its source code before the class will
successfully compile.
Check the link: http://www-01.ibm.com/support/knowledgecenter/SSB23S_1.1.0.9/com.ibm.tpfops.doc_1112/aaeo1/fengapi.html?cp=SSB23S_1.1.0.9%2F2-3-10-3
Below are the 5 methods that are present in ETOSFilterEngine, which you need to implement.
public MessageBlock doFilter (MessageBlock) throws
FilterRuntimeException;
public void modifyState (Object[ ]) throws
FilterConfigurationException,
FilterRuntimeException;
public boolean isActive();
public void shutdown();
public String getName();
Above link has a code example on how to properly implement this interface. You can see that the class ZSTATEngine in the example is implementing all the 5 methods provided by ETOSFilterEngine.
Check the type of MessageBlock in your imports, it should be import
com.ibm.tpf.etos.api.MessageBlock; I can see that you have commented your import which is wrong.
Uncomment the line : import com.ibm.tpf.etos.api.MessageBlock;
AS mentioned by "Jakub Zaverka" perhaps you have two versions in classpath or build path. Check the jar order, whether is picking the right class... It will happen even if no code has changed.
One way to find it out is, just do an F3 on ETOSFilterEngine and click "Link with editor" option in package explorer. It will show the .class file and the jar from which its picked up.. If its from the wrong jar or old jar, just go to Project>Properties>Build Path>Order and Export and change the order of the right jar to the top, by clicking on Top button..

A java class can't find an other in the same package

I am implementing a java program in ubuntu without an IDE that converts a currency to €, i have 2 classes ConvertiEuro and Valuta both in the same directory (package) called finanza, the class ConvertiEuro uses the class Valuta, when i try to compile Valuta.java it compiles correctly but when i compile ConvertiEuro.java I get an error saying "ConvertiEuro.java:3: error: cannot find symbol" I don't know why here is the code
package finanza;
public class Valuta {
private String nomeValuta;
private double totValuta;
public Valuta(String nomeVal, double totVal) {
nomeValuta = nomeVal;
totValuta = totVal;
}
public String getNomeValuta() {
return nomeValuta;
}
public double getTotValuta() {
return totValuta;
}
}
package finanza;
import finanza.Valuta;
public class ConvertiEuro {
private int valuteGestibili;
private int cont = 0;
private Valuta [] valutas;
public ConvertiEuro(int valuteGest) {
this.valuteGestibili = valuteGest;
this.valutas = new Valuta [this.valuteGestibili];
}
public boolean impostaValuta(Valuta val){
if(cont<valuteGestibili) {
this.valutas[cont] = val;
cont ++;
return true;
}
else {
return false;
}
}
}
and this how I compile: javac ConvertiEuro.java
I strongly suspect the problem is in how you're compiling.
Both ConvertiEuro.java and Valuta.java should be in a directory called finanza, and you should ideally compile from the parent directory, so that all the compiler knows where to find other code in the same package. It would expect to find a source file in a finanza directory under the one you're currently in, for a package called finanza.
It's simplest just to compile all the files at the same time though:
javac finanza/*.java
... or better yet, use an IDE which will manage this sort of things for you.

Tricky ClassCastException in using the Plastic framework for code generation

What's it all about
Hi everyone - I was looking at a presentation called "Have your cake and eat it too: Meta-programming in Java"
The presenter was Howard M. Lewis Ship, (one?) of the authors of Tapestry - and in making that, a subproject called "plastic" was made to leverage ASM to alter the bytecode.
I won't pretend to be an expert, but the end-result should be that I can write code such that annotated classes, methods and fields can be used to generate further java code thus cutting down on boilerplate code.
My Question
The code below is a complete example to demonstrate my problem. The test example should modify the EqualsDemo class such that it contains implementations of equals() and hashCode().
When running it I get an error which basically states that I can't cast an object of type 'com.example.plastic.transformed.EqualsDemo' to 'com.example.plastic.transformed.EqualsDemo' (yes, the same class).
The presenter just mentioned that these errors were annoying without alluding to where they stem from - my searching so far indicates that they pertain to different class loaders.
I have, however, been completely unable to fix the problem, hence my question here(!)
com.example.plastic.transformed.EqualsDemo cannot be cast to com.example.plastic.transformed.EqualsDemo
at MainClass.main(MainClass.java:28)
So what do I need to do ? Replace class loaders ? (if so, how?) or is there some part of Plastic I don't get ? Some method for generating proxy objects or similar that I need to use for things to go smoothly ?
PS!
The examples I've found so far all use what I think is Groovy in the final use of the annotated instances.
Hopefully someone are more competent than I :)
Links:
Tapestry Homepage (plastic is contained as a jar in the download): http://tapestry.apache.org/
Main.java
import java.util.ArrayList;
import java.util.List;
import org.apache.tapestry5.internal.plastic.StandardDelegate;
import org.apache.tapestry5.plastic.ClassInstantiator;
import org.apache.tapestry5.plastic.PlasticManager;
import com.example.plastic.transformer.EqualsHashCodeTransformer;
import com.example.plastic.transformed.EqualsDemo;
public class MainClass {
public static void main(String[] args) {
List<String> pList = new ArrayList<String>();
pList.add("com.example.plastic.transformed");
PlasticManager pm = PlasticManager
.withContextClassLoader()
.delegate( new StandardDelegate(new EqualsHashCodeTransformer()) )
.packages(pList)
.create();
final String EQUALSDEMO = "com.example.plastic.transformed.EqualsDemo";
ClassInstantiator<EqualsDemo> i = pm.getClassInstantiator(EQUALSDEMO);
i.newInstance().hashCode();
/*
com.example.plastic.transformed.EqualsDemo cannot be cast to com.example.plastic.transformed.EqualsDemo
at MainClass.main(MainClass.java:28)
*/
}
}
ImplementEqualsHashCode.java
package com.example.plastic.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface ImplementEqualsHashCode {
}
EqualsHashCodeTransformer.java
package com.example.plastic.transformer;
import java.util.ArrayList;
import java.util.List;
import org.apache.tapestry5.plastic.FieldHandle;
import org.apache.tapestry5.plastic.MethodAdvice;
import org.apache.tapestry5.plastic.MethodDescription;
import org.apache.tapestry5.plastic.MethodInvocation;
import org.apache.tapestry5.plastic.PlasticClass;
import org.apache.tapestry5.plastic.PlasticClassTransformer;
import org.apache.tapestry5.plastic.PlasticField;
import com.example.plastic.annotations.*;
public class EqualsHashCodeTransformer implements PlasticClassTransformer {
private MethodDescription EQUALS = new MethodDescription("boolean", "equals", "java.lang.Object");
private MethodDescription HASHCODE = new MethodDescription("int", "hashCode");
private static final int PRIME = 37;
public void transform(PlasticClass plasticClass){
//check that the class is annotated
if(!plasticClass.hasAnnotation(ImplementEqualsHashCode.class)) {
return;
}
List<PlasticField> fields = plasticClass.getAllFields();
final List<FieldHandle> handles = new ArrayList<FieldHandle>();
for(PlasticField field : fields){
handles.add(field.getHandle());
}
//HashCode method introduction :)
plasticClass.introduceMethod(HASHCODE).addAdvice(new MethodAdvice() {
public void advise(MethodInvocation invocation){
Object instance = invocation.getInstance();
int result = 1;
for(FieldHandle handle : handles){
Object fieldValue = handle.get(instance);
if(fieldValue != null)
result = (result * PRIME) + fieldValue.hashCode();
}
invocation.setReturnValue(result);
//Don't proceed to the empty introduced method
}
});
plasticClass.introduceMethod(EQUALS).addAdvice(new MethodAdvice() {
public void advise(MethodInvocation invocation) {
Object thisInstance = invocation.getInstance();
Object otherInstance = invocation.getParameter(0);
invocation.setReturnValue(isEqual(thisInstance, otherInstance));
//Don't proceed to the empty introduced method
}
private boolean isEqual(Object thisInstance, Object otherInstance) {
if(thisInstance == otherInstance)
return true;
if(otherInstance == null)
return false;
if(!(thisInstance.getClass() == otherInstance.getClass()))
return false;
for(FieldHandle handle : handles){
Object thisValue = handle.get(thisInstance);
Object otherValue = handle.get(otherInstance);
if(!(thisValue == otherValue || thisValue.equals(otherValue)))
return false;
}
return true;
}
});
}
}
EqualsDemo.java
package com.example.plastic.transformed;
import com.example.plastic.annotations.ImplementEqualsHashCode;
#ImplementEqualsHashCode
public class EqualsDemo {
private int intValue;
private String stringValue;
public int getIntValue(){
return intValue;
}
public void setIntValue(int intValue){
this.intValue = intValue;
}
public String getStringValue(){
return stringValue;
}
public void setStringValue(String stringValue){
this.stringValue = stringValue;
}
}
you don't want to add the packages to the plastic manager -- it uses a different classloader and will load those classes, making two copies of the classes in those packages (one in the parent classloader and one in the plastic classloader) which will give you the ClassCastException you are seeing when the framework tries to cast to your class. Try this instead:
import org.apache.tapestry5.internal.plastic.StandardDelegate;
import org.apache.tapestry5.plastic.ClassInstantiator;
import org.apache.tapestry5.plastic.PlasticManager;
public class MainClass {
public static void main(String[] args) {
PlasticManager pm = PlasticManager
.withContextClassLoader()
.delegate(new StandardDelegate())
.create();
ClassInstantiator<EqualsDemo> ci = pm.createClass(EqualsDemo.class, new EqualsHashCodeTransformer());
System.out.println(ci.newInstance().hashCode());
}
}
I guess instead of
PlasticManager.withContextClassLoader()...
using the following should fix your problem:
PlasticManager.withClassLoader(getClass().getClassLoader())...

JUnit testing a class on Netbeans

Could someone create a JUnit test in NetBeans for the code that I have pasted below? I'm not quite sure what to do once I've created the actual test.
package prog3;
import java.util.ArrayList; import java.util.Iterator;
public class MedicineClass
{
private String MedicineName;
private int MedicineRegNum;
private ArrayList RelatedMedicine;
public MedicineClass(String newMedicineName, int newMedicineRegNum)
{
newMedicineName = MedicineName;
newMedicineRegNum = MedicineRegNum;
RelatedMedicine = new ArrayList();
}
public void setMedicine(String newMedicineName)
{
newMedicineName = MedicineName;
}
public String getMedicineNameAndNum()
{
return "Medicine Registration Number: " + MedicineRegNum + "Medicine Name: " + MedicineName;
}
public void Medicine(Medicine Drug)
{
RelatedMedicine.add(Drug);
}
public void addMedicine(String newMedicineName, int newMedicineRegNum)
{
Medicine temp = new Medicine(newMedicineName, newMedicineRegNum);
RelatedMedicine.add(temp);
}
public void listAllMedicines()
{
StringBuilder sb = new StringBuilder();
Iterator lst = RelatedMedicine.iterator();
while (lst.hasNext())
{
Medicine temp = (Medicine)lst.next();
sb.append(temp.getNameandRegNum());
sb.append("\n");
}
System.out.println(sb.toString());
}
}
You have the class that you need to write JUnit tests for. Read this: Writing JUnit Tests in NetBeans IDE and Introduction to Unit Testing
I suggest using the "create JUnit test" button in the IDE. This will place the class in the right place for you. You can then copy'n'paste your code into that test. If that button is not visible on your toolbar, right-click on your toolbar and add that button from the customise menu. I also recommend adding the "test this class" button.
There are numerous APIs that claim to automate this process. Perhaps one of them would be helpful for you:
http://sourceforge.net/projects/amaticjunittool/
http://sourceforge.net/projects/junitgenerator/
http://sourceforge.net/projects/junittestmaker/
http://sourceforge.net/projects/spike-test-gen/

Categories

Resources