Simple program to call R from Java using Eclipse and Rserve - java

My application must perform R operations such as:
m = matrix(sample(0:1,100, rep=T),ncol=10)
The results should be available to a Java application.
The Rserve package bridges R to other languages, since it acts as a TCP/IP server. I've read the website but don't know how to make the simplest application that can use Rserve.
What steps are required to make a simple Eclipse application that uses Rserve to execute R commands from Java?

There is a binary version of Rserve in the download section (www.rforge.net/Rserve/files/ I have version R 2.13 and Windows xp, so I need download Windows binary: Rserve_0.6-8.zip (541.3kb, updated: Wed Apr 18 07:00:45 2012)). Copy the file to the directory containing R.DLL. After installed Rserve from CRAN
install.packages("Rserve")
in R (I have RStudio - convenient thing: Download RStudio IDE).
started Rserve is from within R, just type
library(Rserve)
Rserve()
Сheck in Task Manager - Rserve.exe should be run.
After make a Java project in Eclipse, make a directory called lib under that project. Paste
2 jar here RserveEngine.jar and REngine.jar (www.rforge.net/Rserve/files/). Do not forget to add this jars in Properties your java-project. In new class code:
import org.rosuda.REngine.*;
import org.rosuda.REngine.Rserve.*;
public class rserveuseClass {
public static void main(String[] args) throws RserveException {
try {
RConnection c = new RConnection();// make a new local connection on default port (6311)
double d[] = c.eval("rnorm(10)").asDoubles();
org.rosuda.REngine.REXP x0 = c.eval("R.version.string");
System.out.println(x0.asString());
} catch (REngineException e) {
//manipulation
}
}
}

Here are some more detailed instructions for creating an RServe project from scratch:
First Install and get Rserve running in R.
Install R
Add package RServe from CRAN.
In R type: install.packages("Rserve")
For remote access:
Create file: /etc/Rserv.conf
Add the following to Rserv.conf
workdir /tmp/Rserv
remote enable
auth required
plaintext disable
port 6311
maxsendbuf 0 (size in kB, 0 means unlimited use)
In R: run the following commands
library(Rserve)
For Windows:
Rserve()
For Mac:
Rserve(args="--no-save")
An instance of Rserve is now running on localhost port 6311.
Next Create an Rserve project (i'm using eclipse)
For this I'm going to use eclipse:
Download RserveEngine.jar and REngine.jar from here.
Create a java project in eclipse.
Create a lib folder under your project directory. (same level as your src folder)
Copy RserveEngine.jar and REngine.jar into the lib folder.
Add jars to build path: Instructions
Add a package then a main class: call it something like HelloWorldApp.
Add this code to the class
package com.sti.ai;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
public class HelloWorldApp {
public static void main(String[] args) throws RserveException, REXPMismatchException, FileNotFoundException, IOException {
RConnection c = new RConnection("<host/ip>", 6311);
if(c.isConnected()) {
System.out.println("Connected to RServe.");
if(c.needLogin()) {
System.out.println("Providing Login");
c.login("username", "password");
}
REXP x;
System.out.println("Reading script...");
File file = new File("<file location>");
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
for(String line; (line = br.readLine()) != null; ) {
System.out.println(line);
x = c.eval(line); // evaluates line in R
System.out.println(x); // prints result
}
}
} else {
System.out.println("Rserve could not connect");
}
c.close();
System.out.println("Session Closed");
}
}
Finally, run HelloWorldApp.java
For those who are using Maven
REngine
<dependency>
<groupId>org.nuiton.thirdparty</groupId>
<artifactId>REngine</artifactId>
<version>1.7-3</version>
</dependency>
RServe
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>Rserve</artifactId>
<version>1.8.1</version>
</dependency>

Quick ones, trying to separate tasks:
Rserve can be installed by itself. Start there.
Rserve has sample clients. Try to the Java samples to work.
From there, write your new program.
Eclipse is entirely optional. You do not have to use it. If this is one more step to learn, consider skipping it. Once 1 to 3 are fine, learn how to express build dependencies in Eclipse.

