Spotfire® Enterprise Runtime for R

To Pass Data Between Java and Spotfire Enterprise Runtime for R

TerrJava methods have limitations for evaluating expressions.

One such limitation is that the methods do not support sending data between Java and TERR, except for a single string value returned from evaluateToString. Simple values can be included in the expression string sent to TERR, and the string value returned from evaluateToString can include some data, but this is not reasonable for transferring large amounts of data.

The solution is to use methods for converting between TERR data objects and Java TerrData objects:

   public static void setVariable(String name, TerrData value)
   public static TerrData getVariable(String name)
   public static TerrData getVariable(String name, TerrData reuse)
  • The first method converts a TerrData object into a TERR data object, and assigns it to the specified global variable.
  • The second method retrieves the value of a global variable, and converts it to a TerrData object.
  • The third method retrieves a value, but also allows reusing the storage of an existing TerrData object, reducing Java object allocation.

TerrData is the superclass of several specific classes for representing particular types of TERR data objects, including TerrDouble, TerrString, TerrFactor, TerrList, and TerrDataFrame. Here is some example code showing how to start an embedded engine, construct a TerrDataFrame object in Java, send it to TERR, evaluate a linear model on the data and retrieve the coefficients of the model as another TerrData object.

TerrJava.startEngine();
TerrDataFrame df = new TerrDataFrame(new String[] { "x", "y" },
   new TerrData[] {
      new TerrDouble(new double[] { 1,2,3,4,5,6 }),
      new TerrDouble(new double[] { 1,4,9,16,25,36 })
   });
TerrJava.setVariable("df", df);
TerrJava.evaluateInteractive("df.mod <- lm(y~x, data=df)");
TerrJava.evaluateInteractive("df.coef <- df.mod$coefficients");
TerrData coef = TerrJava.getVariable("df.coef");
for (int i=0; i<coef.getLength(); i++) {
   System.out.println(coef.names[i]+" : "+((TerrDouble)coef).data[i]);
}
// this prints:
//   (Intercept) : -9.333333333333345
//   x : 7.000000000000002

Before the development of the TerrData object and these methods for reading and writing variables, the best way to transfer data between Java and TERR was to use the .JavaMethod function to call static Java methods that read or write values from static Java fields. However, this only supported reading and writing simple vectors of doubles, strings, and so on. Large and complex objects such as data.frames could be transferred by breaking them down into simple vectors that can be transferred via .JavaMethod.

This works, but the code is complex and unreliable and slow.

In one test, transferring a data frame with 40 columns of doubles as a TerrDataFrame was 100 times as fast as transferring the columns individually via .JavaMethod.