jMeter not applying variable to header manager - json

I'm using Apache JMeter 3.2 r1790748 on Mac.
I have a setUp Thread Group making an authentication call. The call works and outputs the tokens correctly. Now I need to pass that token to the HTTP Header Manager for all the calls I'm making.
First of all, here's my token json output:
{
"access_token": "aaaaaa555555555",
"token_type": "Access",
"user_id": "5555"
}
Here's what my HTTP Header manager looks like:
1 value: Authorization : Bearer ${access_token}
My network call:
GET https://my_server.com/some_path
GET data:
[no cookies]
Request Headers:
Connection: close
Authorization: Bearer ${access_token}
Host: my_server.com
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_91)
As you can see, the variable access_token is not being replaced with the value from the setup call.
What I've tried:
BeanShell PostProcessor:
I created this script, and it actually parses and outputs the access_token properly:
import org.apache.jmeter.protocol.http.control.Header;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
String jsonString = prev.getResponseDataAsString();
log.info("jsonString = " + jsonString);
JSONParser parser = new JSONParser(JSONParser.MODE_JSON_SIMPLE);
JSONObject json = (JSONObject) parser.parse(jsonString);
String access_token = json.getAsString("access_token");
log.info("access_token = " + access_token);
vars.put("access_token", access_token);
JSON Extractor:
Apply to: Main sample and sub-samples
Variable names: access_token
JSON Path expressions: access_token
Match No. (0 for Random): 1
Compute concatenation var (suffix _ALL): unchecked
Default Values: none
Any ideas as to why the header manager is not applying the value of the access_token result?
Thanks!

Since you set a variable in setUp Thread Group, you cannot use it in another thread groups, since thread groups don't share variables, only properties.
So in order to pass authentication, you need to save it as a property:
${__setProperty(access_token, ${access_token})};
In this example I am using value of variable named access_token (already set, but only available in setUp thread group) to set property with the same name, which will be available across thread groups. Or change BeanShell post-processor, add:
props.put("access_token", access_token);
And then in the other thread group, you retrieve it using __P or __property function:
${__P(access_token)}
Also keep in mind that HTTP Header Manager initializes before any thread starts, so you can't use variables there for that reason too. Check this question for instance.
If you still see empty value, I recommend adding Debug Sampler (with both JMeter Properties and JMeter Variables enabled) in both thread groups, and checking where the breakage is (on saving or retrieving).

As per Functions and Variables chapter of the JMeter User Manual
Variables are local to a thread; properties are common to all threads, and need to be referenced using the __P or __property function
So the variable you define in the setUp Thread Group cannot be accessed by:
other threads in the same Thread Group
other threads outside the Thread Group
So my recommendations are:
Switch to JMeter Properties instead of Jmeter Variables, JMeter Properties are global to all threads and in fact the whole JVM instance
Switch to JSR223 PostProcessor with Groovy language instead of Beanshell PostProcessor, JSR223 Elements performance is much better, moreover Groovy has built-in JSON support.
So:
The relevant Groovy code for getting access_token attribute value and storing it into the relevant property would be :
props.put('access_token', new groovy.json.JsonSlurper().parse(prev.getResponseData()).access_token)
You can refer the value in the HTTP Header Manager (or wherever you require) as:
${__P(access_token,)}

Related

JMeter reads the old version of csv

