Running an R script from Java - java

I've got a problem when I try to run a R script from Java Netbeans on Mac OS. I truly look for an answer of this problem on internet but nothing works.
I've used Rserve and Runtime.getRuntime().exec("Rscript myScript.R") but neither of them works with my program.
When I use Rserve, I run Rserve(args="--no-save") on R console and Rconnection.eval("\myscript.R") on Java program and when I execute it, the program continues running without any response, no errors either and no stops. In fact when I try to execute a more simply R script, like calculate the mean or something like that, it works, but when I try to coerce a data.frame in a xts/zoo time series or just to load xts/zoo library first in my script, the program doesn't stop running and does nothing.
On the other hand, when I try to execute "Runtime.getRuntime().exec("Rscript myScript.R")" like appears in other similar post, nothing happens. The program looks to execute the script but it doesn't give me any result although stops running at least. Maybe it is because of Mac OS and that I couldn't indicate to Java what is the Rscript or R.app path, I don't really know.
Thank you very much in advance and I wish you could help me.
Javi.
The file code is:
public void Rconnection () {
RConnection c=new RConnection();
System.out.println("INFO : Trying to Connect to R");
c.parseAndEval("source(\"/scriptname.R\")");
System.out.println("Greeting from R:" + result.asString());
c.close();
}
And the R script is:
EU.df <- read.csv("/myinput.csv",header=T)
EU.xts <- xts(EU.df[,2:5],seq(as.Date("1970-01-02"),len=nrow(EU.df),by="day"))
write.csv(EU.df, file = "/myoutputfile.csv",row.names=FALSE)
Maybe it's because of some problems with R libraries or because of MAC OS.

Have you tried using JRI? That might "block" unlike RServe and give you better messages.
For example:
REngine re = new JRIEngine(new String[] { "--no-save" }, new RCallback(), false);
re.parseAndEval("source(\"/scriptname.R\")");
re.close();

Related

Java start python process

I'm trying to start a python script via java and send the data via socket back to the java program.
My problem is that when I start the python script after the SocketServer is created with Runtime.getRuntime().exec("python3 ~/Documents/sensor/sensorADC.py");
no connection is established and no data is transmitted.
But when I start the script manually via CLI, everything works fine.
The timing of the program start shouldn't be the problem, because I already tried different ways and orders.
The java program is a javaFx application.
EDIT: tested in Linux
2nd Edit:
private void startPythonScript () {
try {
measureProcess = Runtime.getRuntime().exec("python3 ~/Documents/sensor/sensorADC.py"));
} catch (IOException e) {
e.printStackTrace();
}
}
What am I missing?
Thank you in advance
You're close, you can pass an array to the exec method, like this:
String[] cmd = { "python3", "sensorADC.py", "~/Documents/sensor/"};
Runtime.getRuntime().exec(cmd);
and it should work.
I "solved" it.
I compiled it with pyinstaller and now it works. Python seems to be the problem here.
But I don't know why....
For others I compiled it to an executable with pyinstaller --onefile sensor.py

Read and write to cmd in windows

I used system("java .....")to run a java app in cmd with VC++ code.
The java app will run a server in the cmd,it will output info in the console.And I can also enter commands to it just like run "dir" commands in cmd.
Now I want get all the output in my program and use C++ code to write commands sent to the java app.
But I found that the system() won't return until I stop the java app.It's reasonable.And how to avoid it?Use Thread ?
And the biggest problem is I don't know how to get the output and write commands,can anyone give me a method?
Thanks a lot!
P.S. The java app's code can't be changed.
--------------------------------------I have made progress--------------------
int main()
{
char psBuffer[256];
FILE* output = _popen("java xxxx.jar", "rt" );
if(output == NULL)
return 0;
while(fgets(psBuffer, 256, output))
{
printf(psBuffer);
}
if (feof( output))
{
printf( "\nProcess returned %d\n", _pclose( output ) );
}
else
{
printf( "Error: Failed to read the pipe to the end.\n");
}
system("pause");
return 0;
}
When I use "dir".It works perfect!But when I use java,psBuffer is always nothing,and the output of java app is normally.Is it pipe cannot redirect java's output?
I change my code and make some java command run perfect:
FILE* output = _popen("java -version 2>&1", "rt" );
But when it run that .jar,It failed.I read the .jar's code and find the output is create by java.util.logging.Logger.info().I'm not familiar with java. How dose the info() work in cmd?
Thanks many!
Finally, I found last code above is work correctly.But origin output of java app haven't been redirect .It will display normally,but buffer is correctly received the output I want.Anyway I solved my problems.Thanks everyone!!!
The MSDN article Creating a Child Process with Redirected Input and Output explains how you can do it. It is quite a lot of code to go through, but will allow you to do what you want, and give you full control over it.
On the other hand, using _popen is much easier, but you don't have as much control. Depends on your exact needs as to how much code you'll be writing :).

