R Programming Through Java

Articles —> R Programming Through Java

Accessing the statistical power of R within java applications can sometimes be a powerful technique. Although one can attempt to automate R via Runtime.exec, doing so can be exception prone and can limit how one accesses R to single calls. Rserve is a great alternative to facilitate pluging R into java applications.

Rserve Configuration

The Rserve webpage gives details for how one goes about installing and starting the server. Briefly, one must first download the Rserve package in R, followed by starting the R server by loading the library and calling the Rserve() function, or running Rserve as a daemon via the command line using the 'R CMD Rserve' syntax.

The Java Client

From Java, accessing Rserve requires adding the appropriate Rserve jars to the classpath, instantiating an instance of RConnection, then performing evaluations - the code of which is evaluated with R, the result of which is passed back to the java application.


import org.rosuda.REngine.REXP;

import org.rosuda.REngine.Rserve.*;



public class RTest {





	public static void main(String[] args) throws Exception{



		RConnection c = null;

		try{

			c = new RConnection();

			REXP x = c.eval("R.version.string");

			System.out.println(x.asString());

		}catch(Exception e){

			e.printStackTrace();

		}finally{

			if ( c != null ){

				try{

					c.close();

				}finally{}

			}

		}



	}

}

The above code is a simple demonstration for accessing Rserve running on the localhost computer through R, simply printing out the version of R. To run on a remote server, simply pass the name or IP address of the server running Rserve to the RConnection constructor. Rserve runs as a single instance of R, allowing variables within R to be reused, negating the need to pass the same data twice.




import org.rosuda.REngine.REXP;

import org.rosuda.REngine.Rserve.*;



/**

 * Demonstration for accessing R via java

 *

 */

public class RTest {





	public static void main(String[] args) throws Exception{

		double[] myvalues = {1.0, 1.5, 2.2, 0.5, 0.9, 1.12};

		RConnection c = null;

		try{

			c = new RConnection();

			c.assign("myvalues", myvalues);

			REXP x = c.eval("mean(myvalues)");

			System.out.println(x.asDouble());

			x = c.eval("sd(myvalues)");

			System.out.println(x.asDouble());

		}catch(Exception e){

			e.printStackTrace();

		}finally{

			if ( c != null ){

				try{

					c.close();

				}finally{}

			}

		}



	}

}

Here, the java code passes an array of doubles to R, the calculates the mean and standard deviation of the values. Of course, more complex calculations can be made, as well as accessing installed packages.

Local and Remote R Instances

Rserve can run locally or on a remote server accessible by multiple clients. Pass the name or IP address of the server to the RConnection constructot to access a remote server. Of course one should take into consideration network traffic and optimization when passing large amounts of data.

Multithreading

When accessing R through Rserve from a java application, often one must take into account the communication and computation delay. For instance, to prevent a user interface from freezing up, perform Rserve communications in a different thread or via a class such as a SwingWorker (if using swing). Alternative, if computation is long and can be parallelized the R library Snow can be utilized.

Disadvantages

  • Networking - Rserve operates through networks, thus if transferring large volumes of data the overhead may be too much. Often, the solution may transfer data through other means of store the data on the server locally to the R server.
  • R Graph and Charting via Java - Because Rserve runs via a programmatic interface, accessing the graphical power of R is more complex. Two options can be to a) download the results and plot in java using an API such as JFreeChart or b) plot in R and save the plot as a file (for instance, PDF or jpg) - then read the file from java (the latter is a bit more complex should the Rserver be a remote server).
  • Timing - R does not provide a value insofar as progress completion. As a result, when using Rserve via a graphical user interface one must use indeterminate progress bars rather than letting a user know how much of the process has completed.