I am trying to test some APIs but first I need to get session keys for each customer I use in the test. I have a CSV file with customer login information and read it with each thread.
I have the following form in my JMeter file.
CSV Data Set Config - User Login Info
Set username, password - one for each iteration
Setup Thread Group
BeanShell Sampler to delete the sessionKeys.csv
File file = new File("C:/user/sessionKeys.csv");
if (file.exists() && file.isFile()) {
file.delete();
}
Login Thread - ThreadCount = threadCount, Loop = 1
Login Request
BeanShell PostPrecessor to create file and append Session Keys to sessionKeys.csv
if("${sessionKey}" != "not_found")
{
File file = new File("C:/user/sessionKeys.csv");
FileWriter fWriter = new FileWriter(file, true);
BufferedWriter buff = new BufferedWriter(fWriter);
buff.write("${sessionKey}\n");
buff.close();
fWriter.close();
}
CSV Data Set Config - Session Keys
API Call Thread - ThreadCount = threadCount, Loop = loop
GetData Request
And I noticed that even if the file is actually deleted, created and filled with new sessionKeys, first a few requests uses the old sessionKeys in the file before it was deleted.
I have tried adding constant timer or changing the structure of the JMeter file but nothing worked.
Take a look at JMeter Test Elements Execution Order
Configuration elements
Pre-Processors
Timers
Sampler
Post-Processors (unless SampleResult is null)
Assertions (unless SampleResult is null)
Listeners (unless SampleResult is null)
CSV Data Set Config is a Configuration Element hence it's executed long before the Beanshell Sampler and this perfectly explains the behaviour you're facing.
So if you need to do some pre-processing of the CSV file you will need to do it in setUp Thread Group
Also be aware that starting from JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting so it makes sense considering migrating.
It looks like the CSV Config element in your test plan exists outside of the thread group and so will be called first before the file is deleted and recreated.
In your case it might be simpler to just store the session key as a JMeter property so that it can be accessed in all thread groups. You can store it using Groovy like props.put("${sessionKey}", sessionKey) or via JMeter functions like ${__setProperty("sessionKey",${sessionKey})}.
The property can then be accessed again using the property function like ${__P(sessionKey,)}.

Haproxy frontend configuration to replace response header depending on query string

I used the following haproxy configuration in frontend to modify the response header of requests depending on a query string:
frontend my-frontend
acl is-foo urlp(foo) 1
http-response replace-header Set-Cookie "(.*)" "\1; SameSite=None" if is-foo
Depending on my information from the docs the acl should match for all requests like
example.com?a=b&foo=1&bar=2
example.com?foo=1
example.com?a=b&foo=1
And it should not match for requests like
example.com?a=b&foo=0&bar=2
example.com?a=b
example.com?a=b&foo=bar
The actual result is that the acl matches never.
If i invert the if i.e.: if !is-foo the replace-header happens on every request.
So the problem must be the acl which matches never.
I use haproxy 2.0.15
I got it working by myself.
It seems to be the case that urlp(foo) is not present at runtime when it has been executed for http-response.
So we need to store its value in a temporary variable using set-var(custom.name), before. At runtime in if condition we can access it with var(custom.name) and match it against our condition. I used urlp_val() instead of urlp() here because the value will be casted to int immediately.
frontend my-frontend
http-request set-var(txn.foo) urlp_val(foo)
http-response replace-header Set-Cookie "(.*)" "\1; SameSite=None" if { var(txn.foo) eq 1 }
Thank you for traveling.

AWS SDK in java - How to get activities from worker when multple execution on going for a state machine

