How to resolve "Cannot invoke method contains() on null object" - jmeter

In my script I am trying to make a get call and asserting on the response. This is working fine with valid response but for invalid response I am trying to fetch the UUID of the request URL but not working.
Request URL:
http://localhost:8080/log/log-events/6cef99be-591e-42e4-b07c-34b45f9540df
Response incase of failure:
{"trace-id":"8000043e-0001-eb00-b63f-84710c7967bb","invalid-param":[],"type":"https://tools.ietf.org/html/rfc7231#section-6.5.4","title":"The specified resource was not found.","status":404,"detail":"Resource not found","instance":"/log-events/6cef99be-591e-42e4-b07c-34b45f9540df"}
Assertion Script:
import groovy.json.JsonSlurper;
import java.util.regex.Pattern;
def failureMessage = "";
def jsonResponse = null;
JsonSlurper JSON = new JsonSlurper();
try {
jsonResponse = JSON.parseText(prev.getResponseDataAsString());
customerID = jsonResponse.customerId
} catch (Exception e) {
def requestData = sampler.getUrl().toString();
def pattern = Pattern.compile('^http?://localhost:8080/log/log-events/([^/]+)/.*$')
def (_, refDATA) = (requestData =~ pattern)[0]
failureMessage += refDATA
}
if (customerID.contains("Test") ||customerID.contains('KENDLE') || customerID.contains('CLINIRX') || customerID.contains('GSK')) {
AssertionResult.setFailure(false);
} else {
AssertionResult.setFailure(true);
AssertionResult.setFailureMessage(failureMessage);
}
Error message details:
2021-08-13 10:40:21,803 ERROR o.a.j.a.JSR223Assertion: Problem in JSR223 script: ClientID_Validator
javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method contains() on null object
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320) ~[groovy-jsr223-3.0.3.jar:3.0.3]
at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:71) ~[groovy-jsr223-3.0.3.jar:3.0.3]
at javax.script.CompiledScript.eval(Unknown Source) ~[?:1.8.0_251]
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:222) ~[ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.assertions.JSR223Assertion.getResult(JSR223Assertion.java:50) [ApacheJMeter_components.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.processAssertion(JMeterThread.java:916) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.checkAssertions(JMeterThread.java:885) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:573) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:489) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:256) [ApacheJMeter_core.jar:5.3]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_251]
Just wanted to print the UUID:6cef99be-591e-42e4-b07c-34b45f9540df incase of failure
What I missed here?

I fail to see any customerId object in your JSON response hence your line customerID = jsonResponse.customerId returns null and when later on you're trying to call customerID.contains() function it fails because customerID is null.
Without seeing successful response and not knowing what you're trying to achieve in case of success it's hard to advice anything meaningful, as a workaround you can add an extra check for the customerID like:
import groovy.json.JsonSlurper
import java.util.regex.Pattern
def failureMessage = "";
def jsonResponse = null;
JsonSlurper JSON = new JsonSlurper();
try {
jsonResponse = JSON.parseText(prev.getResponseDataAsString());
customerID = jsonResponse.customerId
} catch (Exception e) {
def requestData = sampler.getUrl().toString();
def pattern = Pattern.compile('^http?://localhost:8080/log/log-events/([^/]+)/.*$')
def (_, refDATA) = (requestData =~ pattern)[0]
failureMessage += refDATA
}
if (customerID != null) {
if (customerID.contains("Test") || customerID.contains('KENDLE') || customerID.contains('CLINIRX') || customerID.contains('GSK')) {
AssertionResult.setFailure(false);
} else {
AssertionResult.setFailure(true);
AssertionResult.setFailureMessage(failureMessage);
}
}
More information on using JSR223 Assertions: Scripting JMeter Assertions in Groovy - A Tutorial

You can split the URL and get the last item in the list.
Here is a sample code to extract the UUID from the URL
def requestData ="http://localhost:8080/log/log-events/6cef99be-591e-42e4-b07c-34b45f9540df"
def uuid = requestData.split("/").last()
println "uuid = $uuid"

Related

Return ldap entries on paginated form in springboot

