StaleElementReferenceException while iterating over embedded links - java

On my webpage I have a list of links to sections, each section has links to details. I'm trying to go to each section, then verify all the links are not broken.
List<WebElement> sections = driver.findElements(By.xpath("//*[#id='sections']/li/a"));
System.out.println("sections: " + sections.size());
sections.forEach(selement -> {
selement.click();
List<WebElement> details = driver.findElements(By.xpath("//*[#id='details']/div/table/tbody/tr/td/table[1]/tbody/tr/td[2]/strong/a"));
System.out.println("details: " + details.size());
details.forEach(delement -> {
url = delement.getAttribute("href");
try {
huc = (HttpURLConnection) new URL(url).openConnection();
huc.setRequestMethod("HEAD");
huc.connect();
respCode = huc.getResponseCode();
if(respCode == 404) {
System.out.println(url + " link is broken");
} else if (respCode == 200) {
System.out.println(url + " link is ok");
} else {
System.out.println(url + " returned code " + respCode);
}
huc.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
});
driver.navigate().back();
});
The problem is I'm getting a StaleElementReferenceException after the first sections' details are checked. I'm guessing it's because after iterating over details and going back Selenium does not treat the rest of the sections list as current?
I could probably create a list of all the hrefs for sections and then iterate over that list navigating to specific section link and then checking for details' links. But maybe there is some other/simpler solution?

Yes, you are correct, after going back to the main page. list elements are changing and it will not refer same elements even though it is same.
You can not use for each for the first/outer iteration. You can change it as follows. Also. list elements should be re identified/searched after going back.
List<WebElement> sections = driver.findElements(By.xpath("//*[#id='sections']/li/a"));
System.out.println("sections: " + sections.size());
for(int i=0;i<sections.size();i++){
WebElement selement = sections.get(i);
selement.click();
List<WebElement> details = driver.findElements(By.xpath("//*[#id='details']/div/table/tbody/tr/td/table[1]/tbody/tr/td[2]/strong/a"));
System.out.println("details: " + details.size());
details.forEach(delement -> {
url = delement.getAttribute("href");
try {
huc = (HttpURLConnection) new URL(url).openConnection();
huc.setRequestMethod("HEAD");
huc.connect();
respCode = huc.getResponseCode();
if(respCode == 404) {
System.out.println(url + " link is broken");
} else if (respCode == 200) {
System.out.println(url + " link is ok");
} else {
System.out.println(url + " returned code " + respCode);
}
huc.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
});
driver.navigate().back();
sections = driver.findElements(By.xpath("//*[#id='sections']/li/a"));
}

Related

Exiting a for loop via try/catch

following is a portion of my code
if(search_result.contains(num_per_page_str)) { // if num item per page is => 24,
for(int item = 1 ; item <= num_per_page_int ; item++ ) { //interate over the current page
Thread.sleep(3000);
try {//if display vertical + horizontal
WebElement url = driver.findElement(By.linkText(item_desc)); // get the URL via element
String item_URL = url.getAttribute("href");
System.out.println("Item URL = " + item_URL);
getPrice(driver, item_URL);
} //try
catch (Exception e) { //if display vertical only
WebElement url = driver.findElement(By.linkText(item_desc)); // get the URL via element
String item_URL = url.getAttribute("href");
System.out.println("Item URL = " + item_URL);
getPrice(driver, item_URL);
} //catch
} // for int item = 1
} //if search result
else { //if items per page < 24
}//else
Once in the try/catch branch, upon reaching getPrice(driver, item_URL); , I expect it to call the getPrice function together with the arguements.
However, what I am getting now is upon executing the calling of the getPrice() function, it did not exit the for loop and re-iterates the loop.
Am I doing anything wrong in my code that blocks the exiting of for loop ? Thanks
Add a break after calling getPrive, like:
for(int item = 1 ; item <= num_per_page_int ; item++ ) { //interate over the current page
Thread.sleep(3000);
try {//if display vertical + horizontal
WebElement url = driver.findElement(By.linkText(item_desc)); // get the URL via element
String item_URL = url.getAttribute("href");
System.out.println("Item URL = " + item_URL);
getPrice(driver, item_URL);
break;
} //try
catch (Exception e) { //if display vertical only
WebElement url = driver.findElement(By.linkText(item_desc)); // get the URL via element
String item_URL = url.getAttribute("href");
System.out.println("Item URL = " + item_URL);
getPrice(driver, item_URL);
break;
} //catch
} // for int item = 1

Java "Content not allowed in prolog.”

I am writing a client that can reserve slots, view available slots, view slots you've booked and cancel reserved slots. My code for works for everything but reserving slots.
The below is code for reserving a slot.
while(hotelBooked == false && bandBooked == false)
{
// This works
xmlString = XMLRequest.availability(requestID, USERNAME, PASSWORD);
ArrayList<String> availSlots = checkAvailiabilityOrBookings(xmlString);
for(int i = 0; i < availSlots.size(); i++)
{
TimeUnit.SECONDS.sleep(1);
System.out.println("availSlots.get(" + i + "): " + Integer.parseInt(availSlots.get(i).trim()));
// generate a unique ID based off time
requestID = genRequestID();
System.out.println("REQUESTID" + requestID);
//Something goes wrong around here
xmlString = XMLRequest.Reservation(requestID, USERNAME, PASSWORD, 134);
// breaks in this method
hotelBooked = reserveSlot(xmlString, hotelNum);
if(hotelBooked == true)
{
bandBooked = reserveSlot(xmlString, bandNum);
if(bandBooked == false)
{
requestID = genRequestID();
System.out.println("REQUESTID " + requestID);
xmlString = XMLRequest.cancel(requestID, USERNAME, PASSWORD, Integer.parseInt(availSlots.get(i).trim()));
cancelSlot(xmlString, hotelNum);
}// if
else
{
requestID = genRequestID();
System.out.println("REQUESTID" + requestID);
xmlString = XMLRequest.bookings(requestID, USERNAME, PASSWORD);
bookedSlots = checkAvailiabilityOrBookings(xmlString);
System.out.println("1st time - Booked slots:");
System.out.println(bookedSlots.toString());
break;
}
}// if
The below is the method it breaks in
// reserve a slot
public static Boolean reserveSlot(String xmlString, String hotelOrBand) {
System.out.println("Entered reserveSlot");
Response recMsgOutput;
PutMethod putMethod;
boolean booked = false;
try {
if(hotelOrBand.equals(String.valueOf(3010)))
{
putMethod = putMethodHotel;
}
else
{
putMethod = putMethodBand;
}
/*
* Set the request's entity (body).
*/
System.out.println("Set the request's entity (body)");
RequestEntity entity = new StringRequestEntity(xmlString);
putMethod.setRequestEntity(entity);
/*
* Set the put method's headers
*/
System.out.println("Set the put method's headers");
putMethod.addRequestHeader("Content-Type", "application/xml");
putMethod.addRequestHeader("Accept", "application/xml");
/*
* Create a client and the execute the put method.
*/
System.out.println("Create a client and the execute the put method.");
HttpClient client = new HttpClient();
int responseCode = client.executeMethod(putMethod);
while(responseCode != HttpStatus.SC_OK){
client = new HttpClient();
responseCode = client.executeMethod(putMethod);
TimeUnit.SECONDS.sleep(1);
}// while
if (responseCode == HttpStatus.SC_OK) {
System.out.println("Message uri: " + Response.getMsgURI(putMethod.getResponseBodyAsString()));
String [] message = Response.getMsgURI(putMethod.getResponseBodyAsString()).split("/");
String msgNum = message[message.length - 1];
String recMsgArg = "http://jewel.cs.man.ac.uk:" + hotelOrBand + "/queue/msg/" + msgNum + "?username=0ih058&password=4UhMf9";
System.out.println("recMsgArg " + recMsgArg);
String [] recMsgArgArray = new String[1];
// Send requests to ClientRecMsg
recMsgArgArray[0] = recMsgArg;
System.out.println("recMsgArgArray " + recMsgArgArray[0]);
recMsgOutput = ClientRecMsg.main(recMsgArgArray);
Matcher matcher1 = Pattern.compile("\\d+").matcher(recMsgOutput.toString());
matcher1.find();
int responseNum = Integer.valueOf(matcher1.group());
System.out.println("num: " + responseNum);
if(responseNum == 200)
booked = true;
} else if(responseCode != HttpStatus.SC_OK) {
System.out.println("Error code:" + responseCode);
System.out.println("Error message:" + putMethod.getResponseBodyAsString());
}
}//try
Outputs this
availSlots.get(4): 135
REQUESTID 1584934385
Entered reserveSlot
Set the request's entity (body)
Set the put method's headers
Create a client and the execute the put method.
[Fatal Error] :1:1: Content is not allowed in prolog.
uk.ac.manchester.cs.comp28112.lab2.ParseException
at uk.ac.manchester.cs.comp28112.lab2.Response.getMsgURI(Response.java:179)
at uk.ac.manchester.cs.comp28112.lab2.ClientReserve.reserveSlot(ClientReserve.java:527)
at uk.ac.manchester.cs.comp28112.lab2.ClientReserve.reserveRequest(ClientReserve.java:164)
at uk.ac.manchester.cs.comp28112.lab2.ClientReserve.main(ClientReserve.java:77)
The XML for reservation is the code below
static public String Reservation(String request_id, String username,
String password, int slot_id) throws RequestException {
try {
XMLRequest.createBuilder();
Document document = documentBuilder.newDocument();
Element reserve_element = document.createElement(RESERVE_ELEMENT);
document.appendChild(reserve_element);
Node id_element = document.createElement(REQUEST_ID_ELEMENT);
id_element.appendChild(document.createTextNode(request_id));
reserve_element.appendChild(id_element);
Node username_element = document.createElement(USERNAME_ELEMENT);
username_element.appendChild(document.createTextNode(username));
reserve_element.appendChild(username_element);
Node password_element = document.createElement(PASSWORD_ELEMENT);
password_element.appendChild(document.createTextNode(password));
reserve_element.appendChild(password_element);
Node slot_id_element = document.createElement(SLOT_ID_ELEMENT);
slot_id_element.appendChild(document.createTextNode(new Integer(
slot_id).toString()));
reserve_element.appendChild(slot_id_element);
return XMLRequest.toString(document);
} catch (ParserConfigurationException e) {
throw new RequestException(e);
} catch (TransformerConfigurationException e) {
throw new RequestException(e);
} catch (TransformerFactoryConfigurationError e) {
throw new RequestException(e.getException());
} catch (TransformerException e) {
throw new RequestException(e);
}
Below is the method for Response.getMsgURI()
static public String getMsgURI(String xmlString) throws ParseException {
try {
Response.createBuilder();
InputSource source = new InputSource(new StringReader(xmlString));
Node node = (Node) msgIdXPathExpression.evaluate(source, XPathConstants.NODE);
return node.getTextContent();
} catch (XPathExpressionException e) {
throw new ParseException();
} catch (ParserConfigurationException e) {
throw new ParseException();
}
}
Below is the output for putMethod.getResponseBodyAsString()
Status: 500 Internal Server Error
Content-Type: text/html
<html><body><h1>500 Internal Server Error</h1></body></html>
I've think it's something to do with making multiple xml requests in the same method because when I make the reservation request first it runs fine but when I try to make another xml request immediately after that gets stuck as well.
Sorry for including so much code, help would be much appreciated thanks.
The problem was that I was trying to reuse putMethod objects, I needed to create a new one everytime I made a request. I don't know why this is though.

Selenium method visibilityOf - Doesn't seem to be working?

When i used the listed method to see whether an element is visible on the page, I get an exception stating that its unable to locate an element using the specified locator.
Any ideas, has anyone faced this issue before or even have a better method?
public boolean isElementPresentByWebElement(WebElement element) {
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver).withTimeout(15, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
for (int i = 0; i < 2; i++) {
try {
fluentWait.until(ExpectedConditions.visibilityOf(element));
System.out.println("Element is visible: " + element.toString());
return true;
} catch (Exception e) {
System.out.println(
"Unable to locate the element: " + element.toString() + ", Exception: " + e.toString());
throw (e);
}
}
return false;
}
I think your code is overly complicated for what you are trying to do. There is a built in class, ExpectedConditions, that will do what you want. You are also looping over the wait which is unnecessary. I would suggest that you pass in a locator (By) instead of a WebElement. It will expand your ability to use this function because you won't have to find the element before using the function.
public boolean isElementPresentByLocator(By locator)
{
try
{
new WebDriverWait(driver, 15).until(ExpectedConditions.visibilityOfElementLocated(locator));
System.out.println("Element is visible: " + locator.toString());
return true;
}
catch (TimeoutException e)
{
System.out.println("Unable to locate the element: " + locator.toString() + ", Exception: " + e.toString());
return false;
}
}
The code below is more of a direct translation and simplification of your code.
public boolean isElementPresentByWebElement(WebElement element)
{
try
{
new WebDriverWait(driver, 15).until(ExpectedConditions.visibilityOf(element));
System.out.println("Element is visible: " + element.toString());
return true;
}
catch (TimeoutException e)
{
System.out.println("Unable to locate the element: " + element.toString() + ", Exception: " + e.toString());
return false;
}
}
Updated :
try using following :
int waitCounter = 0;
public static void WaitUntilVisible(WebDriver driver, WebElement element) throws InterruptedException, IOException {
try {
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOf(elementToBeClicked));
if (!elementToBeClicked.isDisplayed()) {
System.out.println("Element not visible yet. waiting some more for " + element);
if (waitCounter < 3) {
waitCounter++;
WaitUntilVisible(element);
}
waitCounter = 0;
}
} catch (Exception e)
{
System.out.println("Handling exception");
}
}

How to fix input getting cut off by output

So, I'm trying to create a function (If not pretty) IRC client using no libraries, written in Java. I've gotten almost everything working, the only problem is that I'm currently getting user input using System.in. And if someone else in the channel sends a message while I'm in the middle of typing, it cuts off what I currently have, and I need to guess where I am in the string. I want to know if there's a way to separate user input from the output of the program, so that this doesn't happen. This is the code in question:
new Thread(() -> {
while(connected[0]) {
String output = sc.nextLine();
if(!output.startsWith("~") && !output.startsWith("/")) {
try {
writeToSocket("PRIVMSG " + focused[0] + " " + output);
} catch (IOException e) {
e.printStackTrace();
}
}
if(output.substring(1).toLowerCase().startsWith("quit")) {
String[] split = output.substring(5).split(" ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
if(i == 0) {
sb.append(split[i]);
}
sb.append(" ").append(split[i]);
}
try {
writeToSocket("QUIT " + sb.toString());
connected[0] = false;
} catch (IOException e) {
e.printStackTrace();
}
}else if(output.substring(1).toLowerCase().startsWith("focus")) {
String get = output.substring(7);
if(!channels.contains(get)) {
print("Not connected to channel");
}else {
try {
writeToSocket("PART " + focused[0]);
writeToSocket("JOIN " + get);
} catch (IOException e) {
e.printStackTrace();
}
focused[0] = get;
}
}else if(output.substring(1).toLowerCase().startsWith("join")) {
String get = output.substring(6);
channels.add(get);
}
if(output.startsWith("/") && output.substring(1).toLowerCase().startsWith("msg")) {
String[] split = output.substring(5).split(" ");
String username = split[0];
StringBuilder msg = new StringBuilder();
for(int i = 1; i < split.length; i++) {
if(i == 1) {
msg.append(split[i]);
continue;
}
msg.append(" ").append(split[i]);
}
try {
writeToSocket("PRIVMSG " + username + " " + msg.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();

NullPointerException with listview on android

I am want to show this json data in to listview. Iam having this problem:
java.lang.NullPointerException: Attempt to invoke virtual method 'org.json.JSONObject org.json.JSONArray.getJSONObject(int)' on a null object reference
private String[] arrow() throws JSONException {
json = new JSONObject();
JSONArray com= null;
String[] list = new String[10];
try {
com = json.getJSONArray("parameters"); // this have 10 different values
} catch (JSONException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++)
try {
json = com.getJSONObject(i);
String forward= json.getString("forward");
String back= json.getString("back");
list[i]="Forward: " + forward + "\n" + "Backward: " + back;
} catch (JSONException e) {
e.printStackTrace();
}
return list;
}
I did it with textview but cant do it with listview, i get this nullpointer..
Please help. Thanks.
There are multiple problems. The first problem is that you are using two try/catch. If you get exception in first one, you still go to 2nd try and try to run code.
json = com.getJSONObject(i);
this line is in 2nd try catch. In your case it seems com is null because there was exception in 1st try/catch.
try {
com = json.getJSONArray("parameters"); // this have 10 different values
for (int i = 0; i < com.length(); i++) {
json = com.getJSONObject(i);
String forward= json.getString("forward");
String back= json.getString("back");
list[i]="Forward: " + forward + "\n" + "Backward: " + back;
}
} catch (JSONException e) {
e.printStackTrace();
}

Categories