How to return a value from database in jmeter - jmeter

I am trying to return a value from MSSQL server database and storing it in a variable inside JSR223 timer script in Jmeter. However I am getting the following error in log -
**WARN o.a.j.t.JSR223Timer: Script did not return a value
**
This is the code which i have written in the script -
try {
def promoName = ${promotionName}; //extracted the value using JSONExtractor
log.info("Promotion Name is " + promoName); //not displaying in the log
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection con = DriverManager.getConnection("jdbc:sqlserver://ServerIP;databaseName="";integratedSecurity=true","<userId>","<password>");
String query ="select query";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
vars.put("promotionInstanceId", rs.getString(1)); //The query returns an instanceId which i need to store in a variable and use it later
log.info("Promotion Instance is " + ${promotionInstanceId});
}
conn.close();
}
catch (Exception e) {
e.printStackTrace();
Can anyone help me in understanding where i might have gone wrong ?

Any reason to use the timer? The warning you're getting is about missing return keyword as the JSR223 Timer is intended to be used for calculation of virtual user think time therefore it should return the value to "sleep" in milliseconds. Given you don't want to introduce the think time it makes sense to go for JSR223 PostProcessor instead.
Don't inline JMeter functions or variables into the scripts as it might cause script misbehavior due to clashing with GString template or the variable will be cached and the same value will be returned for the subsequent calls.
It is recommended to use JMeter's built-in components and avoid scripting where possible, you can use i.e. JDBC PostProcessor in order to extract the interesting value(s) and store it(them) into JMeter Variables. Check out Debugging JDBC Sampler Results in JMeter article to learn how to execute SQL statements and work with results

You should use vars.get to get variable value
vars.put("promotionInstanceId", rs.getString(1)); //The query returns an instanceId which i need to store in a variable and use it later
log.info("Promotion Instance is " + vars.get("promotionInstanceId"));

Related

how to concatenate all the values of a variable in Jmeter

I am storing output of JDBC request in Jmeter Variable - "temp_num".
Now I need to concatenate all the values stored in this variable in form of 'a','b','c'......'n'. I did try aggregation withing SLQ script too, but there we have a limit on string length, that's why I would like to probably use something like string builder, but not sure how to use it.
You can convert JDBC result set into a string using JSR223 PostProcessor and the code like :
temp_num = vars.getObject("temp_num");
result = new StringBuilder();
for (Object row : temp_num) {
iter = row.entrySet().iterator();
while (iter.hasNext()) {
pair = iter.next();
result.append(pair.getValue());
result.append(",");
}
}
vars.put('result', result.toString())
However be aware that there is a limit of the number of characters in Java String so make sure not to exceed it.
More information: Debugging JDBC Sampler Results in JMeter

${__time} function output is incorrect

I'm trying to get today's date using time function of jmeter with the format "${__time(yyyy-MM-dd)}" in BeanShell postprocessor. But after executing the Beanshell postprocessor the result shows as "1996". Basically the "time" function is displaying result by subtracting the values like "2018-03-19"=1996.
Please help me to resolve this issue so that i can get current date and time.
Beanshell code as below
import org.apache.jmeter.gui.GuiPackage;
import org.apache.commons.io.FilenameUtils;
String testPlanFile = GuiPackage.getInstance().getTestPlanFile();
String testPlanFileDir = FilenameUtils.getFullPathNoEndSeparator(testPlanFile);
vars.put("testPlanFileDir", testPlanFileDir);
//create the file in test plan file dir and print current time and Date
FileOutputStream f = new FileOutputStream(testPlanFileDir+"/CurrentDate.txt", true);
PrintStream p = new PrintStream(f);
this.interpreter.setOut(p);
//current date and time;
print("Current date is:"+${__time(yyyy-MM-dd)});
f.close();
Set time function call as parameter of your PreProcessor (by the way migrate to JSR223 + Groovy for performances)
And use it then with variable Parameters:
Try this with JSR223 PostProcessor and language Groovy and put this into script area:
def a = new Date().format('yyyy-MM-dd')
new File('Example.txt').withWriter('utf-8') {
writer -> writer.writeLine 'Current date is : ' + a.toString() }
(It works on JMeter 4.0)
You should move to JSR223 postprocessor according to JMeter Best Practices:
Since JMeter 3.1, we advise switching from BeanShell to JSR223 Test Elements
Until then you can fix it by quoting the function call as
print("Current date is:"+"${__time(yyyy-MM-dd)})";
This fix will treat the function's return value as string.
Currenty it treat it as a numeric substraction: 2018-3-19=1996 and then convert it to string
Performance anti-pattern #1: given you use GuiPackage class you won't be able to execute your test in non-GUI mode, consider migrating to FileServer instead
Performance anti-pattern #2: using Beanshell is not recommended as in case of high loads it might become the bottleneck. Since JMeter 3.1 it is recommended to use JSR223 Test Elements and Groovy language for any form of scripting
Performance anti-pattern #3: don't inline JMeter Variables or Functions in script body they break Groovy compiled scripts caching function and might resolve into something which will cause unexpected behaviour (like in your case), compilation failure or even data loss.
So:
Add JSR223 PostProcessor instead of the Beanshell one
Put the following code into "Script" area:
String testPlanDir = org.apache.jmeter.services.FileServer.getFileServer().getBaseDir()
File currentDate = new File(testPlanDir + File.separator + "CurrentDate.txt")
currentDate << new Date().format("yyyy-MM-dd")

JMeter BeanShell Assertion: Getting error when convert String to Long

Have a need to change the value from String to Long in BeanShell Assertion to do verification.
First Apporach
long balance_after_credit = Long.parseLong(String.valueOf("${balance_after_credit_from_db}"));
Second Approach
long balance_after_credit = Long.parseLong(vars.get("balance_after_credit_from_db"));
For instance, consider am getting a value as '743432545' for the variable balance_after_credit_from_db.
Error
org.apache.jorphan.util.JMeterException: Error invoking bsh method: eval Sourced file: inline evaluation of: ``long token_balance_after_credit = Long.parseLong(vars.get("token_balance_after_c . . . '' : Typed variable declaration : Method Invocation Long.parseLong
Weird thing is sometimes, I didn't get errors and the script is getting passed.
Can anyone please point out where am doing a mistake. TIA.
Inlining JMeter variables into code-based scripts is not something recommended so go for 2nd approach.
How do you know that exactly String is being returned from the database all the time? It easily can be any other object type, in fact any of described in the Mapping SQL and Java Types article. The way more safe approach will be something like:
if (vars.getObject("balance_after_credit_from_db") instanceof String) {
long balance_after_credit = Long.parseLong(vars.get("balance_after_credit_from_db"));
}
else {
log.error("Unexpected \balance_after_credit_from_db\" variable type");
log.error("Expected: String, Actual: " + vars.getObject("balance_after_credit_from_db").getClass().getName());
throw new Exception("Unexpected variable type");
}
So in case of non-String JDBC query result you will be able to see the relevant message in jmeter.log file
See Debugging JDBC Sampler Results in JMeter article for more information on working with the entities coming from databases in JMeter tests
The second option
long balance_after_credit = Long.parseLong(vars.get("balance_after_credit_from_db"));
should work, provided you have a valid numeric variable value. For instance try to run something like this:
vars.put("x", "743432545");
long balance_after_credit = Long.parseLong(vars.get("x"));
It won't return any exception.
The problem is when the variable is not defined, has empty or non-numeric value. Then Long.parseLong will throw a NumberFormatException, which you shold catch and make use of (treat it as assertion failure):
String rawValue = vars.get("balance_after_credit_from_db");
long balance_after_credit = Long.MAX_VALUE; // initialize with some unrealistic value
try {
balance_after_credit = Long.parseLong(rawValue);
}
catch(NumberFormatException e) {
Failure = true;
FailureMessage = "Variable does not contain a valid long. It was " + rawValue + " instead";
}

Capture time difference between values of two regular expression reference names in Jmeter

I defined regular expressions in my JMeter test plan and I'm able to capture the values in simple variables in user.variables. But I'm trying to calculate the time difference between two variables as follows in Beanshell post processor and I'm not getting any result in my report.
import javax.xml.bind.DatatypeConverter;
vars.put("old_date_submitted", "submittedDate"); // submittedDate, succeeddedDate and runningDates are regular expr. reference names
vars.put("old_date_succeeded", "succeededDate");
vars.put("old_date_running", "runningDate");
Calendar cal_s = DatatypeConverter.parseDateTime(vars.get("old_date_submitted"));
Calendar cal_c = DatatypeConverter.parseDateTime(vars.get("old_date_succeeded"));
Calendar cal_r = DatatypeConverter.parseDateTime(vars.get("old_date_running"));
Date new_date1 = cal_s.getTime(); // submitted Time
Date new_date2 = cal_c.getTime(); // succeeded Time
Date new_date3 = cal_r.getTime(); // running Time
long new_date1_ms = new_date1.getTime(); // submitted Time
long new_date2_ms = new_date2.getTime();
long new_date3_ms = new_date3.getTime();
log.info("Date in milliseconds: " + new_date1_ms);
long delta1 = new_date2_ms - new_date1_ms; //calculate the difference (succeededDate - submittedDate)
long delta2 = new_date3_ms - new_date1_ms; //calculate the difference (runningDate - submittedDate)
vars.put("delta1", String.valueOf("delta1")); // store the result into a JMeter Variable
vars.put("delta2", String.valueOf("delta2")); // store the result into a JMeter Variable
This bit:
vars.put("old_date_submitted", "submittedDate"); // submittedDate, succeeddedDate and runningDates are regular expr. reference names
vars.put("old_date_succeeded", "succeededDate");
vars.put("old_date_running", "runningDate");
seems odd to me. Given:
submittedDate, succeeddedDate and runningDates are regular expr. reference names
My expectation is that you should be using JMeter Variables instead of hardcoded strings there, so you should change your code to look like:
vars.put("old_date_submitted", vars.get("submittedDate")); // submittedDate, succeeddedDate and runningDates are regular expr. reference names
vars.put("old_date_succeeded", vars.get("succeededDate"));
vars.put("old_date_running", vars.get("runningDate"));
So most likely your code is failing at DatatypeConverter.parseDateTime.
Next time you face any problem with your Beanshell scripts consider the following troubleshooting techniques:
Check jmeter.log file - in case of Beanshell script failure the error will be printed there
Add debug(); directive to the very beginning of your Beanshell script - it will trigger debugging output to stdout
Put your Beanshell code in try/catch block like:
try {
//your code here
}
catch (Throwable ex) {
log.error("Something went wrong", ex);
throw ex;
}
This way you get more "human-friendly" stacktrace printed to jmeter.log file.
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on using Beanshell in JMeter tests.

How to use "Result Variable Name" in JDBC Request object of Jmeter

In JMeter I added the configuration for oracle server. Then I added a JDBC request object and put the ResultSet variable name to status.
The test executes fine and result is displayed in treeview listener.
I want to use the variable status and compare it with string but jmeter is throwing error about casting arraylist to string.
How to retrieve this variable and compare with string in While Controller?
Just used some time to figure this out and think the accepted answer is slightly incorrect as the JDBC request sampler has two types of result variables.
The ones you specify in the Variable names box map to individual columns returned by your query and these you can access by saying columnVariable_{index}.
The one you specify in the Result variable name contains the entire result set and in practice this is a list of maps to values. The above syntax will obviously not work in this case.
The ResultSet variable returned with JDBC request in JMeter are in the for of array. So if you want to use variable status, you will have to use it with index. If you want to use the first(or only) record user status_1. So you need to use it like status_{index}.
String host = vars.getObject("status").get(0).get("option_value");
print(host);
log.info("----- " + host);
Form complete infromation read the "yellow box" in this link:
http://jmeter.apache.org/usermanual/component_reference.html#JDBC_Request
Other util example:
http://jmeter.apache.org/usermanual/build-db-test-plan.html
You can use Beanshell/Groovy (same code works) in JSR233 PostProcessor to work with “Result Variable Name” from JDBC Request like this:
ArrayList results = vars.getObject("status");
for (HashMap row: results){
Iterator it = row.entrySet().iterator();
while (it.hasNext()){
Map.Entry pair = (Map.Entry)it.next();
log.info(pair.getKey() + "=" + pair.getValue());
}
}
Instead of output to log replace with adding to string with delimiters of your choice.

Resources