There are two ways to call R from Java - JRI and RServe. This is a plugin that will help you setup RJava on windows. If you are looking for a more production level solution then Rserve serves a better purpose. This example shows how to run a sample RServe program. If you are using RServe then run your command in eval function
REXP m = c.eval("matrix(sample(0:1,100, rep=T),ncol=10)")
There are some default datastructures that you can use to convert m (REXP).

Related

How to Obtain Java Thread Dump in JRE 1.8.0_144

I've been trying to find ways to obtain the Thread Dump from a Java Application on my Windows server running on jre 1.8.0_144.
Non of the monitoring utilities like jcmd jstack jconsole are available in either the bin or lib folders of the Java environment directory.
I have come across several applications online that claim to perform the same task but haven't found a reliable one yet.
Changing the JRE version, unfortunately, has been ruled out as an option
There is a way if you are running with tools.jar available, that is running from a JDK instead of a stock JRE. However given that you don't have the jcmd, jstack, jconsole tools available, this is unlikely.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
// You need to add tools.jar to the classpath to get this
import com.sun.tools.attach.VirtualMachine;
public class Main {
public static void main(String[] args) throws Exception {
// Here you will need to use JNI or JNA to get the current process' PID
// because the JRE version you are using doesn't have any other way.
long pid = getCurrentPid(); // you need to create this method
VirtualMachine vm = VirtualMachine.attach(""+pid);
Method m = vm.getClass().getMethod("remoteDataDump", Object[].class);
InputStream in = (InputStream) m.invoke(vm, new Object[] { new Object[0] } ); // awkward due to nested var-args
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(in))) {
buffer.lines().forEach(System.out::println);
}
}
}

WEKA API LibSVM ClassPath not found

I'm trying to use LibSVM with Weka API.
My System:
Win7
Weka 3.7.12
LibSVM 1.0.6 (Installed via Package Manager)
My Code:
import java.io.File;
import java.util.Random;
import javax.swing.JOptionPane;
import weka.classifiers.Evaluation;
import weka.classifiers.functions.LibSVM;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
public class LibSVMClassifier {
// Method to build a SVM classifier with a given data file
public static double buildModel(File dataSet){
// new instance of LibSVM
LibSVM clsSVM = new LibSVM();
try {
Instances data = DataSource.read(dataSet.getAbsolutePath());
// Sets the label feature
data.setClassIndex(data.numAttributes()-1);
String opts = "-S 0 -K 0 -D 3 -G 0.0 -R 0.0 -N 0.5 -M 40.0 -C 1.0 -E 0.0010 -P 0.1";
// set the options for the algorithm
clsSVM.setOptions(weka.core.Utils.splitOptions(opts));
Evaluation eval = new Evaluation(data);
eval.crossValidateModel(clsSVM, data, 2, new Random(1));
return eval.pctIncorrect();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
e.printStackTrace();
}
return 100;
}
}
Code is called from here:
double error = LibSVMClassifier.buildModel(trainDataSet);
My problem:
When I run my code and first use my J48 classifier (code at the end) and afterwards the LibSVM everything works fine.
If I run the LibSVM first I get the following error:
java.lang.Exception: libsvm classes not in CLASSPATH!
weka.classifiers.functions.LibSVM.buildClassifier(LibSVM.java:1636)
weka.classifiers.evaluation.Evaluation.crossValidateModel(Evaluation.java:764)
weka.classifiers.Evaluation.crossValidateModel(Evaluation.java:374)
totd.BuildModel.LibSVMClassifier.buildModel(LibSVMClassifier.java:34)
totd.GUI.Gui$5.actionPerformed(Gui.java:215)
If I export the project to a runable jar and use it on another machine without weka installed the error will also occur if I run the J48 algorithm first. So no matter what I can't use the LibSVM on another machine.
I have read through all the other questions regarding this problem, but there was no solution for me. In order to prevent answers that will not help me here some things that wont work:
Explanation how to add a library to the project: Ive used the package
manager from weka to install LibSVM and I added the resulting jar
file for LIBSVM AS WELL AS weka jar file to my build path
Explanation how to use LibSVM with weka gui: I want to use LibSVM together with the weka api in a programmatic way, it already works in weka gui I dont need that!!!
Explanation how to change the classpath for your system: I want to export my project to a jar file and run it on any system I dont have access to the system class path
Possible solutions that I didnt understand but that I think might work if someone explains in detail:
https://stackoverflow.com/a/13766120/5006670 In this post it is mentioned to obtain the .class files from SVNLib (I suppose SVM?) and adding these to my buildpath. I do not understand which files he is speaking about and how I would compile the make file if I were to find it. But it sounds like my error message.
https://weka.wikispaces.com/LibSVM talks about using reflection. Im not sure how this is used
using a batch file to start the jar file together with the LibSVM.jar with -classpath command
J48 Code:
import java.io.File;
import javax.swing.JOptionPane;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
import weka.classifiers.trees.J48;
import weka.classifiers.Evaluation;
import java.util.Random;
public class J48Classifier {
// Method to build a J48 classifier with a given data file
public static double buildModel(File dataSet){
// new instance of tree
J48 clsJ48 = new J48();
try {
Instances data = DataSource.read(dataSet.getAbsolutePath());
// Sets the label feature
data.setClassIndex(data.numAttributes()-1);
String[] options = new String[1];
// unpruned tree
options[0] = "-U";
// set the options for the algorithm
clsJ48.setOptions(options);
Evaluation eval = new Evaluation(data);
eval.crossValidateModel(clsJ48, data, 2, new Random(1));
return eval.pctIncorrect();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
e.printStackTrace();
}
return 100;
}
}
My build path
Okay, steps how magic work:
Search for hours and fail
Ask on a forum
Try for 5 more minutes and succeed
SOLUTION:
There are 2! LibSVM.jar files in the weka package folder and you need BOTH.
So for all that try to use LibSVM using weka package manager go to:
(HOME)\wekafiles\packages\LibSVM
There you find the first FIRST LibSVM.jar
now go to:
(HOME)\wekafiles\packages\LibSVM\lib
here you will find libsvm.jar
ADD BOTH OF THESE JAR TO YOUR BUILD PATH!!!
Greetings

