NoSuchMethodException when calling sendKeys on object of class org.openqa.selenium.remote.RemoteWebElement via R package rJava - r

I am trying to use the selenium webdriver API directly from R using rJava. I am subject to a fairly restrictive IT environment, so I can't access a remote driver currently (hence why I'm not currently using the Rselenium package), and I don't have either Chrome or Firefox availaible--just phantomjs. I am able to get this working okay from the Scala REPL. I used sbt to get all the dependenices--build.sbt contains, for example:
retrieveManaged := true
libraryDependencies ++= Seq (
"org.seleniumhq.selenium" % "selenium-java" % "3.9.1",
"com.codeborne" % "phantomjsdriver" % "1.4.4"
)
(Note that I have phantomjs installed as /usr/local/bin/phantomjs, and it is
version 2.1.1).
I then copied all the jar files to a single-level folder via cp jars/*/*/*.jar alljars/ containing the following:
animal-sniffer-annotations-1.14.jar httpcore-4.4.6.jar selenium-api-3.9.1.jar
byte-buddy-1.7.9.jar j2objc-annotations-1.1.jar selenium-chrome-driver-3.9.1.jar
checker-compat-qual-2.0.0.jar jline-2.14.5.jar selenium-edge-driver-3.9.1.jar
commons-codec-1.10.jar jsr305-1.3.9.jar selenium-firefox-driver-3.9.1.jar
commons-exec-1.3.jar okhttp-3.9.1.jar selenium-ie-driver-3.9.1.jar
commons-logging-1.2.jar okio-1.13.0.jar selenium-java-3.9.1.jar
error_prone_annotations-2.1.3.jar phantomjsdriver-1.4.4.jar selenium-opera-driver-3.9.1.jar
gson-2.8.2.jar scala-compiler-2.12.4.jar selenium-remote-driver-3.9.1.jar
guava-23.6-jre.jar scala-library-2.12.4.jar selenium-safari-driver-3.9.1.jar
httpclient-4.5.3.jar scala-reflect-2.12.4.jar selenium-support-3.9.1.jar
I start Scala via scala -cp "alljars/*" and can the do following:
val drv = new org.openqa.selenium.phantomjs.PhantomJSDriver
drv.get("https://www.google.com")
val q = drv.findElementByName("q")
q.sendKeys("rJava selenium")
q.submit
drv.getTitle
I think the following is roughly the same thing in R using rJava:
library(rJava)
.jinit()
jars <- dir("alljars", pattern = "*.jar", full.names = TRUE)
.jaddClassPath(jars)
drv <- .jnew('org/openqa/selenium/phantomjs/PhantomJSDriver')
drv$get("https://www.google.com")
q <- drv$findElementByName("q")
q$sendKeys("rJava selenium")
q$submit()
drv$getTitle()
This fails at the point q$sendKeys("rJava selenium") with the following error:
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, :
java.lang.NoSuchMethodException: No suitable method for the given parameters
In RStudio, if I type q$ and press TAB, sendKeys is definitely in the list of available methods. I tried to be explicit about this, and tried:
keys <- .jnew("java/lang/String", "rJava selenium")
keys <- .jcast(keys, "java/lang/CharSequence", check = TRUE)
q <- .jcast(q, "org/openqa/selenium/WebElement", check = TRUE)
.jcall(q, "V", "sendKeys", keys)
which resulted in the following error:
Error in .jcall(q, "V", "sendKeys", keys) :
method sendKeys with signature (Ljava/lang/CharSequence;)V not found
q has class org/openqa/selenium/remote/RemoteWebElement in R, and org/openqa/selenium/WebElement in Scala; but in both cases the return is void and the required argument is CharSequence according to the javadocs. I tried a few variations of this--java.lang.String instead of CharSequence, RemoteWebElement instead of WebElement, etc., but no joy.
I doubt this is a problem with rJava, but I'm stumped nonetheless and need help!

Oh good grief. I didn't know about .jmethods. Running this:
> .jmethods(q, "sendKeys")
[1] "public void org.openqa.selenium.remote.RemoteWebElement.sendKeys(java.lang.CharSequence[])"
So, basically, my problem was that I was passing String instead of String[]. That is, instead of:
q$sendKeys("rJava selenium")
I can use:
q$sendKeys(.jarray("rJava selenium"))
The more you know...

Related

RStudio fails when run through "Source as Local Job"

