Use Jackcess from R using rJava - java

I am not much familiar with Java but I try to accomplish this task in R (my fav)!
There is this Java library called Jackcess. I want to connect to this library and open an MS Access 2003 .mdb file in it. Jackcess cookbook tells me the first step to using this library is this:
Database db = DatabaseBuilder.open(new File("mydb.mdb"));
or as #Gord suggests,
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
but I'm stuck at this very first step.
I have installed Java and rJava and set up everything about directories.
This is my code in R
library(rJava)
.jinit()
.jaddClassPath("java/jackcess-2.1.2.jar") # there I have put the downloaded jar file of Jackcess
# .jaddClassPath("java/commons-logging-1.2.jar") # this is the commons-logging class that Jackcess depends on, commented to replicate problem 2] in my question.
file.name <- "D:/63.mdb" # some data base .mdb file (containing only tables)
file <- .jnew("java/io/File",file.name)
dbbo <- .jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
[Edit: I found out I had two problems, one solved, one still not.]
up to this part everything is ok, but I have some problems from now on:
1] Correctly calling a method from Jackcess without signature mismatch, neither of these work:
dbbo <- .jcall(dbbo,"L<DatabaseBuilder>","setFile",file)
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder","setFile",file)
I get this error:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/DatabaseBuilder", :
method setFile with signature (Ljava/io/File;)Lcom/healthmarketscience/jackcess/DatabaseBuilder not found
well I found the answer to this step, I just needed a semicolon (;) at the end of class definition string.
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder;","setFile",file)
2] Calling the open method correctly, my first round of try:
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
and I get this error:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
I googled and found out that Jackcess depends on some library called commons-logging, so downloading and adding it to classpath solves THAT problem
3] Calling the open method correctly, my second round of try: with commons-logging in classpath
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
this gives me this error:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: Could not initialize class com.healthmarketscience.jackcess.impl.DatabaseImpl
Any Ideas for this error?
[NOTE]: some answers were suggested before my edits, so they may seem irrelevant now, but I have used them in the steps I explained above.

The following code shows an alternate approach in Java using the .setFile and .open methods of a "real" DatabaseBuilder object:
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
Try something similar in rJava and see if it works for you.
Edit re: updated question
You mentioned that you added Apache commons-logging to your CLASSPATH, but Jackcess also relies on Apache commons-lang v2.x (not v3.x), so try downloading that and including it in your CLASSPATH as well.

3 suggestions:
Include commons-lang-2.0.jar in your classPath, similarly to
rJava::.jaddClassPath("commons-lang-2.0.jar")
The easy way is to try calling with J() like so:
dbb <- rJava::.jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
dbjfile <- rJava::.jnew('java/io/File', "D:/63.mdb")
dbop <- rJava::J(dbb, "open", dbjfile)
For what it's worth, if you really want to do it the low-level way, this is one way to try:
dbop <- .jcall(
"RJavaTools"
, "Ljava/lang/Object;"
, "invokeMethod"
, .jcall(dbb, "Ljava/lang/Class;", "getClass")
, .jcast(dbb, "java/lang/Object")
, .jnew("java/lang/String", "open")
, .jarray(list(dbjfile), "java/lang/Object", dispatch = FALSE)
, .jarray(rJava:::._java_class_list(list(dbjfile)), "java/lang/Class", dispatch = FALSE)
, use.true.class = TRUE
, evalString = TRUE
, evalArray = FALSE
)

Related

OpenCV 3.0.0 FaceDetect Sample fails

