My task is simple to download a file from a url using selenium. I did till clicking on the download part. Now I want to wait till the file is downloaded.Fine. I use following and done.
do {
Thread.sleep(60000);
}
while ((downloadeBuild.length()/1024) < 138900);
Now challenge is for how much time do I wait ? Can I set some threshold ? I can think of is use a counter in do while and check till counter goes to 10 or something like that ? But any other way in Java ? As such I do not have any action to do till the file is downloaded.
How about this?
I think using TimeOut is not stable since there is no need to wait for a un-predictable downloading operation.
You can just turn to CompletableFuture using supplyAsync to do the downloading and use thenApply to do the processing/converting and retrieve the result by join as follows:
public class SimpleCompletableFuture {
public static void main(String... args) {
testDownload();
}
private static void testDownload() {
CompletableFuture future = CompletableFuture.supplyAsync(() -> downloadMock())
.thenApply(SimpleCompletableFuture::processDownloaded);
System.out.println(future.join());
}
private static String downloadMock() {
try {
Thread.sleep(new Random().nextInt() + 1000); // mock the downloading time;
} catch (InterruptedException ignored) {
ignored.printStackTrace();
}
return "Downloaded";
}
private static String processDownloaded(String fileMock) {
System.out.println("Processing " + fileMock);
System.out.println("Done!");
return "Processed";
}
}
You can use guava Stopwatch
Stopwatch stopwatch = Stopwatch.createStarted();
while ((downloadeBuild.length()/1024) < 138900 && topWatch.elapsed(TimeUnit.SECONDS) < 60);
If what you want is a time out practice, may be you can try code below:
long timeout = 10 * 60 * 1000;
long start = System.currentTimeMillis();
while(System.currentTimeMillis() - timeout <= start ){
//Not timeout yet, wait
}
//Time out, continue
It's quite common in java library.
Related
I get my data from the server and have to update it every x seconds.
I do this using the Handler's postDelayed function.
private long mInterval = 10000;
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try {
takeServerResponse(); //with vary duration
}catch (Exception e){
itsRunning = false;
} finally {
if(mHandler!=null) {
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
}
};
Sometimes it may take more than X seconds to get new data.
What can I do in this situation?
If we need increase interval,how to determine when to do so?
You can calculate the duration time of your job and postDelayed your handler based on the duration time.
For example:
startTime = System.currentTimeMillis();
//your job
duration = System.currentTimeMillis() - startTime;
mInterval = mInterval - duration
your handler used to call the server response after 10 sec.But Its all depend own your internet speed to get the data from server that's the reason its take long time
I want to send a ping for up to 10 users at the same time, and update the user object with the result once the ping is done.
In order to do this, I am trying to use ExecutorService.
I started with a code like this:
private void pingUsers(List<User> userList) throws ExecutionException, InterruptedException {
final int NUM_THREADS = 10;
ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
for (User user : userList) {
SnmpPingDevice pingUser = new PingUser(user);
Future<Boolean> isUserActive = executor.submit(pingUser);
user.isActive = isUserActive.get() ; // -- I guess it will block other pings and i'm back to my starting point where I need to run the pings in parallel.
}
executor.shutdown();
try {
executor.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.error("Failed to terminate executor");
}
}
This is how my PingUser class look like:
#Override
public Boolean call() {
ping = new CmdRunner(toolDir,outDir,
new UserOidWorkerPing(version,community,ip,logger));
return this.isActive();
}
public boolean isActive(){
String cmd = ping.getCmdNoRedirect();
String rc = this.cmdRunner.runShellCmd(cmd,this.outDir +"/dummy",false);
logger.debug("PING was sent with cmd:" + cmd + ",rc:" + rc);
return rc != null && !rc.contains("Timeout:") && !rc.isEmpty();
}
And back to the same issue, that the pings won't run in parallel (as soon as the loop waiting for the isUserActive.get() to end)
Any idea what I'm missing? How I can make those pings run in parallel and save the result for each user in my List<User> userList?
Future::get is a blocking operation so the invoking thread will be blocked until the call is completed. So you submit a new task only after the previous was finished.
Consider using ExecutorService::invokeAll which will return a list of Futures :
List<PingUser> pingUsers = userList.stream().map(PingUser::new).collect(Collectors.toList());
List<Future<Boolean>> results = executor.invokeAll(pingUsers);
You are blocking your execution for each call, with this line:
user.isActive = isUserActive.get() ;
This effectively waits for the call to end, and does this for each call, on at a time.
You should rather submit all tasks, and build a list of Futures, to only wait for results when all tasks have been submitted. Something like this:
List<Future<Boolean>> tasks = new ArrayList<>();
for (User user : userList) {
SnmpPingDevice pingUser = new PingUser(user);
tasks.add(executor.submit(pingUser));
}
for(Future<Boolean> task: tasks) {
//use the result... OK to get() here.
}
What you can do is add the user.isActive = future.get() into the Runnable you submit.
for (User user : userList) {
SnmpPingDevice pingUser = new PingUser(user);
executor.submit(() -> user.isActive = pingUser.call());
}
I am tying to parse a website with html unit. The process basically;
WebClient client = new WebClient(BrowserVersion.CHROME);
client.waitForBackgroundJavaScript(5 * 1000);
HtmlPage page = client.getPage("http://www.exapmle.com"); //here it waits to run js code.
HtmlUnorderedList ul = (HtmlUnorderedList) page.getByXPath("//ul[contains(#class, 'class-name')]").get(0);
HtmlListItem li = (HtmlListItem) ul.getChildNodes().get(1); // I want to click li and get result page. But it takes a little time to execute.
li.click();
client.waitForBackgroundJavaScript(5 * 1000); //At here it does not do what I want.
After that when I check the page, I see that its content does not change.
What can I do to get correct page result?
Thanks.
You could try polling for a javascript condition to be true
int attempts = 20;
int pollMillis = 500;
boolean success = false;
for (int i = 0; i < attempts && !success; i++) {
TimeUnit.MILLISECONDS.sleep(pollMillis);
if (someJavascriptCondition == true) {
success = true;
}
}
if (!success) throw new RuntimeException(String.format("Condition not met after %s millis", attempts * pollMillis);
A similar technique discussed here
WebClient client = new WebClient;
HtmlPage page = client.getPage("http://www.exapmle.com");
client.waitForBackgroundJavaScript(5 * 1000);
Thread.sleep(10*1000);// this code will waite to 10 seconds
HtmlUnorderedList ul = (HtmlUnorderedList) page.getByXPath("//ul[contains(#class, 'class-name')]").get(0);
HtmlListItem li = (HtmlListItem) ul.getChildNodes().get(1); // I want to click li and get result page. But it takes a little time to execute.
li.click();
client.waitForBackgroundJavaScript(5 * 1000);
// this code will waite to 10 seconds
Thread.sleep(10*1000);
use Thread.sleep() instead of waitForBackgroundJavaScript
works for me!
You can use a JavaScriptJobManager to check the amount of JavaScript jobs that have yet to complete. Try the following code after you call click().
JavaScriptJobManager manager = page.getEnclosingWindow().getJobManager();
while (manager.getJobCount() > 0) {
System.out.printlin("Jobs remaining: " + manager.getJobCount());
Thread.sleep(1000);
}
You may want to add another way to end the while loop in case your JavaScript jobs never finish. Personally, I start terminating jobs manually with:
JavaScriptJob job = manager.getEarliestJob();
System.out.println("Stopping job: " + job.getId());
manager.stopJob(job.getId());
Hope this helps.
For example:
HttpClient hc =...
...
//need a wait time(Thread.sleep(xxx)) here before executing
hc.execute(post)
...
//need a wait time(Thread.sleep(xxx)) here before executing
hc.execute(get)
...
...
What's the best way to do it? Thanks a lot for any suggest.
It depends if you want at least a certain amount of time to wait. Thread.sleep is not guaranteed to sleep the time you provide as argument.
Also sleep can be interrupted, so you need to take this into account.
You can do something like this:
public static void waitAtLeast(long millis) {
long startTime = System.nanoTime();
while (true) {
long now = System.nanoTime();
long timeWaited = (now - startTime) / 1000000L;
if (timeWaited > millis) {
return;
}
try {
Thread.sleep(millis - timeWaited);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
I have issue keep throw error of unable to find the xpath , as i set the loop for opening this xpath to insert data . Although i set the time wait for existance to 60secound but it still couldn't find it. I been trying alot method calling this by using title or status hence it still not working . Kindly advise
HTML :
91.14
CODE :
public void clickOnItemTax () {
By xPath = By.xpath("//a[contains(#href,'edit_total_amt')]");
this.sleep(3);
if (this.waitForExistence(xPath,60)) {
WebElement domLink = linkGet(xPath);
domLink.click();
} else {
JLog.fail("Unable to find a writable item taxdialog!");
}
}
-waitforExistence
public boolean waitForExistence(By by, int timeoutSeconds){
boolean exists = false;
Long polling_interval = (long) 250;
Long timeout = (long) timeoutSeconds * 1000; // in seconds
Long elapsed = (long) 0;
while (elapsed <= (timeout)) {
if (exists(by)) {
exists = true;
break;
}
try {
Thread.sleep(polling_interval);
} catch (InterruptedException e) {
JLog.warning(JLog.getStackTraceAsString(e));
break;
}
elapsed += polling_interval;
}
if (elapsed >= timeout) {
JLog.warning("waitForExistence waited for " + timeout/1000 + " seconds, but unable to find: " + by.toString());
}
return exists;
}
Thanks you
If it's an internal company webpage could I suggest that you give the an 'id' to make your life easier. If not you can do this. I'm always surprised by people writing their own wait method when you could use either the implicit or explicit wait time in Selenium.
The former is as follows, the only thing to be aware using this method is that when looking for an element it will always wait this long. It is however a much safer way to write your scripts looking for elements and doesn't bloat your code:
driver.manage().timeouts().implicitlyWait(6, TimeUnit.SECONDS);
if (driver.findElements(By.cssSelector("//*[#title=\"Override total tax amount\"]")).size()!=0)
{
driver.findElement(By.cssSelector("//*[#title=\"Override total tax amount\"]")).click();
}
else
{
JLog.fail("Unable to find a writable item taxdialog!");
}
The explicit way to do it would be as follows where 10 is your seconds:
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("//*[#title=\"Override total tax amount\"]")));
See the following link for more on this.
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp