2

I am trying to invoke some r code from within Java,pretty much like this:

private void makeMatrix() throws ScriptException {
    try {
        Runtime.getRuntime().exec(" Rscript firstscript.r");
        System.out.println("Script executed");
         } catch (IOException ex) {
       System.out.println("Exception");
       System.out.println(ex.getMessage());
    }

}

Well, I get the "Script executed" print.

My (well, not really mine, just to test) r-Code is fairly simple, pretty much just to see it works at all:

x=seq(0,2,by=0.01)
y=2*sin(2*pi*(x-1/4))
plot(x,y)

So, it should not do much more than plot a sinus.

However, should not there be some kind of popup where you can actually see the plot? because there is none. What am I doing wrong?

Edit: In response to the comments I got here I edited the r-file, adding:

jpeg('rplot.jpg')
plot(x,y)
dev.off()

to it.

However, If I then try to find rplot.jpg on my system it simply is not there.

5
  • 2
    You should probably explicitly declare a new device for the plot. On OSX the function is quartz, on Windows it is windows, on *nix I believe you want X11. It may make more sense to save the plot to a file using, e.g., png and then open the file from Java. Commented Sep 2, 2013 at 13:55
  • You also might want to take a look at rJava or Rcaller, the latter of which has explicit plotting support rather than manually invoking the R executable. Commented Sep 2, 2013 at 13:57
  • I had a look at both of them. The problem is, the jar has to be executable on windows AND linux, and I simply did not manage that with either. Commented Sep 2, 2013 at 14:05
  • 1
    Read (and implement) all the recommendations of When Runtime.exec() won't. That might solve the problem. If not, it should provide more information as to the reason it failed. Then ignore that it refers to exec and build the Process using a ProcessBuilder. Also break a String arg into String[] args to account for arguments which themselves contain spaces. Commented Sep 2, 2013 at 14:05
  • I would be happy enough if I got an error message or an exception, but how can it be that I get my print but the file I made in the rscript is not on my system? Commented Sep 2, 2013 at 14:21

2 Answers 2

2

You passed a relative directory to the jpeg function . This makes it relative to R's current working directory (the value returned by getwd).

Try printing this value to see where that is (on Windows, by default it's in "My Documents" for the current user)

print(getwd())

or passing an absolute path to jpeg.

jpeg('c:/rplot.jpg')
plot(x,y)
dev.off()

To get an absolute path, use pathological::standardize_path or R.utils::getAbsolutePath.

Sign up to request clarification or add additional context in comments.

2 Comments

That seems to be the Problem. However, how do I find this absolute path (without again using runtime.exec)? I suppose depending on the computer the user uses to open the jar, the script (bundled within the jar) will be in another folder too, won't it?
I have got a weird idea....I could actually as soon as the user starts the program create those r-scripts on the users computer. I guess that would work, but is this solution sensible?
1

You can wait for the Process (exec returns a Process object) to finish with waitFor, and check the exit value: it should be 0.

If it is not zero, you probably need to specify the path of the script.

public static void main( String[] args ) throws IOException, InterruptedException {
    Process p = Runtime.getRuntime().exec("Rscript /tmp/test.R");
    System.out.println("Started");
    p.waitFor();
    if( p.exitValue() != 0 )
        System.out.println("Something went wrong");
    else 
        System.out.println("Finished");
}

If the exit value is not 0, you can look at the stdout and stderr of the process, as suggested in Andrew's comment.

public static void main(String[] args) throws IOException, InterruptedException {
    System.out.println("test...");
    Process p = Runtime.getRuntime().exec(new String[] {
        "Rscript",
        "-e",
        "print(rnorm(5)))" // Intentional error, to produce an error message
    } );
    System.out.println("Started");

    String line = null;

    System.out.println("Stdout:");
    BufferedReader stdout = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
    while ( (line = stdout.readLine()) != null)
        System.out.println(line);

    System.out.println("Stderr:");
    BufferedReader stderr = new BufferedReader( new InputStreamReader( p.getErrorStream() ) );
    while ( (line = stderr.readLine()) != null)
        System.out.println(line);

    p.waitFor();
    if( p.exitValue() != 0 )
        System.out.println("Something went wrong, exit value=" + p.exitValue());
    else 
        System.out.println("Finished");
}

As mentionned in the comments, you need to explicitly open the device. Since it is closed when the script terminates, you also need to add a delay.

x11() # Open a device (also works on Windows)
plot( rnorm(10) )
Sys.sleep(10) # Wait 10 seconds

3 Comments

device refers to the type of graphical output, e.g., a window, a PNG file, a PDF file, etc. x11() and windows() are equivalent and open a window to display the plots. Check ?device.
Sometimes I could just..... I know there is no mistake in my r-skript because the exact same script works when used via command line. I know the absolute path is correkt and I STILL get started/sth wrong. Anyone have any idea?
Follow Andrew's advice, in the comments above, and print the standard output and standard error of the process: you will know what goes wrong. I have updated my answer accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.