Using GraphVIZ Native library from Java

I am trying to use graphviz native library from java.I am able to compile the program in Eclipse. But getting exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no gv in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1681)
at java.lang.Runtime.loadLibrary0(Runtime.java:840)
at java.lang.System.loadLibrary(System.java:1047)
at org.graphviz.test.Test.<clinit>(Test.java:12)
Could not find the main class: org.graphviz.test.Test. Program will exit.
Here is my code(copied from somewhere of course):
package org.graphviz.test;
import org.graphviz.internal.SWIGTYPE_p_Agedge_t;
import org.graphviz.internal.SWIGTYPE_p_Agnode_t;
import org.graphviz.internal.SWIGTYPE_p_Agraph_t;
import org.graphviz.internal.gv;
public class Test {
static {
System.loadLibrary("gv");
}
public static void main(String[] args) {
SWIGTYPE_p_Agraph_t g, sg;
SWIGTYPE_p_Agnode_t n, m;
SWIGTYPE_p_Agedge_t e;
g = gv.digraph("G");
System.out.println(gv.setv(g,"aaa","xxx"));
System.out.println(gv.getv(g,"aaa"));
sg = gv.graph(g,"SG");
n = gv.node(g,"hello");
System.out.println(gv.getv(n,"label"));
System.out.println(gv.setv(n,"aaa","xxx"));
System.out.println(gv.getv(n,"aaa"));
m = gv.node(g,"world");
System.out.println(gv.getv(m,"aaa"));
e = gv.edge(n,m);
System.out.println(gv.setv(e,"aaa","xxx"));
System.out.println(gv.getv(e,"aaa"));
gv.rm(e);
gv.rm(n);
gv.rm(m);
gv.rm(g);
g = gv.readstring("digraph G {a->b}");
gv.rm(g);
g = gv.read("hello.gv");
gv.layout(g,"dot");
gv.render(g,"png","hello.png");
gv.rm(g);
}
}
I have pointed the library correctly, but at runtime getting UnsatisfiedLinkError. Any one ever tried using the graphviz native library?Please let me know how to configure JNI.
I believe you're problem is that you are trying to import from gv, but you aren't specifying what you want to import. It's kind of like if you were to just write ---
import org.graphviz.internal;
Instead, try importing a specific library from the gv library. For example, if you want a directed graph, you would probably do something like this ---
import org.graphviz.internal.gv.digraph;
Take a look at the following document and see if it helps at all. It might give you a better idea of where gv comes from and how you can import the methods associated with it.
http://www.graphviz.org/pdf/gv.3java.pdf
Get graphviz-java
Make sure you have graphviz-java installed. For MacPorts this should work like this:
sudo port install graphviz +java
This actually failed for me on the first try and complained about swig-java, this fixed it:
sudo port install swig-java
sudo port install graphviz +java
Now the library is installed under /opt/local/lib/graphviz/java for me, search for libgv.jnilib if you don't find it there.
Setup class path
I compiled in Eclipse, for that I added /opt/local/lib/graphviz/java to the build path as an external class folder.
Compile
This is a simple example that writes an image. Note that System.loadLibrary("gv") must happen before calling anything in graphviz.
import org.graphviz.SWIGTYPE_p_Agedge_t;
import org.graphviz.SWIGTYPE_p_Agnode_t;
import org.graphviz.SWIGTYPE_p_Agraph_t;
import org.graphviz.gv;
public class Main {
static {
System.loadLibrary("gv");
}
public static void main(String[] args) {
SWIGTYPE_p_Agraph_t g = gv.digraph("G");
SWIGTYPE_p_Agnode_t n = gv.node(g, "hello");
SWIGTYPE_p_Agnode_t m = gv.node(g, "world");
SWIGTYPE_p_Agedge_t e = gv.edge(n, m);
gv.layout(g, "dot");
gv.render(g, "png", "hello.png");
}
}
Run
Run with java.library.path=/opt/local/lib/graphviz/java, e.g. -Djava.library.path=/opt/local/lib/graphviz/java as VM arguments in an Eclipse run configuration.