I am trying to get OpenCV running i am using the following
sample code
I get the following Error line displayed:
OpenCV Error: Assertion failed (!empty()) in cv::CascadeClassifier::detectMultiScale, file ..\..\..\..\opencv\modules\objdetect\src\cascadedetect.cpp, line 1580
Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: ..\..\..\..\opencv\modules\objdetect\src\cascadedetect.cpp:1580: error: (-215) !empty() in function cv::CascadeClassifier::detectMultiScale
]
at org.opencv.objdetect.CascadeClassifier.detectMultiScale_1(Native Method)
at org.opencv.objdetect.CascadeClassifier.detectMultiScale(CascadeClassifier.java:176)
at org.maxbit.opencv.samples.DetectFaceDemo.run(SampleB.java:29)
at org.maxbit.opencv.samples.SampleB.main(SampleB.java:51)
Can any body tell me what that error means or how to debug this?
I also faced the problem. The problem is in the .getPath() return an absolute path of the format.
Eg: "/C:/Users/projects/FaceDetection/bin/com/face/detection/haarcascade_frontalface_alt.xml".
So change the code like this.
CascadeClassifier faceDecetor = new CascadeClassifier(FaceDetection.class.getResource("haarcascade_frontalface_alt.xml").getPath().substring(1));
This happens usually for two reasons.
Cascade classifier file lbpcascade_frontalface.xml not present at specified path.
Cascade classifier file is corrupted.
To get an error message instead of exception during runtime, try code sample as below. The CascadeClassifier constructor is silent, if it cannot load the cascade classifier XML. The onus is on the developer to call the empty() method and check if classifier is loaded correctly
CascadeClassifier cascade = new CascadeClassifier( CASCADE_CLASSIFIER_PATH );
if ( cascade.empty() ) {
//handler error here
}
Exception you got is from OpenCV native code assertion here.
I ran into this same error running on a Windows box. This sample runs on linux but not Windows.
The problem is in the .getPath() call after getResource() for both the xml file and the image.
The problem is that the URL.getPath() and the URL.getFile() both return an absolute path of the format "/c:/...".
The OpenCV routines choke on this it must be "c:/..." (no leading '/'). This seems like a bug in the early part of version 3.0.0?
I hope this helps, OpenCV for Java seems like a great tool ... but it is a bit frustrating when the examples don't work.
There is a problem with the latest openCV it doesn't work when you have spaces in your path so do this:
String s =CameraPanel.class.getResource("lbpcascade_frontalface.xml").getPath().substring(1);
String[] split = s.split("%20");
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < split.length-1; i++) {
stringBuilder.append(split[i]+" ");
}
stringBuilder.append(split[split.length-1]);
faceDetector = new CascadeClassifier(stringBuilder.toString());
I ran into the same issue: On windows, OpenCV chokes on both the prepended '\' and any whitespace in the path, as both Imad and Aung have noted. My solution is a bit shorter than Imad's:
Change this:
CascadeClassifier faceDecetor = new CascadeClassifier(
getClass().class.getResource("haarcascade_frontalface_alt.xml").getPath());
To this:
CascadeClassifier faceDecetor = new CascadeClassifier(
getClass().class.getResource("haarcascade_frontalface_alt.xml").getPath().substring(1).replaceAll("%20", " "));
For me the simplest solution was:
private void checkboxSelection(String classifierPath) {
// load the classifier(s)
faceCascade.load(classifierPath);
// Did it work?
if (faceCascade.empty()) {
// Try the full path
String resource = getClass().getResource(classifierPath).getPath();
// Discard leading / if present.
if ( resource.startsWith("/")) {
resource = resource.substring(1);
}
faceCascade.load(resource);
}
// now the video capture can start
cameraButton.setDisable(false);
}
I am using openCv 3.4.1
I think there's a bug in CascadeClassifier initializer.
In order to get rid of this error, I must call "load" once again. Hope this solution could help.
cascadeClassifier = new CascadeClassifier(mCascadeFile.getAbsolutePath());
cascadeClassifier.load(mCascadeFile.getAbsolutePath());
I faced problem on Mac (OSX) Java.
CameraFrame.class.getResource("haarcascade_frontalface_alt.xml").getPath().substring(1)
returned "Users/username/Desktop/JavaProjects/Camera/bin/haarcascade_frontalface_alt.xml".
whereas path should start with "/" therefore I appended "/".
face = new CascadeClassifier("/" +
CameraFrame.class.getResource("haarcascade_frontalface_alt.xml").getPath().substring(1));
It works OK now :)
I faced the same problem as well. It is just because the path you gave for 'haarcascade_frontalface_alt2.xml' might be incorrect of not proper. just copy the full path from file explorer and paste it. This solution works for me.
face_cascade = cv2.CascadeClassifier('C:/Users/xyz/FaceDetect/faceId/OpenCV-Python-Series-master/src/cascades/data/haarcascade_frontalface_alt2.xml')

Error when using xlsx package in write.xlsx

I am trying to save a file using write.xslx (when saving with write.csv some row got shift in more columns so I am trying to save the file as xlsx directly).
If I type this command:
write.xlsx (old.data, file ="Documents/new.xlsx", sheetName="Sheet1",col.names=TRUE, row.names=TRUE, append=FALSE)
or
write.xlsx (old.data, "Documents/new.xlsx", sheetName="Sheet1",col.names=TRUE, row.names=TRUE, append=FALSE)
I get this error:
Error in .jnew("org/apache/poi/xssf/usermodel/XSSFWorkbook") :
Java Exception <no description because toString() failed>.jnew("org/apache/poi/xssf/usermodel/XSSFWorkbook")<S4 object of class "jobjRef">
Can anyone help me sort it out?
I don't think that this question can easily be answered. Is <working_directory>/Documents writeable to you? Can you create the file
write.xlsx ( data.frame( a = 1:10, row.names = letters[ 1:10 ] ), "Documents/new.xlsx", sheetName="Sheet1",col.names=TRUE, row.names=TRUE, append=FALSE)
If this works, but with old.data it doesn't you have to provide a reproducible example.
However, I experienced every here and again weird problems with the xlsx package. From my experience XLConnect is much more robust and bug-free:
library("XLConnect")
writeWorksheetToFile( "Documents/newxlsx", old.data, "Sheet1", header=TRUE, rownames = "rownames.header" )
write_xlsx() from the writexl package works great for me and is way faster! It also works fine with tibbles and does not have the annoying errors or resctrictions from the xlsxpackage. It is also completely written in C so no Java, Perl or Rtools are required.
For more info see https://ropensci.org/technotes/2017/09/08/writexl-release/
I just had this same problem. I think there might be a bug with openXL but I love working with it. So I open and close R and then change the wd, saved the file exactly where the wd was and then I run the exact same code again. It worked.
Today I had that problem after deployment.
At this moment I didn't need to change package and stick to xlsx
I updated dplyr, xlsx, and the one that did the trick was updating rjava.
Since it was a conflict with java and xlsx calls it, I gave it a shot.
Hope this work for you too