I have a ldap method that returns all users that are in it (almost 1300 users) and I want to return them by page, similar to what PagingAndSortingRepository does in Springboot:
If I have this endpoint ( users/?page=0&size=1 )and I wnat to return on page 0 just 1 entry.
Is there any way to do that?
Currently I have this but it doesn´t work:
SearchRequest searchRequest = new SearchRequest(ldapConfig.getBaseDn(), SearchScope.SUB,
Filter.createEqualityFilter("objectClass", "person"));
ASN1OctetString resumeCookie = null;
while (true) {
searchRequest.setControls(new SimplePagedResultsControl(pageable.getPageSize(), resumeCookie));
SearchResult searchResult = ldapConnection.search(searchRequest);
numSearches++;
totalEntriesReturned += searchResult.getEntryCount();
for (SearchResultEntry e : searchResult.getSearchEntries()) {
String[] completeDN = UaaUtils.searchCnInDn(e.getDN());
String[] username = completeDN[0].split("=");
UserEntity u = new UserEntity(username[1]);
list.add(u);
System.out.println("TESTE");
}
SimplePagedResultsControl responseControl = SimplePagedResultsControl.get(searchResult);
if (responseControl.moreResultsToReturn()) {
// The resume cookie can be included in the simple paged results
// control included in the next search to get the next page of results.
System.out.println("Antes "+resumeCookie);
resumeCookie = responseControl.getCookie();
System.out.println("Depois "+resumeCookie);
} else {
break;
}
Page<UserEntity> newPage = new PageImpl<>(list, pageable, totalEntriesReturned);
System.out.println("content " + newPage.getContent());
System.out.println("total elements " + newPage.getTotalElements());
System.out.println(totalEntriesReturned);
}
I'm unsure if this is the proper way, but here's how I went about it:
public PaginatedLookup getAll(String page, String perPage) {
PagedResultsCookie cookie = null;
List<LdapUser> results;
try {
if ( page != null ) {
cookie = new PagedResultsCookie(Hex.decode(page));
} // end if
Integer pageSize = perPage != null ? Integer.parseInt(perPage) : PROCESSOR_PAGE_SIZE;
PagedResultsDirContextProcessor processor = new PagedResultsDirContextProcessor(pageSize, cookie);
LdapName base = LdapUtils.emptyLdapName();
SearchControls sc = new SearchControls();
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
sc.setTimeLimit(THREE_SECONDS);
sc.setCountLimit(pageSize);
sc.setReturningAttributes(new String[]{"cn", "title"});
results = ldapTemplate.search(base, filter.encode(), sc, new PersonAttributesMapper(), processor);
cookie = processor.getCookie();
} catch ( Exception e ) {
log.error(e.getMessage());
return null;
} // end try-catch
String nextPage = null;
if ( cookie != null && cookie.getCookie() != null ) {
nextPage = new String(Hex.encode(cookie.getCookie()));
} // end if
return new PaginatedLookup(nextPage, results);
}
The main issue I kept on hitting was trying to get the cookie as something that could be sent to the client, which is where my Hex.decode and Hex.encode came in handy.
PersonAttributesMapper is a private mapper that I have to make the fields more human readable, and PaginatedLookup is a custom class I use for API responses.

how to add the unified response body to ApiResponse

I want add unified response by modifying ApiResource. It is a HTTP body, it always contains json data below:
{
data: T
message: String
status: Int
}
I tried to add
val gson = Gson()
val stewardResponse = gson.fromJson(
response.body().toString(),
StewardResponse::class.java
)
if (body == null || response.code() == 204) {
ApiEmptyResponse()
} else {
ApiSuccessResponse(
body = stewardResponse.data,
linkHeader = response.headers()?.get("link")
)
}
but failed with the tip:
Type mismatch.
Required: ApiResponse<T> Found: ApiSuccessResponse<Any?>

Null Response on HttpWebRequest.GetResponse()?

