I have to call a series of http Request from a for loop from Beanshell processor in jmeter.
for (String fName : FNameArray)
{
System.out.println(fName);
if (dict.get(fName) != null)
{
String dicValue = dict.get(fName).toString();
String sr = dicValue.substring(dicValue.indexOf('=') + 1);
String id = sr.substring(sr.indexOf('=') + 1);
String pval = sr.substring(0, (sr.indexOf('=') - 3));
String email = id.replace("%40", "#");
System.out.println(id);
System.out.println(email);
System.out.println(pval);
// from here i have to call http request and pass the pval, id and email to that http request
}
}
From the above code, i have to pass pval, id and email to the 1st http request and then the next http request and so on.
but this pval, id and email are passing from a for loop.
how can i acheive this ?
I would go for the following option:
Amend your code as follows:
for (String fName : FNameArray) {
int counter = 1;
System.out.println(fName);
if (dict.get(fName) != null) {
String dicValue = dict.get(fName).toString();
String sr = dicValue.substring(dicValue.indexOf('=') + 1);
String id = sr.substring(sr.indexOf('=') + 1);
String pval = sr.substring(0, (sr.indexOf('=') - 3));
String email = id.replace("%40", "#");
System.out.println(id);
System.out.println(email);
System.out.println(pval);
vars.put("id_" + counter, id);
vars.put("email_" + counter, email);
vars.put("pval_" + counter, pval);
counter++;
// from here i have to call http request and pass the pval, id and email to that http request
}
}
Add ForEach Controller after Beanshell Test Element and configure it as follows:
Input variable prefix: id
Output variable name: current_id
Add "_" before number: checked
other fields - blank
Add Counter Test Element as a child of the ForEach Controller and configure it like:
Start: 1
Increment: 1
Reference Name: counter
Add HTTP Request Sampler after counter and use the following references:
"id" - ${current_id}
"email" - ${__V(email_${counter})}
"pval" - ${__V(pval_${counter})}
where required.
Alternative option is use Apache HTTPClient libraries (JMeter is built on top of them so they're available), see above link for quick start and examples. But in that case I would strongly recommend to use JSR223 Sampler and Groovy language instead of Beanshell.
Related
From a gatling senario making endpoint calls, where saving jobIds response from initiate endpoint into session and need to pass jobIds retrived from it to next endpoint call. However those values are not picked in call back endpoint.
code snippet:
var testScenario:ScenarioBuilder=scenario("Test Scenario")
.exec(testObj.initiateEndpoint())
.pause("8")
.exec(session => {
var jobId1: String = null
var jobId2: String = null
val jobIds = session(BulkConstants.JOB_IDS).as[Vector[String]]
if (jobIds != null && jobIds.size > 0) {
jobId1 = bulkJobIds(0)
println("************JobID1************", jobId1)
jobId2 = bulkJobIds(1)
println("************JobID2************", jobId2)
}
if(jobId1 != null && jobId2 != null)
session.set("jobId1", jobId1).set("jobId2", jobId2)
else
session
})
.exec(testObj.callBack("${jobId1}"))
.pause("2")
.exec(testObj.callBack("${jobId2}"))
.pause("2")
when I try to print values or use them in callBack(String jobId), it simply prints "${jobId1}" and not the passed value. what could be wrong here.
Gatling Expression Language doesn't work in your custom code.
You must use the Session API.
My test receives the following json in response.
{"result":"success","additional-info":"{\"q-list\":[{\"tag\":\"un2-new tag2-empty\",\"description\":\"some description2\",\"q-id\":\"5c86fb8a-d9ce-4978-be4c-2c4b547c7868\",\"creation-year\":2020,\"creation-month\":11,\"creation-hour\":8,\"creation-minute\":48}],\"pagination-info\":{\"page-state\":\"004400100038000800000000000000080800000000000000302435633836666238612d643963652d343937382d626534632d326334623534376337383638f07ffffffef07ffffffe9fde9512dc65b09db4b903cca66a71aa0004\",\"partition-info\":{\"year\":2020,\"month\":11}}}"}
I want to extract q-id from the response and the use it in next request. I have created the following extractor.
and am using it as follows:
But I see that the value is not getting extracted.
What am I doing wrong?
Happy to accept other answers. I was able to solve the issue by using beanshell script. However, I still don't know why extracting value from Regular Expression Extractor didn't work.
Beanshell script
import com.eclipsesource.json.*;
//prev.setSuccessful(false);
try {
String jsonString = prev.getResponseDataAsString(); //response as string
log.info("received json string: "+jsonString);
JsonObject responseAsJsonObject = JsonObject.readFrom(jsonString); //convert response string as json
log.info("converted to object: "+responseAsJsonObject);
String additionalInfoString = responseAsJsonObject.get("additional-info").asString(); //get additional info string from json object
log.info("additional info as string: "+additionalInfoString);
JsonObject additionalInfoJsonObject = JsonObject.readFrom(additionalInfoString); //convert additional info string to json
log.info("additional info as object: "+additionalInfoJsonObject);
JsonArray questionListObject = additionalInfoJsonObject.get("questions-list").asArray(); //get questions list array
log.info("questions list: "+questionListObject );
JsonObject firstQuestionFromList = questionListObject.get(0).asObject(); //get 1st question
log.info("first question: "+firstQuestionFromList);
String questionID = firstQuestionFromList.get("question-id").asString();
log.info("question id of 1st question "+questionID);
vars.put("questionIDFromBeanShell",questionID); //use this in next request
// prev.setSuccessful(true);
} catch (Exception e){
log.info("error in processing beanshell script: ", e);
prev.setSuccessful(false);
}
We are automating rest APIs using Rest Assured. During this process, trying to have a re-usable method created to pass different JSON nodes with different values.
Interger variable created:
Integer amt = 50;
Method created:
public void replaceValues_gson(String mainNode, String childNode, Integer amt) {
if(amt != null){
jsonObjectNew.getAsJsonObject("mainNode").add("childNode", gson.toJsonTree(amt));
}
//here 'amt' throws an error as java.lang.NullPointerException; Also the amt it shows as 9 assigned to variable amt in the debugger where as it supposed to assign 50 value
}
Calling above method as:
replaceValues_gson("bInfo", "bEx", amt );
Request JSON payload for the above is:
{
"bInfo":{
"bEx":9,
"oriDate":"2020-07-08"
}
}
Getting NullPointerException for 'amt' variable and Request JSON payload value is getting assigned rather assigning Integer amt value which is 50.
It works if directly trying like below:
jsonObjectNew.getAsJsonObject("bInfo").add("bEx", gson.toJsonTree(amt));
here amt variable value correctly goes as 50, but when trying to create re-usable method then throws an error.
Please guide.
You can use the following method. But it does not support when the value that need to be updated is inside a json array.
public void replaceValues_gson(JsonObject jsonObjectNew, String[] keyArray, Object updatingValue) {
Gson gson = new Gson();
JsonObject jsonObject = jsonObjectNew;
for (int i = 0; i < keyArray.length - 1; i++) {
jsonObject = jsonObject.getAsJsonObject(keyArray[i]);
}
jsonObject.add(keyArray[keyArray.length - 1], gson.toJsonTree(updatingValue));
System.out.println(jsonObjectNew.toString());
}
Here;
jsonObjectNew - the JsonObject converted from initial json request.
keyArray - String array of json node names from the root (in the exact order) including the key that need to be updated
updatingValue - value that will be updated
Eg:-
String[] keyArray = {"bInfo", "bEx"};
replaceValues_gson(jsonObjectNew, keyArray, 50);
Using the Microsoft.CrmSdk assembly to generate entities in Dynamics 365 for Customer Engagement (version 9), I found out that the method GetEntityMetadata from CrmServiceClient does not get the most uptodate information from entities.
Here the code to show you:
using (var svc = new CrmServiceClient(strConn))
{
EntityMetadata em = svc.GetEntityMetadata(PREFIX + TABLE_NAME_D, EntityFilters.Attributes);
if (em == null)
{
Console.WriteLine($"Create entity [{PREFIX + TABLE_NAME_D}]");
CreateEntityRequest createRequest = new CreateEntityRequest
{
Entity = new EntityMetadata
{
SchemaName = PREFIX + TABLE_NAME_D,
LogicalName = PREFIX + TABLE_NAME_D,
DisplayName = new Label(TABLE_LABEL, 1036),
DisplayCollectionName = new Label(TABLE_LABEL_P, 1036),
OwnershipType = OwnershipTypes.UserOwned,
},
PrimaryAttribute = new StringAttributeMetadata
{
SchemaName = PREFIX + "name",
MaxLength = 30,
FormatName = StringFormatName.Text,
DisplayName = new Label("Residence", 1036),
}
};
CreateEntityResponse resp = (CreateEntityResponse)svc.Execute(createRequest);
em = svc.GetEntityMetadata(PREFIX + TABLE_NAME_D, EntityFilters.All);
// At this point, em is null!!!
}
}
After the createResponse is received, the entity is well created in Dynamics, but still the GetEntityMetadata called just after is still null. If I wait a few seconds and make another call, the response is now correct. But that's horrible!
Is there any way to "force" the refresh of the response?
Thanks.
Ok I found it! It's linked to a caching mechanism.
One must use the function ResetLocalMetadataCache to clean the cache, but there seems to be an issue with this function.
It will only works by passing the entity name in parameter (if you call it without parameter, it is supposed to clean the entire cache but that does not work for me).
EntityMetadata em = svc.GetEntityMetadata(TABLE_NAME_D, EntityFilters.All); // Request sent
em = svc.GetEntityMetadata(TABLE_NAME_D, EntityFilters.All); // Cache used
svc.ResetLocalMetadataCache(); // No effect?!
em = svc.GetEntityMetadata(TABLE_NAME_D, EntityFilters.All); // Cache used
em = svc.GetEntityMetadata(TABLE_NAME_D, EntityFilters.All); // Cache used
svc.ResetLocalMetadataCache(TABLE_NAME_D); // Cache cleaned for this entity
em = svc.GetEntityMetadata(TABLE_NAME_D, EntityFilters.All); // Request sent!
My company has created a Yammer application that we use internally. Our app automatically subscribes people to various threads that have been created. We have found that there is a difference between "subscribing" someone to a thread and what happens when a user clicks the "follow in inbox" link on the site. When we automatically subscribe people, the only thing that we can see happening is that the thread will appear in the users "Following" section in the Home tab. Contrast this with what happens when a user clicks the "Follow in Inbox" link. From that point on any comments added to the thread will show up in the user's inbox and an email will be sent out to the user when this happens. We would really like for this to happen when we automatically subscribe someone to a thread, however, this feature seems to be missing from the REST API. Does anyone know of a way to accomplish this? The functionality provided by the subscription API endpoint is not sufficient for our purposes.
Thank you
P.S. I've sent the link to this question to several of my colleges they may respond before I get a chance to.
As a verified admin it is possible to create an impersonation token and then perform actions on behalf of the user such as join group/thread.
Note that for private groups, the group admin's are still required to approve the new member
https://developer.yammer.com/docs/impersonation
You can achieve your desired behaviour by adding users directly to the groups.
A C#.Net example I use:
// Impersonate user to join group
string ClientID = ConfigurationSettings.AppSettings["ClientID"]; // ClientID of custom app.
string userid = XMLDoc.Root.Element("response").Element("id").Value; // Yammer user id (in this case retreived from a previous API query)
string YammerGroupID = "123456"; // set group id.
string url = "https://www.yammer.com/api/v1/oauth/tokens.json?user_id=" + userid + "&consumer_key=" + ClientID; // impersonation end-point
HttpWebRequest request;
request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add("Authorization", "Bearer " + bearer); // Bearer token of verified admin running the custom app.
request.Timeout = 90000;
request.Method = "GET";
request.ContentType = "application/json";
request.Proxy = new WebProxy() { UseDefaultCredentials = true };
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream);
string UserTokenJSON = reader.ReadToEnd(); // UserOAuth token as a JSON string.
string UserToken = UserTokenJSON.Substring(UserTokenJSON.IndexOf("token") + 8, 22); // Find 'token' in json string.
string temp = UserToken.Substring(UserToken.Length); // there is likely a much better way to parse out the token value, although this works.
temp = UserToken.Substring(UserToken.Length - 1);
temp = UserToken.Substring(UserToken.Length - 2);
if (UserToken.Substring(UserToken.Length) == "\\")
{ UserToken = UserToken.Substring(0, UserToken.Length); }
if (UserToken.Substring(UserToken.Length - 1) == "\"")
{ UserToken = UserToken.Substring(0, UserToken.Length - 1); }
if (UserToken.Substring(UserToken.Length - 2) == "\",")
{ UserToken = UserToken.Substring(0, UserToken.Length - 2); }
string url2 = "https://www.yammer.com/api/v1/group_memberships.json?group_id=" + YammerGroupID; // group membership endpoint,
HttpWebRequest request2;
request2 = (HttpWebRequest)WebRequest.Create(url2);
request2.Headers.Add("Authorization", "Bearer " + UserToken); // Impersonation Token
request2.Timeout = 90000;
request2.Method = "POST";
request2.ContentType = "application/json";
request2.Proxy = new WebProxy() { UseDefaultCredentials = true };
try
{
using (WebResponse response2 = (HttpWebResponse)request2.GetResponse())
{
confirmedstring += " New member: " + Email + "\\r\\n"; // This is used for posting summary back to a Yammer group in further code.
confirmedadditions++;
}
}
catch
{
Errorstring += "Error in adding " + Email + " to group " + YammerGroupID + "\\r\\n";
errors++;
}
}
}