How can java object from java code be passed to R script? - java

i'm curious is it possible to path java object (in any type (java/class/jar)) to REngine? till now i'm successfully executing an operation from java to R or vice versa. for example: i have my custom jar files which i'm using in RStudio, i wish to have same opportunity from java code as well.
above code is from RStudio
bellow code is from java
String javaVector="c(1,2,3,4,5)";
Rengine rengine = new Rengine(new String[]{"-no-save"}, false, null);
rengine.eval("rVector <-"+javaVector);
rengine.eval("meanVal=mean(rVector)");
double mean = rengine.eval("meanVal").asDouble();
REXP rexp = rengine.eval("meanVal");
System.out.println("Mean of given vector is <-"+mean);
rengine.eval(String.format("greeting <- '%s'", "Hello R World"));
REXP result = rengine.eval("greeting");
System.out.println("Greeting from R: "+result.asString());

i will answer my question. if someone is interested in answer. so to path java object from java code to R script you can do next: first pick the object you want to work with, for example :
public class RAccess{
static public Object getObject(String id){
return test;
}
static TestClass test = new TestClass();
}
public class TestClass{
String message;
public void setMessage(String value){
message = value;
}
}
after evaluate R script exactly like you do it in R console or RStudio, just put it in curly braces.
REXP x = re.eval(rCode3);
System.out.println(RAccess.test.message);
static String rCode3 =
"{ \n" +
"library(rJava) \n" +
".jinit() \n" +
"obj <- .jcall(\"jriTest/RAccess\", \"Ljava/lang/Object;\", \"getObject\", \"id\") \n" +
".jcall(obj, \"V\", \"setMessage\", \"hello from R\") \n" +
"}";
jriTest is a package name.

Related

R/Java code not working as expected

I am trying to print an R dataframe in Java but I am not sure of the datatype to be used for that.
I am getting a null value if I use STRING or STRING ARRAY. This is my code:
public static void main(String a[]) {
// Create an R vector in the form of a string.
String javaVector = "c(1,2,3,4,5)";
String name="c('a','b','c','d','e')";
// Start Rengine.
Rengine engine = new Rengine(new String[] { "--no-save" }, false, null);
// The vector that was created in JAVA context is stored in 'rVector' & 'names' which is a variable in R context.
engine.eval("rVector=" + javaVector);
engine.eval("names="+name);
//Calculate MEAN of vector using R syntax.
engine.eval("meanVal=mean(rVector)");
//Making a data frame in R.
engine.eval("data=data.frame(rVector,names)");
engine.eval("initial=paste('aakash','singhal')");
String myname = engine.eval("initial").asString();
//TRYING TO PRINT THE DATA FRAME (NOT SURE OF THE DATA TYPE)
REXP datafinal = engine.eval("data");
//RETRIEVE MEAN VALUE
double mean = engine.eval("meanVal").asDouble();
//Print output values
System.out.println("Mean of given vector is=" + mean);
System.out.println("Data table is :" + datafinal);
System.out.println(myname);
}
It prints-
Mean of given vector is=3.0
Data table is :[VECTOR ([REAL* (1.0, 2.0, 3.0, 4.0, 5.0)], [FACTOR {levels=("a","b","c","d","e"),ids=(0,1,2,3,4)}])]
aakash singhal
edit-
i used RXP so got this new result but not a table.

Include parameters for spring shell before method