I'm using http://dictionary.reference.com/browse/:word and check the status of returned response to evaluate whether the 'word' definition exists or not. It works fine for correct words (200 status code). But for those spelled incorrectly (404 status code), I'm unable to catch the status code from HttpWebRequest.GetResponse(), as it returns null?
The thing is I'm using PostMan to check and I did receive status code 404 there for the following url:
http://dictionary.reference.com/browse/sdfsdsdc
Here's my implementation:
string baseURL = "http://dictionary.reference.com/browse";
bool result = false;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(baseURL + "/" + word);
request.Method = "GET";
//request.Timeout = 2000;
request.KeepAlive = false;
request.ContentType = "text/html; charset=UTF-8";
Console.WriteLine(request.RequestUri);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
HttpStatusCode statusCode = response.StatusCode;
int statusCodeNumber = (int)statusCode;
Console.WriteLine("Status Code: " + statusCode + " - status number: " + statusCodeNumber);
try
{
if (statusCodeNumber == 200) result = true;
else if (statusCodeNumber == 404) { result = false; }
else { throw new UnknownStatusCodeException(); }
}
catch (UnknownStatusCodeException e) {}
response.Close();
}
catch (WebException e) {
}
}
Here's the WebException I caught
full-size-pic
Could someone give me some pointers? Thanks

How to let XPathExtractor extract xml element only if Http response code is 200?

In my JMeter test plan, I have a HttpRequest, I want to extract the link from its response only if the response code is 200.
I can add an XPathExtractor post processor under HttpRequest and it works.
But I want to have an IfCondition first so that the extractor won't try to work on invalid content. But the IfController can't be added as a postprocessor.
Maybe I can have a BeanShell sampler to do it but I don't know how to use XPathExtractor in BeanShell.
"Short and easy" way - use an additional Sampler
Add If Controller after the HTTP Request
Use ${JMeterThread.last_sample_ok} as "Condition"
Put Beanshell Sampler under the If Controller
Use the following code in Beanshell Sampler "Script" area:
SampleResult.setResponseData(ctx.getPreviousResult().getResponseData());
Put XPath Extractor as a child of the Beanshell Sampler
The above Beanshell script will return the same response as preceding HTTP Request sampler
"Long and hard" way - extract XPath directly in Beanshell.
Put Beanshell PostProcessor instead of XPath Extractor
Use the following script as a reference:
import org.apache.jmeter.util.PropertiesBasedPrefixResolver;
import org.apache.jmeter.util.XPathUtil;
import org.apache.xpath.XPathAPI;
import org.apache.xpath.objects.XObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
InputStream in = new ByteArrayInputStream(prev.getResponseData());
boolean useNameSpace = false;
boolean isTolerant = true;
boolean isQuiet = true;
boolean showWarnings = true;
boolean reportErrors = true;
boolean isXML = false;
boolean isDownloadDTDs = false;
if (prev.isResponseCodeOK()) {
InputStream in = new ByteArrayInputStream(prev.getResponseData());
boolean useNameSpace = false;
boolean isTolerant = true;
boolean isQuiet = true;
boolean showWarnings = true;
boolean reportErrors = true;
boolean isXML = false;
boolean isDownloadDTDs = false;
String query = "//a[text()='JMeter FAQ (Wiki)']";
List matchStrings = new ArrayList();
//matchStrings.add("-1");
boolean returnFragment = false;
Document doc = XPathUtil.makeDocument(in, false, false, useNameSpace, isTolerant, isQuiet, showWarnings, reportErrors
, isXML, isDownloadDTDs);
String val = null;
XObject xObject = XPathAPI.eval(doc, query, new PropertiesBasedPrefixResolver(doc.getDocumentElement());
int objectType = xObject.getType();
if (objectType == xObject.CLASS_NODESET) {
NodeList matches = xObject.nodelist();
int length = matches.getLength();
for (int i = 0; i < length; ++i) {
Node match = matches.item(i);
if (match instanceof Element) {
if (returnFragment) {
StringWriter sw = new StringWriter();
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(match), new StreamResult(sw));
val = sw.toString();
} else {
Node firstChild = match.getFirstChild();
if (firstChild != null) {
val = firstChild.getNodeValue();
} else {
val = match.getNodeValue();
}
}
} else {
val = match.getNodeValue();
}
matchStrings.add(val);
}
} else if (objectType != xObject.CLASS_NULL && objectType != xObject.CLASS_UNKNOWN && objectType != xObject.CLASS_UNRESOLVEDVARIABLE) {
val = xObject.toString();
matchStrings.add(val);
} else {
log.warn("Unexpected object type: " + xObject.getTypeString() + " returned for: " + query);
}
for (String match : matchStrings) {
log.info("Match -----> " + match);
}
}
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on using Beanshell in JMeter scripts