java.lang.IllegalArgumentException: no JSON input found while trying google calendar Api in java

I downloaded google calendar api sample from http://code.google.com/p/google-api-java-client/source/browse/calendar-cmdline-sample/?repo=samples and created a project in eclipse.
Now when i try to run the project am getting java.lang.IllegalArgumentException: no JSON input found at this line
FileCredentialStore credentialStore = new FileCredentialStore(
new File(System.getProperty("user.home"), ".credentials/calendar.json"), JSON_FACTORY);
Have any of you tried this example? what is wrong here?
This error can be resolved by providing input to the .credentials/calendar.json file. If you manually provided the following entry in the calendar.json , it will work :
{
"installed": {
"client_id": "client_id",
"client_secret": "client_secret"
}
}
It seems to be the Windows problem which is not allowing to set writable permissions on calendar.json file . The method setWritable(boolean,boolean) is returning false and so is the cause of this problem. Still providing json input manually is not a perfect solutions but your application will work.
That may happen when your application executed before and it created empty .credentials/calendar.json file in you home dir. That may happen if you're running your application in Windows, cause FileCredentialStore tries to do:
file.setReadable(false, false)
and fails.
To solve it just remove calendar.json. Although you might have another error: [unable to set file permissions]
which I don't know how to solve yet.
Is that project having calendar.json resource file. Please share complete exception stack trace.
Seems some required configuration missed from calendar.json file

Using FileInputFormat.addInputPaths to recursively add HDFS path

I've got a HDFS structure something like
a/b/file1.gz
a/b/file2.gz
a/c/file3.gz
a/c/file4.gz
I'm using the classic pattern of
FileInputFormat.addInputPaths(conf, args[0]);
to set my input path for a java map reduce job.
This works fine if I specify args[0] as a/b but it fails if I specify just a (my intention being to process all 4 files)
the error being
Exception in thread "main" java.io.IOException: Not a file: hdfs://host:9000/user/hadoop/a
How do I recursively add everything under a ?
I must be missing something simple...
As Eitan Illuz mentioned here, in Hadoop 2.4.0 a mapreduce.input.fileinputformat.input.dir.recursive configuration property was introduced that when set to true instructs the input format to include files recursively.
In Java code it looks like this:
Configuration conf = new Configuration();
conf.setBoolean("mapreduce.input.fileinputformat.input.dir.recursive", true);
Job job = Job.getInstance(conf);
// etc.
I've been using this new property and find that it works well.
EDIT: Better yet, use this new method on FileInputFormat that achieves the same result:
Job job = Job.getInstance();
FileInputFormat.setInputDirRecursive(job, true);
This is a bug in the current version of Hadoop. Here is the JIRA for the same. It's still in open state. Either make the changes in the code and build the binaries or wait for it to be fixed in the coming releases. Processing of the files recursively can be turned on/off, check the patch attached to the JIRA for more details.

Problem loading R own created libraries in Java/JRI code

I created my own new R library (called "Media"). There is no problem when I try to load it with RGui, and I can call the functions defined in the new package. This is how I load it:
> library(Media)
But, I'm also trying to call that functions from Java/JRI code, and when I load the new R package, Java doesn't seem to find the pacakge, throwing the message "Error in library(Media) : object 'Media' not found"
This is my current code using JRI:
REXP rexpSetFolder = re.eval("setwd('C:/Users/Albert/Documents')");
REXP rexpFolder = re.eval("getwd()");
System.out.println(rexpFolder.asString());
REXP rexpLoad = re.eval("library(Media)"); // fails
It also fails without the 'setwd' command, and simple calls to existing R functions work fine. I'm using R 2.10 and the latest JRI 0.5-0 under Windows.
Any help would be appreciated.
Thank you very much.
Edit:
The parameter lib.loc seems to work, at least this sentence does not return an error:
library("Media", lib.loc = "c:/Users/Albert/Documents")
But after that, calling a function in the package with re.eval("myfunction()"); still fails, as the function is not properly found.
You can modify the library path - see ?.libPaths in R, you simply want to add your private library to the path. The GUI does that for you, but if you are outside it doesn't happen. For example:
re.eval(".libPaths('c:/users/foo/Documents/R')");
Then load your package.
Did you install the library properly first? You might want to try using the lib.loc parameter.
library("Media", lib.loc = "c:/Users/Albert/Documents")
My work-around was to copy the package from my personal library (%USERPROFILE%\Documents\R) to the global library (%R_HOME%\library).
It's not the best because this requires Administrator privileges which not all users will have...

Categories