Runtime.getRuntime().exec strange behavior

I am trying to call a perl script from java runtime. It worked fine on my windows7 laptop with the following code,
try {
String cmdString= "c:\\perl64\\bin\\perl.exe c:\\perl64\\eg\\userinput.pl \""+arg1+"\" \""+arg2+"\"";
Process p = Runtime.getRuntime().exec(cmdString);
} catch(IOException e) {
System.out.println(e);
}
The perl script runs and produces what I expect (update database).
When I move the whole thing over to a remote CentOS server, it doesn't work anymore. The script is the same and the java code is,
try {
String cmdString= "/opt/lampp/bin/perl /home/support/scripts/userinput.pl \""+arg1+"\" \""+arg2+"\" > /tmp/userinput.log";
log(cmdString);
Process p = Runtime.getRuntime().exec(cmdString);
} catch(IOException e) {
System.out.println(e);
}
I added redirect to /tmp/userinput.log after I see the script is not working. But there is no log file created at all. I also added log to make sure this part of the java code did get executed, and indeed it did. I also tried to add "/bin/bash " in front of the comString and it didn't make a difference. However, when I run the cmdString directly on the remote server from command line, it works without problem.
Now, when I changed the cmdString to "touch /tmp/userinput.log", it does create the empty log file.
So I know the Runtime.getRuntime().exec(cmdString) command ran, and the cmdString works when entered on command line, and a simple "touch" command would work with this setup. But I am totally lost why the actual cmdString that calls the perl script doesn't work, and there is no message whatsoever to tell me what is wrong.
Can someone please help?
Frist, separate each parameter for the command and use the version of exec which takes a String[] (you won't have to worry about quoting issues). also, shell redirection won't work since java isn't executing a shell.

how to run cygwin script from java

I'm trying to run a bash script from a Java program I'm writing in windows. I've been trying to use the Runtime object to get a process to work, and my program compiles and runs without exceptions, but my simple test script, which just makes a directory, is not being executed.
Here's what I've got so far:
String cmmd[] = new String[3];
cmmd[0] = "C:\\cygwin\\bin\\bash.exe";
cmmd[1] = "cd C:/Users/pro-services/Desktop/projects/github/cygwin";
cmmd[2] = "bash TEST.sh";
Runtime rt= Runtime.getRuntime();
Process proc = rt.exec(cmmd);
This is basically a mix of different things I've found in forums around the net, but I guess I just don't really understand what is happening with the Process class (and I only have a basic idea about the Runtime class).
I also found this, and plugged my own stuff in where I thought it should go:
Runtime.getRuntime().exec(new String[]{"C:\\cygwin\\bin\\bash.exe",
"-c", "c:\\cygwin\\bin\\run.exe -p /bin bash C:\\Users\\pro-services\\Desktop\\projects\\github\\cygwin\\TEST.sh"},
new String[]{"PATH=/cygdrive/c/cygwin/bin"});
Here I'm not sure what the "-c" and "-p" strings represent, but I just went with it. At first it looked like I could just plug in the sequential commands that I want the Runtime/Process object to execute, in essence creating a "script" to run my script. But it now seems that there's more to it...
I'm just shooting in the dark at this point, and I have tried to understand the documentation but I'm lost. Any help would be appreciated. Thanks )))
Untested, but I would think:
cmmd[0] = "C:/cygwin/bin/bash.exe";
cmmd[1] = "-c";
cmmd[2] = "cd /cygdrive/c/Users/pro-services/Desktop/projects/github/cygwin && bash TEST.sh";

How do I launch a completely independent process from a Java program?