GRAILS - GORM : DuplicateKeyException during saving a new object

I use GORM to back occurrences in a database, from an excel file.
new ExcelBuilder(excelFile.inputStream).eachLine([labels: true, sheet: 0]) {
if (cell(0)) {
def nameA = cell(0)
def nameB = cell(1)
def a = Chapitre.findByNom(nameA)
def code = cell(2)
def designation = cell(3)
if (code == null || nameA == null || nameB == null) {
flash.messages << "error"
} else if (!Chapitre.findByNom(nameA)) {
flash.messages << "error"
} else if ( Rubrique.where{nom == nameB && chapitre == a}.list().size() == 0) {
flash.messages << "error"
} else if(Object.where{rubrique == Rubrique.findByNom(nameB) && c == code && d == designation}.count() > 0){
flash.messages << "error"
} else {
def b = Rubrique.findByNom(nameB)
def isNew = false;
Object.withNewSession {session2->
def object = Object.findOrCreateByCode(code)
if(object.designation == null)
isNew = true;
object.rubrique = b
object.d= (designation == null)?"":designation
// try {
rowCount += object.save()? 1 : 0
// } catch(ValidationException) {
// if(isNew)
// rowCount++;
// log.info("ErreuRRRRRRRRrrrRRrrRrRRrrrrRrrrRrrrRrrrr")
// }
}
}
}
currentLine++
}
flash.messages << "${rowCount} ligne create or update"
An update will break any worries, the course of the lines of file continue and database recording is effective.
However when it comes to inserting a new object, I get an Exception:
org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session:[fen.NuisanceType#2202];
nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
The registration of the object in question is effective , but the error raised off the path of the file.
When i uncommented the try and catch I bypasses the error and so all my copies of each file are created in the database .
I thus found a way around my worries, but I do not find it very clean and i come to you to try to understand my problem.
Without further information hard to give any clear answers. Is this code back in a service?(very much doubt it since it has flash.message pointing to controller doing all of it.) Try making it into a service and transactional then maybe you could look at removing withNewTransaction call.
You can read more about error created here:
Grails - DuplicateKeyException
Review comment:
"Well, that problem occurs when you are initializing a class new ClassD with an id or unique property manually, when there is another already in the session. So, you should try to get that entity first (that's what findOrCreateWhere does, but if you use an id you need to use get) and then use the instance found or create a new one for the update"
Hibernate Error: a different object with the same identifier value was already associated with the session
You code tidied up and running from service: (issues may go away) since I have also cleaned up the duplicated finds you were doing:
class TestService {
static transactional=true
def saveRecord() {
def results=[]
new ExcelBuilder(excelFile.inputStream).eachLine([labels: true, sheet: 0]) {
if (cell(0)) {
def nameA = cell(0)
def nameB = cell(1)
def code = cell(2)
def designation = cell(3)
def a = Chapitre.findByNom(nameA)
def b = Rubrique.where{nom == nameB && chapitre == a}
def c = Object.where{rubrique == b && c == code && d == designation}
if (!code||!nameA||!nameB||!a||!b||!c) {
results << "Error saving ${nameA} ${nameB} ${code}"
} else {
//boolean isNew = false
def object = Object.findOrSaveWhere(code:code)
if(object) {
if (!object.designation) {
rowCount++
results << "Record ${object} has no designation ? new Record?"
}
object.rubrique = b
object.d = designation ?: ''
object.save()
results << "Record ${object.id} is saved"
} else {
/*
* Could not save or find code:code now create a new object:
* object = new Object(code:code, rubrique:rubrique: d: designation ?: '').save()
*
*/
}
}
}
currentLine++
}
results << "${rowCount} ligne create or update"
return results
}
}

Resources