i have written an Java Applet, which is loaded in HTML and its function is called through javascript.
The Applet ist loaded with this html-Code:
<applet id="xapplet" code="xapplet" archive="java/xApplet.jar" height="0" width="0"></applet>
In the applet is a function, which returns an ArrayList.
public ArrayList<String> GetXY()
{
ArrayList<String> lStrX=new ArrayList<String>();
lStrX.add("X");
lStrX.add("Y");
return lStrX;
}
THe function is called through javascript:
var applet = document.getElementById('xapplet');
var xy = applet.GetXY();
In most browsers I can access the Properties of the java-Object, which is given as result. I have successfully tested this with Firefox, Internet Explorer and Chrome.
Only in Safari the Objects I get have the type "CRuntimeObject", which donĀ“t have any property or function.
So it seems to me, that in Safari i have to do something different. Can anyone can help me?
Thank you.
I do not know how to do it on Saphari but I'd recommend you to make some changes to your java code. Your method should return array, not list. I believe that in this case you will be able to access the element of this array from java script in all browsers.
Related
I am working on an app in Android Studio and am having some trouble web-scraping with JSoup. I have successfully connected to the webpage and returned some basic elements to test the library, but now I cannot actually get the elements I need for my app.
I am trying to get a number of elements with the "data-at" attribute. The weird thing is, a few elements with the "data-at" attribute are returned, but not the ones I am looking for. For whatever reason my code is not extracting all of the elements that share the "data-at" attribute on the web page.
This is the URL of the webpage I am scraping:
https://express.liatoyotaofcolonie.com/inventory?f=dealer.name%3ALia%20Toyota%20of%20Colonie&f=submodel%3ACamry&f=trim%3ALE&f=year%3A2020
The method containing the web-scraping code:
#Override
protected String doInBackground(Void... params) {
String title = "";
Document doc;
Log.d(TAG, queryString.toString());
try {
doc = Jsoup.connect(queryString.toString()).get();
Elements content = doc.select("[data-at]");
for (Element e: content) {
Log.d(TAG, e.text());
}
} catch (IOException e) {
Log.e(TAG, e.toString());
}
return title;
}
The results in Logcat
The element I want to retrieve
One of the elements that is actually being retrieved
This is because some of the content - including the one you are looking for - is created asyncronously and is not present in initial DOM (Javascript ;))
When you view the source of the page you will notice that there is only 17 data-at occurences, while running document.querySelector("[data-at]") 29 nodes are returned.
What you are able to get in the JSoup is static content of the page (initial DOM). You wont be able to fetch dynamically created content as you do not run required JS scripts.
In order to overcome this, you will have to either fetch and parse required resources manually (eg trace what AJAX calls are made by the browser) or use headless browser setup. Selenium + headless Chrome should be enough.
Letter option will allow you to scrape ANY posible web application, including SPA apps, which is not possible using plaing Jsoup.
I don't quite know what to do about this, but I'm going to try one more time... The "Problematic Lines" in your code are these:
doc = Jsoup.connect(queryString.toString()).get();
Elements content = doc.select("[data-at]");
It is the queryString that you have requested - the URL points to a page that contains quite a bit of script code. When you load up a browser and click the button (or menu-option) that reads: "View Source", the HTML you see is not the same exact HTML that is broadcast to and received by JSoup.
If the HTML that is broadcast contains any <SCRIPT TYPE="text/javascript"> ... </SCRIPT> in it (and the named URL in your question does), AND those <SCRIPT> tags are involved in the initial loading of the page, then JSoup will not know anything about it... It only parses what it receives, it cannot process any dynamic content.
There are four ways that I know of to get the "Post Script Loaded" version of the HTML from a dynamic web-page, and I will type them here, now. The first is likely the most popular method (in Java) that I have heard about on Stack Overflow:
Selenium This Answer will show how the tool can run Java-Script. These are some Selenium Docs. And then there is this page right here has a great "first class" for using the tool to retrieve post-script processed HTML. Again, there is no way JSoup can retrieve HTML that is sent to the browser by script (JS/AJAX/Angular/React) since it just a parser.
Puppeteer This requires running a language called Node.js Perhaps calling a simple Node.js program from Java could work, but it would be a "Two Language" solution. I've never used it. Here is an answer that shows getting, sort of, what you are trying to get... The HTML after the script.
WebView Android Java Programmers have a popular class called "WebView" (documented here), that I have recently been told about (yesterday ... but it has been out for years) that will execute script in a browser, and return the HTML. Here is an answer that shows "JavaScript Injection" to retrieve DOM Tree elements from a "WebView" instance (which is how I was told it was done)
Splash My favorite tool, which I don't think anyone has heard of, but has been the simplest for me... So there is an A.P.I. called the "Splash API". Here is their explanation for a "Java-Script Rendering Service." Since this one I have been using... I'll post a code snippet that shows how "Splash Tool" can retrieve post-script processed HTML below.
To run the Splash API (only if you have access to the docker loading program) ... You start a Splash Server as below. These two lines are typed into a GCP (Google Cloud Platform) Shell instance, and the server starts right up without any configurations:
Pull the image:
$ sudo docker pull scrapinghub/splash
Start the container:
$ sudo docker run -it -p 8050:8050 --rm scrapinghub/splash
In your code, just prepend the String to your URL's:
"http://localhost:8050/render.html?url="
So in your code, you would use the following command (instead), and the script would (more likely) load all the HTML Elements that you are not finding:
String SPLASH_URL = "http://localhost:8050/render.html?url=";
doc = Jsoup.connect(SPLASH_URL + queryString.toString()).get();
I am using Selenium web driver. I have below method to navigate to page.
public String navigate(String url){
driver = new FirefoxDriver();
driver.get(url);
return "Success";
}
Above code works fine if the server is up. some times server might be down then the page will not be loaded. Now how can I return "failure" string if the page is not loaded?
Thanks!
You can't directly test that a get() failed because the navigator always displays a page. You can either check that this page is a known error page, or check that you are not in the expected page.
First solution
It depends on the navigator. Chrome displays a special page when it can't find an url, firefox another page, etc.. You can test the title of those pages. For example firefox error page title is something like "Page load error" or "Problem loading page". Then all you have to do is something like :
if(driver.getTitle().equals("Problem loading page"))
return "failure";
Second solution
You must check the non-existence of an element that is present in every pages of your website (for example a logo or a home button). Say the ID of this element is "foo", you can do something like :
if(driver().findElements(By.id("foo")).isEmpty())
return "failure";
Dave Haeffner has a good solution for checking status codes using a proxy with the webdriver configuration.
http://elementalselenium.com/tips/17-retrieve-http-status-codes
The examples are in python, but the API is pretty close between python and java. I've not had much difficulty finding the java-analagous methods from the tips I've implemented myself.
That site has a lot of good information.
If using the Page Object Model, leveraging the LoadableComponentClass can help in determining whether the page is loaded or not either as a result of server down or something else.
Here's the link
https://code.google.com/p/selenium/wiki/LoadableComponent
I have encountered a small problem that I need some help on. The issue is that I wish to call a browser window which calls a html page. The html file opens in 3 different browsers so the code for that should be correct. The actual problem is that it brings up a page can't be displayed error message
Here is the code that gets the location
package org.error;
public class BrowserLocation {
private String test1 = "org\\error\\PatientNumberError.html";
public BrowserLocation() {
}
public String patientNumberAddress() {
return test1;
}
}
and here is the code that creates the browser component and calls the location of the html file.
Browser browser = new Browser(container, SWT.NONE);
browser.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_BLUE));
browser.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
browser.setUrl(browserLocation.patientNumberAddress());
browser.setBounds(25, 25, 315, 180);
Would it be possible to find the error of my ways?
setUrl require a URL so you need something like:
browser.setUrl(new File(path).toURI().toURL().toString());
Sorry for not getting back to you earlier.
Someone that I know who is a senior Java programmer told me the problem that I was having was a case of absolute address versus relative address.
The reason for this is that if I was reading and writing to a file, then I would be able to use a relative address. However If I'm interacting with a server which is the case here as eventually It could go on-line (If I had the money) it would need to be an absolute address.
As I am still learning Java programming this was a very specific and important lesson to learn. I hope this would help anybody else who has had this issue.
I am using the Java ScriptEngine to call a JS function from a backing bean under certain conditions in the program. The catch is that the JSF page is running in an iFrame. Although the iFrame is not the real problem at this stage, I want it to be able to browse to a new page. For this, I have used top.window.location and parent.location and they work on a button click to load the page out of the iFrame without a problem.
This is a sample of the code I'm using for this:
ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript");
se.eval("function someFunc(){parent.location = \"www.someurl.com\";}");
Invocable invocableJS = (Invocable) se;
invocableJS.invokeFunction("someFunc");
With parent.location and top.window.location I have read that they are called from the browser itsself, and are not JavaScript. So because of this, I get the following error:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "parent" is not defined. (<Unknown source>#1) in <Unknown source> at line number 1
It does exactly the same with document.getElementById("someComponent") and other similar. And it seems that the error remains with sun.org.mozilla..... in Chrome, IE, and FF all together.
So the question: How can I get the JS function to possibly use the parent.location? I imagine that I would need to check for the browser used and then import or call something from there depending on the browser, but I am not sure how I should go to work to do this. Any light that can possibly be shed on this problem will be very helpful.
Thanks in advance.
I have solved this problem, by checking for the cookies before the redirect in a Javascript method, and simply calling the JS method before the page loads using onload="someMethod();" in the body tag. Everything worked out fine, by using the parent.location to navigate to the new page. Tested in FF, Chrome and IE. Thus there was also no need for the ScriptEngine in this situation.
I have implemented small applet on the jsp page in web app which works although I need to set PARAM tag of applet with javascript vars defined on the jsp page. Is it possible? I can see its possible the other way around: to read in javascript variables from applet. I cant find solution for reverse action.
Have the JavaScript write the applet element. Or in this day and age, use deployJava.js to write the applet element, and assign the JS variable to one of the parts of the parameters.
If userFontSize is the custom variable, then E.G.
var parameters = {
fontSize:16,
jnlp_href:'java2d.jnlp'
}
..might become..
var parameters = {
fontSize:userFontSize,
jnlp_href:'java2d.jnlp'
}