Java and R integration

I am trying to build a java project which contains R codes. Main logic behind that is I want to automate the data structuring and data analysis with in a same project. Partially I am being able to do that. I connected R to Java and my R codes are running well. I did all my set up in the local machine and its giving me all output as I need. As data set is big I am trying to run this on amazon server. But when I am shifting it to server, my project is not working properly. Its not being able to execute library(XLConnect), library(rJava). When ever I am calling this two libraries in my java project it's crashing. Independently in R codes are running and giving me output. What I can I for that, and how to fix thus error. Please help me out from this.
My java codes is
import java.io.InputStreamReader;
import java.io.Reader;
public class TestRMain {
public static void main(String[] arg)throws Exception{
ProcessBuilder broker = new ProcessBuilder("R.exe","--file=E:\\New\\Modified_Best_Config.R");
Process runBroker = broker.start();
Reader reader = new InputStreamReader(runBroker.getInputStream());
int ch;
while((ch = reader.read())!= -1)
System.out.print((char)ch);
reader.close();
runBroker.waitFor();
System.out.println("Execution complete");
}
}
And in the Modified_Best_Config.R I have written these codes
library('ClustOfVar');
library("doBy");
library(XLConnect)
#library(rJava)
#library(xlsx)
path="E:/New/";
############Importing and reading the excel files into R##############
Automated_R <- loadWorkbook("E:/New/Option_Mix_Calculation1.xlsx")
sheet1 <- readWorksheet(Automated_R, sheet = "Current Output")
sheet2 <- readWorksheet(Automated_R, sheet = "Actual Sales monthly")
sheet3 <- readWorksheet(Automated_R, sheet = "Differences")
#####################Importing raw Data###############################
optionData<- read.csv(paste(path,"ModifiedStructureNewBestConfig1.csv",sep=""),head=TRUE,sep=",");
nrow(optionData)
optionDemand=sapply(split(optionData,optionData$Trim),trimSplit);
optionDemand1=t(optionDemand[c(-1,-2),]);
optionDemand1
################Calculating the equipment Demand####################
optionDemand2<-t(optionDemand2[c(-1,0)]);
Rownames <- as.data.frame(row.names(optionDemand2))
writeWorksheet(Automated_R,Rownames, sheet = "Current Output", startRow = 21, startCol = 1)
writeWorksheet(Automated_R,optionDemand2, sheet = "Current Output", startRow = 21, startCol = 2)
saveWorkbook(Automated_R)
But java is stopping its operation after these line.
library("doBy");
Whole set of codes are running on nicely on my local machine. But whenever I am trying to run this on amazon server it's not running. Individually in R this code is running on server. I have couple of more R codes which are running with out any error. What can I do for that, please help me out.
Thanks for updating your question with some example code. I cannot completely replicate your circumstances because I presently don't have immediate access to Amazon EC2, and I don't know the specific type of instance you are using. But here a couple of suggestions for de-bugging your issue, which I have a hunch is being caused by a missing package.
1. Try to install the offending packages via your R script
At the very beginning of your R script, before you try to load any packages, insert the following:
install.packages(c("XLConnect", "rJava"))
If your instance includes a specified CRAN mirror (essentially, the online repository where R will first look to download the package source code from), this should install the packages in the same repo where your other packages are kept on your server. Then, either library or require should load your packages.
(sidenote: rJava is actually a dependency of XLConnect, so it will automatically load anyway if you only specify library(XLConnect))
2. If the above does not work, try installing the packages via the command line
This is essentially what #Ben was suggesting with his comment. Alternatively, see perhaps this link, which deals with a similar problem with a different package. If you can, in terminal on the server, I would try entering the following three commands:
sudo add-apt-repository ppa:marutter/rrutter
sudo apt-get update
sudo apt-get install r-cran-XLConnect
In my experience this has been a good go-to repo when I can't seem to find a package I need to install. But you may or may not have permission to install packages on your server instance.