I am working on a program written in Java which, for some actions, launches external programs using user-configured command lines. Currently it uses Runtime.exec() and does not retain the Process reference (the launched programs are either a text editor or archive utility, so no need for the system in/out/err streams).
There is a minor problem with this though, in that when the Java program exits, it doesn't really quit until all the launched programs are exited.
I would greatly prefer it if the launched programs were completely independent of the JVM which launched them.
The target operating system is multiple, with Windows, Linux and Mac being the minimum, but any GUI system with a JVM is really what is desired (hence the user configurability of the actual command lines).
Does anyone know how to make the launched program execute completely independently of the JVM?
Edit in response to a comment
The launch code is as follows. The code may launch an editor positioned at a specific line and column, or it may launch an archive viewer. Quoted values in the configured command line are treated as ECMA-262 encoded, and are decoded and the quotes stripped to form the desired exec parameter.
The launch occurs on the EDT.
static Throwable launch(String cmd, File fil, int lin, int col) throws Throwable {
String frs[][]={
{ "$FILE$" ,fil.getAbsolutePath().replace('\\','/') },
{ "$LINE$" ,(lin>0 ? Integer.toString(lin) : "") },
{ "$COLUMN$",(col>0 ? Integer.toString(col) : "") },
};
String[] arr; // array of parsed tokens (exec(cmd) does not handle quoted values)
cmd=TextUtil.replace(cmd,frs,true,"$$","$");
arr=(String[])ArrayUtil.removeNulls(TextUtil.stringComponents(cmd,' ',-1,true,true,true));
for(int xa=0; xa<arr.length; xa++) {
if(TextUtil.isQuoted(arr[xa],true)) {
arr[xa]=TextDecode.ecma262(TextUtil.stripQuotes(arr[xa]));
}
}
log.println("Launching: "+cmd);
Runtime.getRuntime().exec(arr);
return null;
}
This appears to be happening only when the program is launched from my IDE. I am closing this question since the problem exists only in my development environment; it is not a problem in production. From the test program in one of the answers, and further testing I have conducted I am satisfied that it is not a problem that will be seen by any user of the program on any platform.
There is a parent child relation between your processes and you have to break that.
For Windows you can try:
Runtime.getRuntime().exec("cmd /c start editor.exe");
For Linux the process seem to run detached anyway, no nohup necessary.
I tried it with gvim, midori and acroread.
import java.io.IOException;
public class Exec {
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("/usr/bin/acroread");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished");
}
}
I think it is not possible to to it with Runtime.exec in a platform independent way.
for POSIX-Compatible system:
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "your command"}).waitFor();
I have some observations that may help other people facing similar issue.
When you use Runtime.getRuntime().exec() and then you ignore the java.lang.Process handle you get back (like in the code from original poster), there is a chance that the launched process may hang.
I have faced this issue in Windows environment and traced the problem to the stdout and stderr streams. If the launched application is writing to these streams, and the buffer for these stream fills up then the launched application may appear to hang when it tries to write to the streams. The solutions are:
Capture the Process handle and empty out the streams continually - but if you want to terminate the java application right after launching the process then this is not a feasible solution
Execute the process call as cmd /c <<process>> (this is only for Windows environment).
Suffix the process command and redirect the stdout and stderr streams to nul using 'command > nul 2>&1'
It may help if you post a test section of minimal code needed to reproduce the problem. I tested the following code on Windows and a Linux system.
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec(args[0]);
}
}
And tested with the following on Linux:
java -jar JustForTesting.jar /home/monceaux/Desktop/__TMP/test.sh
where test.sh looks like:
#!/bin/bash
ping -i 20 localhost
as well as this on Linux:
java -jar JustForTesting.jar gedit
And tested this on Windows:
java -jar JustForTesting.jar notepad.exe
All of these launched their intended programs, but the Java application had no problems exiting. I have the following versions of Sun's JVM as reported by java -version :
Windows: 1.6.0_13-b03
Linux: 1.6.0_10-b33
I have not had a chance to test on my Mac yet. Perhaps there is some interaction occuring with other code in your project that may not be clear. You may want to try this test app and see what the results are.
You want to launch the program in the background, and separate it from the parent. I'd consider nohup(1).
I suspect this would require a actual process fork. Basically, the C equivalent of what you want is:
pid_t id = fork();
if(id == 0)
system(command_line);
The problem is you can't do a fork() in pure Java. What I would do is:
Thread t = new Thread(new Runnable()
{
public void run()
{
try
{
Runtime.getRuntime().exec(command);
}
catch(IOException e)
{
// Handle error.
e.printStackTrace();
}
}
});
t.start();
That way the JVM still won't exit, but no GUI and only a limited memory footprint will remain.
I tried everything mentioned here but without success. Main parent Java process can't quit until the quit of subthread even with cmd /c start and redirecting streams tu nul.
Only one reliable solution for me is this:
try {
Runtime.getRuntime().exec("psexec -i cmd /c start cmd.cmd");
}
catch (Exception e) {
// handle it
}
I know that this is not clear, but this small utility from SysInternals is very helpful and proven. Here is the link.
One way I can think of is to use Runtime.addShutdownHook to register a thread that kills off all the processes (you'd need to retain the process objects somewhere of course).
The shutdown hook is only called when the JVM exits so it should work fine.
A little bit of a hack but effective.

Categories

Resources