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
Related
Ive got my Parse SDK set up, and the "Hello World!" function runs fine. Im trying to now send two int's (i1 & i2) and return the sum. What I need to know is:
1) How to send variables
2) How to receive them. As changing the HashMap from HashMap<String,Object> to HashMap<Integer,Object> gives an error
ParseCloud function (js)
Parse.Cloud.define("add", function(request,response)
{
var intA = 1;
var intB = 2;
var intC = intA + intB;
//var s = "Hello Add!";
//response.success(s);
response.success(intC);
});
Android method, doAddition()
s1 = et1.getText().toString();
s2 = et2.getText().toString();
i1 = Integer.parseInt(s1);
i2 = Integer.parseInt(s2);
ParseCloud.callFunctionInBackground("add", new HashMap<Integer, Object>(), new FunctionCallback<Integer>()
{
#Override
public void done(Integer sum, ParseException e)
{
s3 = sum.toString();
et3.setText(s3);
}
});
The above Android-method gives an error:
The method callFunctionInBackground(String, Map<String,?>,
FunctionCallback<T>) in the type ParseCloud is not applicable for the
arguments (String, HashMap<Integer,Object>, new
FunctionCallback<Integer>(){})
set your args correctly before the call to your Cloudfunction ( as proper javascript parms ) then get them in the cloud funct...
var mathArg1 = request.params.arg1;
var mathArg2 = request.params.arg2;
create a result field in JS...
var mathResult = mathArg1 + mathArg2;
return the result to client as JSON ( get used to this in cloud interfaces! )
success: function(user) {
response.success(mathResult.toJSON());
},
I have the unenviable task of editing a 2000 line javascript file inorder to maintain and add some new feature to a web app written in JSP, Json-RPC, jQuery and Java. I do not possess any deeper knowledge of jQuery and Json-RPC except basic Javascript knowledge and the original developer is not there anymore.
There is a JS function which accepts a few params, and calls a Json-RPC and here I am getting the error
arg 1 could not unmarshal
Can someone please tell me what this error means?
Here is my code
function distributeQuantityNew(pReportId, pDecimalPlaces, pRun) {
try {
alert('distributeQuantityNew: ' + pReportId + ', ' + pDecimalPlaces + ', ' + pRun);
var fieldValue = $("#distribution_quantity_" + pReportId).val();
if (fieldValue.length == 0) {
showErrorDialog(resourceBundleMap["error.no.distribution.quantity"]);
return;
} else {
$("#distribution_quantity_" + pReportId).val("");
}
var affectedRowIds = [];
var rows = $("#tableBody_" + pReportId + " tr:visible").has("input[type=text]").filter(function(index) {
var voucherType = this.cells[getVoucherColumnIndex()].innerHTML;
if ((voucherType == 'TRANSFER_CS') || (voucherType == 'PAYOUT_CS') || (voucherType == 'SOURCE_BON') || (voucherType == 'PAYOUT_BON')) {
return false;
}
affectedRowIds.push(parseInt(this.id.split("_")[3]));
return true;
}
);
var affectedReportRows = $.extend(true, {}, foreignReportMap[pReportId]);
$.each(affectedReportRows.map, function(i, row) {
if ($.inArray(row.partnerReportBillNr, affectedRowIds) == -1) {
delete affectedReportRows.map["row_" + row.partnerReportBillNr];
}
});
var report = getLoadedReportByRunId(pReportId);
var productType = report.partnerProductType;
SessionManager.extend();
var resultRows = jsonrpc.foreignReportObject.distributeQuantity(affectedReportRows, fieldValue, pDecimalPlaces, pRun);
alert('back after RPC');
$.each(resultRows.map, function(i, row) {
foreignReportMap[pReportId].map["row_" + row.partnerReportBillNr] = row;
updateForeignReportRow(row, true, productType);
});
updateSummaryRow(pReportId);
toggleApproveAllLink(pReportId);
sortForeignReportTable(pReportId, true);
} catch (e) {
handleError("Failed to distribute quantity: ", e);
}
}
I have peppered it with alerts so that I know whether RPC call was succesful, but I get the error arg 1 could not unmarshal before that from the catch block. Thanks for any hints
OK, got it solved. The first parameter to the remote function is expecting a list of Map<String, SomeBO>. SomeBO is a bean with several BigDecimals. I had another JS function which had set the values passed into the Map. This function was setting a BigNumber where I had a setter of String only. I wish the error I had gotten back from JSON unmarshaller was a bit more descriptive...Below is the code where I added .toString() to solve the issue
foreignReportMap[pReportId].map["row_" + pRowId].clientQuantity = clientQuantity.toString();
foreignReportMap[pReportId].map["row_" + pRowId].totalClientQuantity = totalClientQuantity.toString();
I have a project as follows: Several photos are taken from a mobile, the photos are saved in a web system, which in turn displays the photos on google earth that is inside it. I've read many articles but all of them were using fetchKml, one good article that i've read was using php, but using fetchKml. I dont know if its possible using parseKml instead. Anyway, I'm not sure how to do this with the kml, so it looks tike this:
My Class KMLGenerator()
public static String getKMLFromObra (List<Obra> obraFotos) {
StringBuffer sb = new StringBuffer();
sb.append("<?xml version='1.0' encoding='UTF-8'?>");
sb.append("<kml xmlns='http://www.opengis.net/kml/2.2' " +
"xmlns:gx='http://www.google.com/kml/ext/2.2' " +
"xmlns:kml='http://www.opengis.net/kml/2.2' " +
"xmlns:atom='http://www.w3.org/2005/Atom'> ");
if (obraFotos != null && obraFotos.size() > 0) {
for (Obra o : obraFotos) {
for (Local local : o.getLocais()) {
sb.append("<Document>");
sb.append("<name>" + local.getName() + "</name>");
sb.append("<Style id='defaultStyles'>");
sb.append("<IconStyle>");
sb.append("<scale>1.1</scale>");
sb.append("<Icon>");
sb.append("<href>" + "http://localhost:8080/ConstruMobilFoto/lib/img/fotoIcon.png" + "</href>");
sb.append("</Icon>");
sb.append("</IconStyle>");
sb.append("</Style>");
sb.append("<Placemark>");
sb.append("<name>" + "Foto" + "</name>");
sb.append("<styleUrl>" + "#defaultStyles"+ "</styleUrl>");
sb.append("<altitudeMode>" + "relativeToGround" + "</altitudeMode>");
sb.append("<Point>");
sb.append("<altitudeMode>relativeToGround</altitudeMode>");
sb.append("<coordinates>" + local.getLongitude() + "," + local.getLatitude() + "," + 50</coordinates>");
sb.append("</Point>");
sb.append("<Link>");
sb.append("<href>" + local.getFotos() + "</href>");
sb.append("</Link>");
sb.append("</Placemark>");
sb.append("</Document>");
sb.append("</kml>");
return sb.toString();
}
}
}
return null;
}
I have a dwr function in my jsp that invokes this method, got its String results and make the parse like this:
Class PainelEarth()
#SuppressWarnings("static-access")
public String geraFotosObra (int idObra) throws Exception {
try {
List<Obra> obraFotos = obraBusiness.getObraLatLong(new Obra(idObra));
return new KMLGenerator().getKMLFromObra(obraFotos);
} catch (Exception e) {
log.error(e.getLocalizedMessage(), e);
return null;
}
}
and in my jsp page
function initCB(instance) {
// other codes
showPics(ge);
}
function showPics(ge) {
PainelEarthAjax.geraFotosObra({
callback : function(kmlString) {
var kmlObject = ge.parseKml(kmlString);
ge.getFeatures().appendChild(kmlObject);
}
});
return null;
}
Any help will be welcome!!
In your code if you look at the signature of the method geraFotosObra you can see it takes a single int parameter idObra.
public String geraFotosObra (int idObra) throws Exception { ...
Yet when you call the method in your jsp you are passing an an object literal containing a callback function.
PainelEarthAjax.geraFotosObra({
callback : function(kmlString) { ...
As it is I don't see how the kml is generated, unless perhaps geraFotosObra is an overloaded method? Also even if it was generated, as is, I don't see how the callback function that you pass in place of an id is ever called - why for example would kmlString be the result of the call to geraFotosObra?
// How is this called, what sets kmlString!?
callback : function(kmlString) {
var kmlObject = ge.parseKml(kmlString);
ge.getFeatures().appendChild(kmlObject);
}
All in all the code you posted is a wee bit confusing, so sorry if I have missed something...I think you have possibly copy and pasted some code from a fetchKml example and the asynchronous callbacks used with that method have confused you slightly.
Anyhow, based on what you have posted, you should be passing an int id to the geraFotosObra method, getting the string result and then parsing it in the plug-in.
Something like the following makes sense. Replace the showPics function with the following.
function showPics(ge) {
var kmlString = PainelEarthAjax.geraFotosObra(1); // or something?
var kmlObject = ge.parseKml(kmlString);
ge.getFeatures().appendChild(kmlObject);
}
If i have a js object such as below stored in a js file
var _sampleProcessor = {
process: function(data){
...
}
}
How would i use Apache Rhino to call the process function?
// sb holds the contents of the js file
Context cx = Context.enter();
Scriptable scope = cx.initStandardObjects();
cx.evaluateString(scope, sb.toString(), "Test", 1, null);
Object processor = scope.get("sampleProcessor ", scope);
if (processor == Scriptable.NOT_FOUND) {
System.out.println("processor is not defined.");
}
Getting to the root of the object is easy, but how do i traverse the object tree to get at the process function property
Thanks in advance
This sample does a few things. Pulls out the sampleProcessor as your example does, and also pulls out the process property and executes that function.
It also shows adding Java objects into the scope so they can be used - the System.out object in the example.
package grimbo.test.rhino;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
public class InvokeFunction {
public static void main(String[] args) {
String sb = "var sampleProcessor = {\n" + " process: function(data){\n out.println(0); return 1+1;\n }\n" + "}";
Context cx = Context.enter();
Scriptable scope = cx.initStandardObjects();
Object out = Context.javaToJS(System.out, scope);
ScriptableObject.putProperty(scope, "out", out);
cx.evaluateString(scope, sb.toString(), "Test", 1, null);
// get the sampleProcessor object as a Scriptable
Scriptable processor = (Scriptable) scope.get("sampleProcessor", scope);
System.out.println(processor);
// get the process function as a Function object
Function processFunction = (Function) processor.get("process", processor);
System.out.println(processFunction);
// execute the process function
Object ob = cx.evaluateString(scope, "sampleProcessor.process()", "Execute process", 1, null);
System.out.println(ob);
}
}
Output:
[object Object]
org.mozilla.javascript.gen.Test_1#b169f8
0.0
2
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