Error occurred during initialization of VM java/lang/NoClassDefFoundError: java/lang/ref/FinalReference

I am a student in IT and i'm still learning java and android developement.
i'm testing with some udp traffic between a desktop app and a android app.
but every time I try to run the android app it gives this error message :
Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/ref/FinalReference
this is the code of the UDP client
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import android.app.Activity;
import android.util.Log;
public class Client extends Activity {
public static void main(String[] args) throws IOException {
try {
int bufSize = 4096;
int port = 12345;
DatagramSocket sock = new DatagramSocket(port);
sock.setReceiveBufferSize(bufSize);
byte[] buffer = new byte[bufSize];
while (true) {
DatagramPacket p = new DatagramPacket(buffer, bufSize);
sock.receive(p);
Log.d("Client", "Received: " + new String(p.getData()));
}
}finally{}
}
}
the code may contain some parts that may not work, but it gives no errors.
I just want to know why the VM won't start.
grtz
Looks like your Java SDK wasn't installed correctly.
Try and see if java is in your system PATH. You can try javac -version command on your terminal. If that produces the same error, then you need to add it to your path.
Also, this guy seems to have had the same problem as yours, check that link:
I found the solution to my error.
I used the android project like a java app, with a main function. this gave the problem of no being able to deploy the vm.
the code hade to be in the oncreate function of the activity instead of in a main function.
thanks for the help.
grtz
Try these steps in order on UBUNTU 12.04LTS:
chmod 755 eclipse.desktop
Check javac -version
Find the correct path for javac
Find correct path for JDK
Add using vi the following lines in the top of file /opt/eclipse/eclipse.ini :
-vm
/usr/bin /*if javac is in /usr/bin */
/usr/share/jdk7/usr/java/jdk1.7.0_25/bin /*if this is the path for JDK */

Categories

Resources