Unable to call object from a List located in external BeanShell script [Jmeter] - list

My end goal here is to get a string from a list that is created dynamically from a JSON response. I am having troubles calling a value from the list that is created in an external BeanShell script. The external script reads the JSON response and creates the list from the filtered response.
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Filter;
try{
String json = new String(prev.getResponseDataAsString());
List allPositiveAffects = JsonPath.read(json, "$.affectTags[?(#.value > 0.0)].key", new Filter[]{});
vars.putObject("allPositiveAffects",allPositiveAffects);
log.info("allPositiveAffects: " + allPositiveAffects);
int positiveAffectCount = allPositiveAffects.size();
vars.put("positiveAffectCount",Integer.toString(positiveAffectCount));
} catch (Throwable ex){
log.error("Error:\n", ex);
}
allPositiveAffects returns the expected values, so now I want to get one of those values into a subsequent JSON POST.
My Jmeter test setup:
- Thread Group
+ JSON GET request
- BeanShell PostProcessor
+ JSON POST request
Attempting to get a value from allPositiveAffects has proven to be not as easy as calling allPositiveAffects.get(n) like I can within my BeanShell script.
I haven't figured out an easy way to get the contents of the Lists. Am I missing something? I have tried several different things in my JSON POST request. The latest being:
//json POST data
{
"entries":[
"id": -1,
"key": "${__BeanShell(${allPositiveAffects}.get(1))}"]
}
Which returns the following error:
java.lang.ClassCastException: net.minidev.json.JSONArray cannot be cast to java.lang.String
Any help on a solution or workaround for this would be greatly appreciated. It would be a lot easier for me to be able to call a List instead of creating various variables.

I believe that you could just add .toString() to your expression like:
`${__BeanShell(${allPositiveAffects}.get(1).toString())}`
By the way, Beanshell has some performance overhead so I would rather suggest going for JSON Path Extractor which is available via Extras with Libs Set of JMeter Plugins package, it should be more convenient and less resource consuming.
See Using the XPath Extractor in JMeter (scroll down to "Parsing JSON") for installation instructions and some JSON Path language reference examples.

Related

How to HTTP request a file using regular expressions

I need to make a request for a CSS file.
I know which folder on the server my file will be in.
What I don't know is the exact file name. It will be titled of the form theme.bundle.xxxxxxxxxxxxxx.css where xxxxxxxxxxxxxx is a series of random characters and numbers generated at build time.
My question is, is it possible to make an HTTP request with a regex to get the name of the matching file(s)? I don't need help constructing the regex itself, but rather how to utilize one in combination with an HTTP request.
I can't find any information related to the usage of regular expressions to construct an HTTP request, or if this is even possible.
Short answer: Not possible, unless you have access to customize your server. You tagged this question as an "angular" question. From an Angular standpoint - Angular can't make this happen.
Longer answer: Totally possible! But this ends up being more of a backend question, not an Angular question. You didn't specify which backend you have, so I'll use a Node/Express server as an example. Part of building a server is setting up routing and API endpoints. Consider this code that responds with a particular file whenever the server receives a GET request to /images/background
app.get('/images/background', function(req, res) {
res.sendFile('public/img/background.png')
})
For your situation, you would need to set up an endpoint with similar logic to this:
app.get('/getMyCssFile', function(req, res) {
// Use NodeJS fs module to loop over files in /testfolder and read the file names
let matchingFile;
fs.readdirSync(testFolder).forEach(file => {
console.log(file);
// Perform REGEX matching here, if filename matches, then save this file name
if (matches) {
matchingFile = file;
}
})
if (matchingFile) {
res.sendFile(file)
} else {
// handle sending error - no matching file found
}
})
On your Angular frontend, you'd just need to request /getMyCssFile, and your server will respond with the matching file.

How to pass response values to Java API from Karate