I am working on a Spring Shell project. The tool is a command line tool to manipulate data in a database. There are commands like add user (which adds a record to a table in database). In order to execute any commands the user of the tool has to be connected to the database. I would like to be able to run this all in one line. The user of my tool should be able to write a command like the following.
--database connection string xyz --username abc --password mno add user --username bob --role AA_ADMIN --company Microsoft
Here the three parameters database connection string, username and password are required to run the add user command.
Below I have included some sample code it is from the spring shell reference docs
package commands;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.stereotype.Component;
#Component
public class UserManipulation implements CommandMarker {
private boolean simpleCommandExecuted = false;
#CliAvailabilityIndicator({"hw simple"})
public boolean isSimpleAvailable() {
//always available
return true;
}
#CliAvailabilityIndicator({"hw complex", "hw enum"})
public boolean isComplexAvailable() {
if (simpleCommandExecuted) {
return true;
} else {
return false;
}
}
#CliCommand(value = "hw simple", help = "Print a simple hello world message")
public String simple(
#CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final String message,
#CliOption(key = { "location" }, mandatory = false, help = "Where you are saying hello", specifiedDefaultValue="At work") final String location) {
simpleCommandExecuted = true;
return "Message = [" + message + "] Location = [" + location + "]";
}
#CliCommand(value = "hw complex", help = "Print a complex hello world message")
public String hello(
#CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final String message,
#CliOption(key = { "name1"}, mandatory = true, help = "Say hello to the first name") final String name1,
#CliOption(key = { "name2" }, mandatory = true, help = "Say hello to a second name") final String name2,
#CliOption(key = { "time" }, mandatory = false, specifiedDefaultValue="now", help = "When you are saying hello") final String time,
#CliOption(key = { "location" }, mandatory = false, help = "Where you are saying hello") final String location) {
return "Hello " + name1 + " and " + name2 + ". Your special message is " + message + ". time=[" + time + "] location=[" + location + "]";
}
#CliCommand(value = "hw enum", help = "Print a simple hello world message from an enumerated value")
public String eenum(
#CliOption(key = { "message" }, mandatory = true, help = "The hello world message") final MessageType message){
return "Hello. Your special enumerated message is " + message;
}
enum MessageType {
Type1("type1"),
Type2("type2"),
Type3("type3");
private String type;
private MessageType(String type){
this.type = type;
}
public String getType(){
return type;
}
}
}
So currently, hw simple is a command that is required to be executed before running hw complex or hw enum command. I do not want hw simple to be a command instead it the message parameter within the hw simple command should be a parameter that is required as a prerequisite to run hw complex or hw enum. So for example the command that I would like to run is.
--message hw complex --message abc --name1 def --name2 ghi --time 7:98 --location: Seattle
Does anyone know how to do this? If it is not possible to do this I would like to hear that or any alternative ideas if possible.
You have 2 options here:
either make those 3 additional parameters (database, username, password) parameters of each and every command that require them (note that in your particular example, you would need to rename one of those username parameters [the one to connect to the DB, or the one that represents the user to add] as you can't have 2 parameters with the same name obviously).
Use the #CliAvailabilityIndicator approach, similar to what is described in the example, where a first command (maybe named use or connect) first tests the connection with the 3 given parameters and stores them somewhere, so that any further "real" command (such as add user) can use those values.
Also note that you can actually use a combination of the two (i.e. use solution 2 to provide defaults, that may be overridden on a case by case basis by solution 1).
Lastly, please note that you'll never be able to have something like what you describe at the beginning of your question, as command names must be at the beginning and they can't contain -- (options do)

Opposing class cast exceptions in Java

I have an issue that is making me a little nuts. Here is the Java method.
public List<FtpActiveMerchantDTO> getFtpActiveMerchants() {
String sql = "select m.merchantId, ma.merchantAcctId, m.domain, f.fetchUrl, ma.acctActive, " +
"f.fieldDelimiter, f.feedType " +
"from merchant_account ma " +
"join merchant_ftp_account f on f.merchantAcctId = ma.merchantAcctId " +
"join merchant m on m.merchantAcctId = ma.merchantAcctId " +
"where f.fetchUrl is not null and ma.acctActive = 1";
Query query = currentSession().createSQLQuery(sql);
List<FtpActiveMerchantDTO> ftpActiveMerchantDTOList = new ArrayList<FtpActiveMerchantDTO>();
int merchantId, merchantAcctId;
byte acctActive;
for (Object rowObject : query.list()) {
Object[] row = (Object []) rowObject;
merchantId = ((BigDecimal) row[0]).intValue();
merchantAcctId = ((BigDecimal) row[1]).intValue();
acctActive = ((BigDecimal) row[4]).byteValue();
ftpActiveMerchantDTOList.add(new FtpActiveMerchantDTOBuilder().withMerchantId(merchantId)
.withMerchantAcctId(merchantAcctId).withDomain((String) row[2])
.withFetchUrl((String) row[3]).withAcctActive(acctActive > 0)
.withFieldDelimiter(row[5].toString()).withFeedType((String) row[6]).build());
}
return ftpActiveMerchantDTOList;
}
When I run my service with the code as it is shown here, I get
$ curl -X GET http://localhost:8080/merchants/ftpActive
{"responseData":null,"errorData":[{"code":500,"detailMessage":"","message":"java.lang.Byte cannot be cast to java.math.BigDecimal"}],"debugData":null}
The error is occurring at the line where acctActive is assigned. When I fix that line to this:
acctActive = (Byte) row[4];
then the service works as expected. But then my integration test (run from within IntelliJ)
private void whenFetchingFtpActiveMerchants() {
openAndBindSession();
ftpActiveMerchantDTOList = merchantDAO.getFtpActiveMerchants();
flushAndCloseSession();
}
fails, with this error:
java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Byte
at com.pronto.mpds.dal.MerchantDAOImpl.getFtpActiveMerchants(MerchantDAOImpl.java:143)
at com.pronto.mpds.dal.MerchantDAOIT.whenFetchingFtpActiveMerchants(MerchantDAOIT.java:96)
at com.pronto.mpds.dal.MerchantDAOIT.testFtpActiveMerchants(MerchantDAOIT.java:44)
...
The field in the db table is a tinyint(4). Why would the results from the db query be "expecting" to be a BigDecimal? Is there some kind of default data type? I know I am not configuring one anywhere.
At a first glance it looks like the database schema for the integration test is different from the production one, thus the type mismatch.

executing javascript code inside Android "java" application

I'm working on an Android app "native written in java"
and I'm getting a response from a server the response is a javascript function
I need to use this function to do some calculations inside my native java code.
any ideas how to do so.
sample response :
function logic_1(surveyString, responseValuesString) {
var survey = eval(surveyString);
var responseValues = eval(responseValuesString);
var target = new Object();
if (isChosen(128133225, responseValues)) {
target.id = 2;
}
if (! target.id) {
target.id = 2;
}
return target;
}
I've previously used Rhino successfully to execute JavaScript code on Android:
http://www.mozilla.org/rhino/
Here's an example of how to return values from a complex type:
String strFunction =
"function add(x,y){ " +
"return { " +
"id:x+y " +
"}; " +
"}";
Context context = Context.enter();
ScriptableObject scope = context.initStandardObjects();
context.evaluateString(scope, strFunction, "test", 1, null);
Function functionAdd = (Function)scope.get("add");
NativeObject untypedResult = (NativeObject)functionAdd.call(context, scope, scope, new Object[] { 1, 2 });
double id = (Double)untypedResult.get("id", untypedResult);
The important part is the last two lines, where we call the JavaScript function, treat the result as a NativeObject, and then retrieve the value of the 'id' property from that object.
Maybe you just need to use a JavaScript auto executing function like this:
(function(x, y){
var result;
result = x + y; // do some calculations
return result;
})(1 , 2); // you can set your parameters from Java
and 1, 2 are just two parameters from Java

Run piece of code contained in a String

I have a piece of Java code in a String.
String javaCode = "if(polishScreenHeight >= 200 && " +
"polishScreenHeight <= 235 && polishScreenWidth >= 220) { }";
Is it possible to convert this Java String to a Java statement and run it? Possibly using Java reflection?
As has already been suggested you can compile, save and run code on the fly using the Compiler API.
Another neat alternative would be to use beanshell. Beanshell is no longer actively developed, but I can vouch for it's reliability, I've used it successfully in multiple production projects.
Use BeanShell. There's a page on how to use it from Java.
Beanshell (as Boris suggested) is a way to "execute" java source code. But it looks like, you want to "execute" fragments that can interact with the compiled classes. Your example contains variabe names.
Reflection will definitly not help, because reflection targets classes ("classfiles").
You could try to define a complete class ("valid java source file"), compile it and load it (url classloader). Then you should be able to use the methods from that "live generated class". But once a class is loaded, you can't get rid of it (unload), so this will work only once (AFAIK).
As far as I know there is no simple way to do this.
However, in Java 6 onwards, you can compile source code for complete classes using javax.tools.Compiler. The compiled classes can then be loaded and executed. But I don't think this will achieve what you want.
Another way would be to execute your code as Groovy code, see this for an example.
you can use this code to run method from using this code
new Statement(Object target, String methodName, Object[] arguments).execute();
import java.beans.Statement;
public class HelloWorld {
public void method_name(String name) {
System.out.println(name);
}
public static void main(String[] args) throws Exception {
HelloWorld h = new HelloWorld();
new Statement(h, "method_name", new Object[]{"Hello world"}).execute();
}
}
Please reevaluate your design and this should be your last alternative.
You should validate the sanity of the String which will be executed to avoid future injection attack.
Now If you can have the String as JavaScript then below code should help,
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// below JS function is executed.
/*
* student object value will be provided by the program as the JSON String.
function checkStudentElgibility(student){
if(student.age >= 10 && student.currentGrade >= 5){
return true;
}
}
// student object value will be provided by the program as the JSON String
checkStudentElgibility(student);
*/
String studentJsonString = "{\n" +
" \"age\" : 10,\n" +
" \"currentGrade\" : 5\n" +
"}";
String javaScriptFunctionString = "function checkStudentElgibility(student){\n" +
" if(student.age >= 10 && student.currentGrade >= 5){\n" +
" return true;\n" +
" }\n" +
"}\n" +
"checkStudentElgibility(student);";
StringBuilder javaScriptString = new StringBuilder();
javaScriptString.append("student=");
javaScriptString.append(studentJsonString);
javaScriptString.append("\n");
javaScriptString.append(javaScriptFunctionString);
Object object = engine.eval(javaScriptString.toString());
System.out.println(object);
// You can also pass the object as follows,
// evaluate JavaScript code that defines an object with one method
engine.eval("var obj = new Object()");
engine.eval("obj.hello = function(name) { print('Hello, ' + name)
}");
// expose object defined in the script to the Java application
Object obj = engine.get("obj");
// create an Invocable object by casting the script engine object
Invocable inv = (Invocable) engine;
// invoke the method named "hello" on the object defined in the
// in js Object with "Script Method" as parameter
inv.invokeMethod(obj, "hello", "Script Method!");
// You can also use Java Objects as Java script object and you can also pass Objects as reference inside Java script function
String jsString = " var obj = new Object()\n" +
" var ArrayList = Java.type(\"java.util.ArrayList\");\n" +
" var customSizeArrayList = new ArrayList(16);\n" +
" obj.hello = function(name) { \n" +
" customSizeArrayList(name); \n" +
" print('Hello, ' + name) \n" +
" }";
}
}
Reference :
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html#A1147187
Try the JavaCompiler API.
Someone else answered this way better than I could, though:
Convert String to Code
Be careful before actually using something like this...
It is not Java, but as pgras has already suggested you could use GrooyScript like so :
Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);
String[] strings = new String[]{"World", "Groovy"};
shell.setVariable("args", strings);
String script = "return \"Hello \" + args[1]";
String value = (String) shell.evaluate(script);
System.out.println(value); // Hello Groovy

Categories

Resources