AWS Step Function
My problem is to how to sendTaskSuccess or sendTaskFailuer to Activity which are running under the state machine in AWS .
My Actual intent is to Notify the specific activities which belongs to particular State machine execution.
I successfully send notification to all waiting activities by activityARN. But my actual need is to send notification to specific activity which belong to particular state machine execution .
Example . StateMachine - SM1
There two execution on going for SM1-- SM1E1, SM1E2 . In that case I want to sendTaskSuccess to activity which belongs to SM1E1 .
follwoing code i used . But it send notification to all activities
GetActivityTaskResult getActivityTaskResult = client.getActivityTask(new GetActivityTaskRequest()
.withActivityArn("arn detail"));
if (getActivityTaskResult.getTaskToken() != null) {
try {
JsonNode json = Jackson.jsonNodeOf(getActivityTaskResult.getInput());
String outputResult = patientRegistrationActivity.setStatus(json.get("patientId").textValue());
System.out.println("outputResult " + outputResult);
SendTaskSuccessRequest sendTaskRequest = new SendTaskSuccessRequest().withOutput(outputResult)
.withTaskToken(getActivityTaskResult.getTaskToken());
client.sendTaskSuccess(sendTaskRequest);
} catch (Exception e) {
client.sendTaskFailure(
new SendTaskFailureRequest().withTaskToken(getActivityTaskResult.getTaskToken()));
}
As far as I know you have no control over which task token is returned. You may get one for SM1E1 or SM1E2 and you cannot tell by looking at the task token. GetActivityTask returns "input" so based on that you may be able to tell which execution you are dealing with but if you get a token you are not interested in, I don't think there's a way to put it back so you won't be able to get it again with GetActivityTask later. I guess you could store it in a database somewhere for use later.
One idea you can try is to use the new callback integration pattern. You can specify the Payload parameter in the state definition to include the task token like this token.$: "$$.Task.Token" and then use GetExecutionHistory to find the TaskScheduled state of the execution you are interested in and retrieve the parameters.Payload.token value and then use that with sendTaskSuccess.
Here's a snippet of my serverless.yml file that describes the state
WaitForUserInput: #Wait for the user to do something
Type: Task
Resource: arn:aws:states:::lambda:invoke.waitForTaskToken
Parameters:
FunctionName:
Fn::GetAtt: [WaitForUserInputLambdaFunction, Arn]
Payload:
token.$: "$$.Task.Token"
executionArn.$: "$$.Execution.Id"
Next: DoSomethingElse
I did a POC to check and below is the solution .
if token is consumed by getActivityTaskResult.getTaskToken() and if your conditions not satisfied by request input then you can use below line to avoid token consumption .awsStepFunctionClient.sendTaskHeartbeat(new SendTaskHeartbeatRequest().withTaskToken(taskToken))

jmeter to issue http request based on response

I'm using Jmeter for my API testing using various http requests and various samplers to validate them. Now, I'm writing test for another http request. In this test,the steps are:
Issue a http request. Handle response.
using xpath xtractor, I'm extracting the response and storing URL in another variable(store_url).
If variable has a URL, repeat step-1.
This loops has to be repeated until no value is stored in (store_URL).
There is not definite number, how many time the loop has to be repeated. It is based on store_url is empty or not.
How can I achieve this in jmeter? I know step-1 and step-2. But I'm looking how to repeat step-1 and step-2. Please help me.
set a jmeter variable loopCount to 1 for init value,
move your step 1 and 2 into a loop controller,
set to loop count to ${loopCount}
in your step 2,
increase loopCount if store_url is found after you finish xpath xtractor
Put your points 1 and 2 under While Controller
Use ${__javaScript(vars.get("store_URL") != null)} as While Controller's Condition
In condition __javaScript() function is used to check store_URL variable value.
if store_URL variable is set (has any value) - everything under the While Controller will start over
if store_URL variable becomes null - the look will break
vars - is a shorthand to JMeterVariables class instance, it provides read/write access to all JMeter Variables
See Using JMeter Functions article for more detailed information on __javaScript and other useful functions

AS3 FLEX SOAP WSLD Argument error

I'm having a problem sending multiple arguments through to a web service, using the Flex RPC Soap libraries.
Code:
var assetOperation:AbstractOperation = new AbstractOperation();
assetOperation = fws.getOperation("registerBarcodeByString");
assetOperation.arguments = [AppID, BarCode];
var assetToken:AsyncToken = new AsyncToken();
assetToken = assetOperation.send();
trace(assetToken.message);
assetToken.addResponder(new Responder(getBarcodeResult, getBarcodeError));
Looking at the logs on the web service, both the AppID and BarCode are being received as the first argument placed in the array. No matter what goes first, that item will be passed as every argument.
Imagine I'm sending [1234, 6789], the web service is receiving [1234, 1234].
I've tried placing the args in the send() method, same thing happens. I've tried creating a temporary object which stores these args and sending that, same thing.
Any ideas?
Thank you.
When passing the args, I had to pass through more information, in this case the exact name of each argument as expected by the web service.
So:
assetOperation.arguments = [{applicationLabel:AppID, barcodeString:BarCode}];