How can I pass values from Karate API to Java class?
As mentioned in the documentation, I used the following code snippet to get the response from Java API. But its returning the response with un-formatted JSON content.
Map<String, Object> result = CucumberRunner.runClasspathFeature("demo/java/from-java.feature", args, true);
And then, I used the following script to print the response.
for(Map.Entry<String , Object> entry: getMbrWksMembershipDetailsResponse.entrySet())
{
if (entry.getKey().equalsIgnoreCase("response"))
{
System.out.println(entry.getValue());
}
}
It shows like,
{soap:Envelope={_={soap:Body={ns1:getMbrWksMembershipDetailsResponse={_={ns4:WksMembershipSummaryResponse={_={ns2:customerSummary={ns2:address={ns2:city=SOUTH CHESTERFIELD, ns2:country=USA, ns2:isoCountryCode=US, ns2:line1=9998, N. MICHIGAN ROAD., ns2:postalCode=23834, ns2:state=VA}, ns2:allowPasswordChange=true, ns2:arpMember=false, ns2:brandCode=RCI, ns2:brandId=1, ns2:companyCode=RCI, ns2:eliteMemberRewardStatus=false, ns2:eliteRewardStatus=true, ns2:europePointsClubMember=false, ns2:firstName=FRANK, ns2:homePhone=804/733-3004, ns2:isoCurrencyCode=USD, ns2:isoLanguageCode=EN, ns2:language=EN, ns2:lastName=BROWNING B, ns2:locale=en_US, ns2:memberDeveloperRenewed=false, ns2:memberEnrolledDate=2009-10-26T00:00:00-04:00, ns2:memberEnrolledForDirectDebit=false, ns2:memberEnrolledForPltDirectDebit=false, ns2:memberStatus=A, ns2:middleName=B, ns2:msgTranslationLanguageCode=EN, ns2:officePhone=0/-0, ns2:pointsCurrencyCode=0......
So it's little difficult to split the data based on the fields / tags from Map.
Please suggest what is the best option to get the values field wize / tag wise from Java API.
Thanks.
Yes, XML is internally held as a strange Map structure, refer to the section on type-conversion to understand more.
You have a simple way to do this. Just define a new variable that is the response converted to a string.
* xmlstring responseXml = response
After this you just need to get the responseXml out of the Map returned by the Java API which will be a string.
Note: don't use the Java API unless you are really trying to mix Karate with something else. The whole point of Karate is to avoid using Java for testing JSON and XML web-services.

REST - post to get data. How else can this be done?

According to my understandings, you should not post to get data.
For example, I'm on a project and we are posting to get data.
For example, this following.
{
"zipCOde":"85022",
"city":"PHOENIX"
"country":"US"
"products":[
{
"sku":"abc-21",
"qty":2
},
{
"sku":"def-13",
"qty":2
}
]
}
Does it make sense to post? How could this be done without posting? There could be 1 or more products.
Actually there is a SEARCH method in HTTP, but sadly it is for webdav. https://msdn.microsoft.com/en-us/library/aa143053(v=exchg.65).aspx So if you want to send a request body with the request, then you can try with that.
POSTing is okay if you have a complex search. Complex search is relative, by me it means, that you have different logical operators in your query.
The current one is not that complex, and you can put the non-hierarchical components into the query string of the URI. An example with additional line breaks:
GET /products/?
zipCOde=85022&
city=PHOENIX&
country=US&
filters[0]['sku']=abc-21&
filters[0]['qty']=2&
filters[1]['sku']=def-13&
filters[1]['qty']=2
You can choose a different serialization format and encode it as URI component if you want.
GET /products/?filter={"zipCOde":"85022","city":"PHOENIX","country":"US","products":[{"sku":"abc-21","qty":2},{"sku":"def-13","qty":2}]}
One potential option is to JSON.serialize your object and send it as a query string parameter on the GET.

Regular expression default value

Jmeter passes default value when trying to fetch a part of response in my case is a unique name which I want to pass in next request but it takes default value:
{"status":"success","body":{"uniqueName":"jpr1444130495897","voucherType":"sales","transactions":[{"creditAccount":{"uniqueName":"acctomerge","name":"Mayank"},"debitAccount":{"uniqueName":"dacc","name":"dummyaccount"},"amount":2228}],"voucherNo":1912,"date":"01-09-2015","tag":"dummydata","description":"Q3goK8QrUo"}}
In above response I have to capture uniquename & pass it in my next request. But by default it take default value.
Bean shell assertion contains:
${__setProperty(uniqueName,${uniqueName})}
Next request is this.
Still fetching default value. Somebody please help.
As Biffen said it is better to use JSON Path Extractor that comes with jmeter plugins (http://jmeter-plugins.org/wiki/JSONPathExtractor/). It's a lot easier for JSON - just put JSON path (probably in your case just uniqueName will be enough, but you can put there $.body.uniqueName) add a variable name as uniqueName as well, so there will be no problem to use it later as ${uniqueName} in the next request. And that's it.
Oh, and your post suggests that you try to extract it with Beanshell assertion instead of Regular Expression Extractor by the way - that also can be a case.
What exact uniqueName you need to extract? There are 3 of them in your JSON data:
jpr1444130495897
acctomerge
dacc
It isn't necessary to convert variable to property to use in next request. If both requests live in the same thread group - it's enough to use reference name like ${uniqueName}
For JSON data it's more handy to use JSON Path Extractor (available via JMeter Plugins project). See Using the XPath Extractor in JMeter guide (scroll down to "Parsing JSON") for plugin installation and usage instructions.

Error in getting user nodes while giving no. of hops as an input using spring with neo4j query

I am executing the query using spring with neo4j..
#Query(value = "START me=node({0}) MATCH me-[:ACTIVEFRIEND*1..{1}]->friend RETURN friend")
public Iterable<User> searchUserInNHops(User a, int hops);
where the depth threshold which the search should go is given as an input hops..
It is not working and giving the error..
The server encountered an internal error that prevented it from fulfilling this request
Request processing failed; nested exception is org.neo4j.rest.graphdb.RestResultException: Properties on pattern elements are not allowed in MATCH
Neo4j Version: 1.9.0
I will appreciate if someone can help me on this.
Thanks
Hemant
You can't specify the depth as a paramater. If you want this to be dynamic, you might want to consider alternative approaches. Some of them are:
Let your repository class extend from CypherDslRepository. Use should use the neo4j-cypher-dsl module to build a query object.
Use the Neo4jTemplate class. You could provide a composed query string to the query method.
Use the traversal API of Neo4j core, like
Traversal:
for (final Path position : Traversal.description().depthFirst() .relationships(RelationType.ACTIVE_FRIEND, Direction.OUTGOING),
Direction.INCOMING).evaluator(Evaluators.fromDepth(1))
.evaluator(Evaluators.toDepth(yourDynamicValue))
.evaluator(Evaluators.excludeStartPosition()).traverse(node)) {
position.endNode();
}