Comments

  • Shahinur Rahman   -   April, 22, 2014

    Hi,

    I am trying to use your sample code R Programming Through Java. But I am getting an error like

    "org.rosuda.REngine.Rserve.RserveException: Cannot connect: Connection refused: connect"

    Please help me to solve.

  • Greg Cope   -   April, 22, 2014

    The R server is not allowing connections. This could be due to a) a firewall on the server refusing connections on the given port or b) Rserve is not configured to accept connections from the client. Fixing the former is OS dependent. Fixing the latter requires one to properly configure Rserve on startup - this is explained in detail on the Rserve webpage.

  • Maxim Nikitin   -   May, 18, 2014

    Fix your code - you are trying to close rConnection twice: in try block and at the end - in finally block. It's enough to keep only c.close() in finally block

  • Greg Cope   -   May, 18, 2014

    Thanks Maxim Nikitin - fixed

  • Jason Donnald   -   July, 10, 2014

    I am using this command below:

    REXP res = c.parseAndEval("try(median(ftch$t31001400),silent=TRUE)");

    System.out.println(res.asDouble());

    But I am getting error as:

    org.rosuda.REngine.REXPMismatchException: attempt to access org.rosuda.REngine.REXPString as double

    I am unable to figure out how to resolve this error.Any idea?

  • Greg Cope   -   July, 10, 2014

    It suggests the returned value is a string - what value is returned if you try to access this way? What is the data contained within your list?

  • Jason Donnald   -   July, 10, 2014

    The value returned by the median function of R should be double. But apparently parseAndEval() or eval() function returns some string. Do they always return that only? As per you above code your REXP stored value is getting converted into double but when I am trying to do that it is throwing the mismatch exception. Do you have any idea why is it happening. If you want I can post my complete code here.

  • Greg Cope   -   July, 10, 2014

    What is the value of the String? Is an exception being thrown within R? If so, the returned value may be an empty String (if silent=TRUE) and thus interpreted by RServe as a String.

    My advice to debug would be to set silent=TRUE, then print out the returned value as a String (if there is an exception, the String should contain the message. For instance, the following example which will throw an exception when using median...

    RConnection rc = ...

    rc.eval("l = list(test=c(1.234, 4312), test2 = c(\"test\"))");

    REXP p = rc.eval("try(median(l),silent=FALSE)"); System.out.println(p.asString());

    will print out:

    Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) :

    'x' must be atomic

    Any attempt to call p.asDouble() will result throw a REXPMismatchException

  • Jasson Donnald   -   July, 18, 2014

    How do you print/access individual records from a set of records returned by a R statement through Java. Like you could pass a SQL query to R from Java through dbSendQuery()inside parseAndEval(), say "select * from table 1", This will return a set of records back to 'REXP res' variable in java(I think it is of type REXPGenericVector) . Now how can I print/access each of these records individually in Java? If I do System.out.println(res) then it prints some random format string.

  • Greg Cope   -   July, 18, 2014

    I recommend testing all the R code from within R - one needs to fetch the data first. Doing all of this is beyond the scope of this article (and difficult to communicate from within the comments section), so I recommend trying an online forum more geared towards things such as this (eg stackoverflow)

  • Paris nicolas   -   September, 13, 2014

    Hello, about plot, they are an other way, using R function "readBin()" you 'll find a demo in the source R package Rserve 1.8.1 in the R/src/java/test/plotDemo.java

    Works great !

  • Greg Cope   -   September, 13, 2014

    @Paris nicolas, excellent info. Thanks for the tip!

  • MAhesh Thenge   -   February, 10, 2015

    I am not able to connect R througth JAVA using JRI API

    This is my code

    import org.rosuda.REngine.REXP;

    import org.rosuda.REngine.Rserve.RConnection;

    import org.rosuda.REngine.Rserve.RserveException;

    public class test

    {

    public static void main (String[] args)

    {

    try {

    RConnection c=new RConnection();

    REXP x = c.eval("Sys.time()");

    } catch (RserveException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    and it giving following errors

    Exception in thread "main" org.rosuda.REngine.Rserve.RserveException: Cannot connect: Connection refused: connect

    at org.rosuda.REngine.Rserve.RConnection.(RConnection.java:88)

    at org.rosuda.REngine.Rserve.RConnection.(RConnection.java:60)

    at org.rosuda.REngine.Rserve.RConnection.(RConnection.java:44)

    at test.main(test.java:15)

  • Greg Cope   -   February, 10, 2015

    @MAhesh, JRI and RServer are different. This article pertains to RServe, and in this context make sure RServe is running on the appropriate host (I presume in this case you are using localhost), and make sure the firewall allows connections to be made through the appropriate port. See: http://rforge.net/Rserve/

  • Sunit Patnaik   -   April, 23, 2015

    I'm trying to pass integer values to the assign() function and apparently it asks me to supply only Strings. Is there any alternative?

  • Greg Cope   -   April, 23, 2015

    @Sunit Patnaik, then pass a String value of the Integer.

  • Parveen Verma   -   May, 19, 2015

    @Maheh... Problem is not with your code. Problem might be because of your Rserve is not running. For that to work you have to start Rserve which you can start from R console using commands -

    library(Rserve)

    Rserve()

    For more info watch - https://www.rforge.net/Rserve/doc.html#start

Back to Articles


© 2008-2017 Greg Cope