The code consists in two files:
caller.R:
a <- 1
source("s1.R", encoding = "UTF-8")
b <- fa()
s1.R:
fa <- function() {
a*2
}
This code runs smoothly when caller.R is sourced (Crtl+Shift+S) in RStudio IDE, providing the correct expected result b=2.
However, when caller.R is sourced through "Source as Local Job...", it throws an error (Portuguese), meaning that execution was interrupted because it was not able to find object 'a':
Error in fa() : objeto 'a' n�o encontrado
Calls: sourceWithProgress -> eval -> eval -> fa
Execu��o interrompida
I have tried all possible "Source as Local Job..." options combinations ("Run job with copy of global environments, etc.) without success.
What do I have to do to be able to run caller.R as a local job?
If you want to have it available in the same environment, you can try to use the local = TRUE
source("s1.R", encoding = "UTF-8", local = TRUE)

Why does lintr say "warning: no visible binding for global variable ‘Cloaked’"?

I'm sure that this is a misunderstanding of mine, since I'm not really an R programmer...
I have my code here: https://gist.github.com/bnsh/3839c4eb2c6b31e32c39ec312014b2b8
#! /usr/bin/env Rscript
library(R6)
Cloaked <- R6::R6Class("Cloaked",
public = list(
msg = function() {
return(paste(
"this code _works_, but lintr (https://github.com/jimhester/lintr)",
"complains that cloak_class.R:19:8: warning: no visible binding for",
"global variable ‘Cloaked’ when I try to use Cloaked within a",
"function. It's fine tho, if I use it _outside_ a function."
))
}
)
)
main <- function() {
c <- Cloaked$new()
c$msg()
}
main()
It works... But, lintr complains: "cloak_class.R:19:8: warning: no visible binding for global variable ‘Cloaked’"
Actually, it's not about a class, really, because this also complains:
#! /usr/bin/env Rscript
cloaked <- function() {
return(paste(
"this code _works_, but lintr (https://github.com/jimhester/lintr)",
"complains that cloak_function.R:13:3: warning: no visible global",
"function definition for ‘cloaked’ when I try to use cloaked within",
"a function. It's fine tho, if I use it _outside_ a function."
))
}
main <- function() {
cloaked()
}
main()
This code also runs, but lintr says:
cloak_function.R:13:3: warning: no visible global function definition for ‘cloaked’
Why? Short of doing something blunt instrument like # nolint start/# nolint end, what can I do to satisfy lintr?
Thanks!
I've just started with lintr and had the same problem. It appears to be a bug.
https://github.com/REditorSupport/atom-ide-r/issues/7
and the actual issue
https://github.com/jimhester/lintr/issues/27
The only workaround for now (short of fixing the bug within lintr) is to disable the object linter (which is not all that ideal as it will not catch genuine errors of this form). e.g.
with_defaults(object_usage_linter=NULL)
(I don't think the object usage linter is intended for scripts but rather packages - as far as I can tell, to work it will eval the entire script (!) to see what globals are defined. For a package where the R files are all function definitions that's fine, but for a script you don't really want to run the whole script every time you lint the file)
Using the linters argument in the lintr functions:
lint("myfile.R", linters = linters_with_defaults(
object_length_linter = NULL,
object_name_linter = NULL,
object_usage_linter = NULL))

tryCatch() Vs if else

I have recently started exploring R programming and have a very trivial doubt. I want to write a function which would try to load the required packages and install the same in case its not installed already.
I have written it using if else logic. My question is will it be more efficient if I use tryCatch()? Is there any other advantage than the ability to handle errors as it is not important to handle errors in this context.
Below is the code I am currently using:
Inst.Pkgs=function(){
if (!require(tm))
{install.packages("tm")
require(tm)}
if (!require(SnowballC))
{install.packages("SnowballC")
require(SnowballC)}
if (!require(wordcloud))
{install.packages("wordcloud")
require(wordcloud)}
if (!require(RWeka))
{install.packages("RWeka")
require(RWeka)}
if (!require(qdap))
{install.packages("qdap")
require(qdap)}
if (!require(timeDate))
{install.packages("timeDate")
require(timeDate)}
if (!require(googleVis))
{install.packages("googleVis")
require(googleVis)}
if (!require(rCharts))
{
if (!require(downloader))
{install.packages("downloader")
require(downloader)}
download("https://github.com/ramnathv/rCharts/archive/master.tar.gz", "rCharts.tar.gz")
install.packages("rCharts.tar.gz", repos = NULL, type = "source")
require(rCharts)
}
}
You can check at once and install missing packages.
# Definition of function out, the opposite of in
"%out%" <- function(x, table) match(x, table, nomatch = 0) == 0
# Storing target packages
pkgs <- c("tm", "SnowballC", "wordcloud", "RWeka", "qdap",
"timeDate", "googleVis")
# Finding which target packages are already installed using
# function installed.packages(). Names of packages are stored
# in the first column
idx <- pkgs %out% as.vector(installed.packages()[,1])
# Installing missing target packages
install.packages(pkgs[idx])
We can in fact use tryCatch for this. If the program tries to load a library that is not installed, it will throw an error - an error that can be caught and resolved with a function called by tryCatch().
Here's how I would do it:
needed_libs <- c("tm", "SnowballC", "wordcloud", "RWeka", "qdap", "timeDate", "googleVis")
install_missing <- function(lib){install.packages(lib,repos="https://cran.r-project.org/", dependencies = TRUE); library(lib, character.only = TRUE)}
for (lib in needed_libs) tryCatch(library(lib, character.only=TRUE), error = function(e) install_missing(lib))
This will install the missing packages and load the required libraries, as requested in the OP.

Building R package with Reference objects fails

I recently rewrote a package to use the new(er) R reference class objects. I've exported the three classes using export() in the NAMESPACE file so as far as I'm aware that should work. However when I test build the package I get an error at lazy loading stage:
** preparing package for lazy loading
Error in file(con, "rb") : invalid 'description' argument
ERROR: lazy loading failed for package ‘PACKAGE_NAME_HERE’
* removing ‘/Library/Frameworks/R.framework/Versions/3.0/Resources/library/PACKAGE_NAME_HERE’
I'm not sure what the problem is here. I don't know if it's relevant but the reference classes do store data on files in the tmp directory by having some fields set as accessor functions - I don't know if that's what s being complained about here when it says (con, "rb") which I guess is some connection thing. Does anybody have any ideas or advice for making sure reference classes get exported properly? My namespace is currently simple -
export(Main)
export(Mainseq)
export(Maintriplet)
Which are the three reference classes I exported by using #export tags in roxygen2.
What is it I'm doing (or not doing) that is throwing the lazy load error?
(ASIDE - I have no compiled code - all R, although the reference class methods do call some internal functions that are not exported, but these are supposed to be internal so I don't think I need to export them.
Thanks,
Ben.
EDIT:
My description file is as follows:
Package: HybRIDS
Type: Package
Title: Quick detection and dating of Recombinant Regions in DNA sequence data.
Version: 1.0
Date: 2013-03-13
Author: Ben J. Ward
Maintainer: Ben J. Ward <b.ward#uea.ac.uk>
Description: A simple R package for the quick detection and dating of Recombinant Regions in DNA sequence data.
License: GPL-2
Depends: ggplot2,grid,gridExtra,png,ape
I can't see what is wrong with this - the Depends are correct.
EDIT:
I've eliminated the first error with the description but I'm still getting the con error.
I think it's because the Mainseq class (which is nested in class Main) has some fields:
FullSequenceFile = "character",
FullSequence = function( value ) {
if( missing( value ) ){
as.character( read.dna( file = FullSequenceFile, format = "fasta", as.matrix = TRUE ) )
} else {
write.dna( value, file = FullSequenceFile, format = "fasta" )
}
},
InformativeSequenceFile = "character",
InformativeSequence = function( value ) {
if( missing( value ) ){
as.character( read.dna( file = InformativeSequenceFile, format = "fasta", as.matrix = TRUE ) )
} else {
write.dna( value, file = InformativeSequenceFile, format = "fasta" )
}
}
The idea being upon initialisation, the two character fields are filled with a path to a temp file in tmpdir, and when the variables are called or edited the files containing the variable data are read or written to. However it seems the variables are being accessed before this path is available because up package build the following happens:
** preparing package for lazy loading
Warning in file(con, "rb") :
cannot open file '/var/folders/kp/clkqvqn9739ffw2755zjwy74_skf_z/T//RtmpLB8ESC/FullSequenceaba52ac591f3': No such file or directory
Error in file(con, "rb") : cannot open the connection

rjava .jcall issue

I am currently working on developing an R package to integrate java code within R. However, I am having issues trying to properly call the java class methods. So far I have independently developed and compiled a java program into a class file and then packaged it up as a jar file. A sample of my code is as follows:
library(rJava)
.jinit()
.onLoad <- function(lib, pkg) {
pathToSdk <- paste(system.file(package = "mailViz") , "C:\\path\\to\\libs", sep="")
jarPaths <- c(paste(pathToSdk, "mail.jar", sep=""),
paste(pathToSdk, "mailReader.jar", sep="")
)
.jpackage(pkg, morePaths=jarPaths)
attach( javaImport( c("java.lang", "java.io", "java.mail", "java.util", "java.text")))
packageStartupMessage( paste( "mailViz loaded. The classpath is: ", paste(.jclassPath(), collapse=" " ) ) )
}
# get method arguments for the class
#.jmethods("mailReader","readEmailInfo")
z=.jcall("mailReader", "Ljava/lang/String;", "readEmailInfo", "username", "password")
However, when I execute the .jcall function I receive an error:
Error in .jcall("mailReader", "Ljava/lang/String;", "readEmailInfo", "username", :
method readEmailInfo with signature (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; not found
I tried multiple ways of changing the arguments but no luck. When I run .jmethods("mailReader") on the class file it lists all the methods available:
[2] "public java.lang.String mailReader.readEmailInfo(java.lang.String,java.lang.String)"
So, I am lost in how to make the proper call passing two arguments (username, password) to the java class file.
Any thoughts? Thanks in advance,
P
I have resolved this issue and the key here is to use the
mailReader = .jnew("mailReader")
call so that R has access to this class before making a call in the
z = .jcall(mailReader, "S", etc....)
By default, R has access to the static java methods.

Resources