I'm working on getting (JavaScript) scripting to work in Java.
I have a program in JavaScript, defined in my Java program (along with instances of all the necessary script engine related things) like so:
static ScriptEngineManager engineManager = new ScriptEngineManager();
static ScriptEngine jsengine = engineManager.getEngineByName("js");
static Invocable jsinvoke = (Invocable) jsengine;
static String program =
"//importPackage(javax.swing);" +
"function myMethod(x, y) {" +
"return x+y;" +
"}";
At the start of the program I do call this, which works without complaint:
try {
jsengine.eval(program);
} catch(ScriptException e) {e.printStackTrace();}
Then, I call myMethod with this:
try {
jsinvoke.invokeFunction("myMethod", x, y);
} catch(ScriptException se) {
se.printStackTrace();
}
catch(NoSuchMethodException nsme) {
nsme.printStackTrace();
}
It gives the error java.lang.NoSuchMethodException: no such method: myMethod. It clearly exists in the JavaScript, so what did I do wrong?
The commented code seems to be the source of problem, since it comments out even the method name myMethod
//importPackage(javax.swing);
remove this line and rerun your code
If you want to preserve your comment then instead of single line comment (//) use multi line comment (/**/)
Related
My application uses https://app.bandwidth.com/ for receiving incoming calls. I have an api to handle the incoming calls which record the calls when the call is not answered(This recording is treated as a voice mail).
if (eventType.equalsIgnoreCase(EventType.ANSWER.toString())) {
Timestamp callStartTime = new Timestamp(TimeUtil.now().getTime());
incomingCall.setCallTime(callStartTime);
callStatus = transferCall(callId, incomingCall.getVoiceForwardNumber(), 1);
}
else if (eventType.equalsIgnoreCase(EventType.TIMEOUT.toString())) {
voiceMailIntro(callId);
}
else if (eventType.equalsIgnoreCase(EventType.SPEAK.toString()) && PLAYBACK_STOP.equalsIgnoreCase(callState)) {
recordVoiceMail(callId);
}
else if (eventType.equalsIgnoreCase(EventType.RECORDING.toString()) &&
state.equalsIgnoreCase(BandwidthCallStatus.COMPLETE.toString())) {
createTranscription(recordingId);
}
else if (eventType.equalsIgnoreCase(EventType.TRANSCRIPTION.toString()) && status.equalsIgnoreCase(BandwidthCallStatus.COMPLETED.toString())) {
incomingCall.setVoiceMail(text);
}
This is the code for recording call
private void recordVoiceMail(String callId) {
BandwidthClient client = BandwidthClient.getInstance();
client.setCredentials(bandwidthUserId, bandwidthApiToken, bandwidthApiSecret);
try {
Call call = Call.get(client, callId);
call.recordingOn();
} catch (Exception e) {
log.error("An exception occurred while recording voice mail : " +
e.getMessage(), e);
}
}
Now i need to transcribe these vocie mails.
From documentation i got methods in python, js, c#, ruby etc. to transcribe the recordings using the recordings.
For example in js,
client.Recording.createTranscription(recordingId, function(err, transcription){});
I searched every where, but i couldn't find any method in java for that.
Can any one help me if you know ?
Anyway, as I see, you need that link for java doc.
And here you can follow to java sdk located on Github.
And, also, you can find some more information about transcriptions API here which you are looking for.
First of all, why do you need that? Perhaps, you do not need that.
As I find, you can't do transcribe with POJO, but you can do something like that.
If you want to do that, you can make it with
public void transcribeOn() throws Exception {
final List<Recording> list = Recording.list(0, 5);
if (!list.isEmpty()) {
final Recording recording = Recording.get(list.get(0).getId());
System.out.println("\nRecording by Id");
System.out.println(recording);
final String recordingUri = mockClient.getUserResourceUri(BandwidthConstants.RECORDINGS_URI_PATH);
client.post(recordingUri + "/" + list.get(0).getId() + "/transcriptions", null);
final JSONObject jsonObject = call.toJSONObject(client.get(recordingUri, null));
call.updateProperties(jsonObject);
}
}
I'm not sure it works correctly, but I hope it put you on correct way
I've come across an issue with LuaJ not accepting an LuaValue as an argument when the Java code specifically asks for an LuaValue.
public void registerEvent(LuaValue id, String event, String priority,
LuaValue callback)
{
if(!(id instanceof LuaTable))
{
throw new RuntimeException("id must be an LuaTable");
}
EventDispatcher.addHandler(id, event, priority, callback);
}
Ideally, this would allow the code in Lua to simply read like so...
function main(this)
this.modName="Some Mod"
this.lastX = 0
hg.both.registerEvent(this, "inputcapturedevent", "last", eventRun)
end
function eventRun(this, event)
this.lastX += event.getX()
end
Sadly, this simple gives an error that it expects userdata, but got a table.
org.luaj.vm2.LuaError: script:4 bad argument: userdata expected, got table
The value of "this" is the same LuaTable in both cases, but because the method registerEvent is added via CoerceJavaToLua.coerce(...) it believes it wants a java Object instead of realising it really wants an LuaVale.
So my question is this. Is there a better way around this that allows me to use the same function from both Java and Lua? And thanks for your time if you read it all the way here :)
The error you are getting is probably a red herring and may be due to the way you are binding the "registerEvent" function into the value of "hg.both". Possibly you just need to use the method syntax instead, such as
hg.both:registerEvent(this, "inputcapturedevent", "last", eventRun)
If you want to use the dot syntax hg.both.registerEvent, then using VarArgFunction and implementing invoke() may be a more direct way to implement this. In this example, Both.registerEvent is a plain variable that is a VarArgFunction.
public static class Both {
public static VarArgFunction registerEvent = new VarArgFunction() {
public Varargs invoke(Varargs args) {
LuaTable id = args.checktable(1);
String event = args.tojstring(2);
String priority = args.tojstring(3);
LuaValue callback = args.arg(4);
EventDispatcher.addHandler(id, event, priority, callback);
return NIL;
}
};
}
public static void main(String[] args) throws ScriptException {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("luaj");
Bindings sb = engine.createBindings();
String fr =
"function main(this);" +
" this.modName='Some Mod';" +
" this.lastX = 0;" +
" hg.both.registerEvent(this, 'inputcapturedevent', 'last', eventRun);" +
"end;";
System.out.println(fr);
CompiledScript script = ((Compilable) engine).compile(fr);
script.eval(sb);
LuaFunction mainFunc = (LuaFunction) sb.get("main");
LuaTable hg = new LuaTable();
hg.set("both", CoerceJavaToLua.coerce(Both.class));
sb.put("hg", hg);
LuaTable library = new LuaTable();
mainFunc.call(CoerceJavaToLua.coerce(library));
}
I have a Java program that calls an Applescript file to run, and returns information back to Java. However, I need to also pass some arguments to the Applescript file. The relevant portion of the Java file:
public static void scriptRunner(String[] args) {
// Connect to the database.
ConnectionManager.getInstance().setDBType(DBType.MYSQL);
// Prepare the AppleScript file to be executed.
String homeFolder = System.getenv("HOME");
File scriptFile = new File(homeFolder + "/Documents/Output--Test.applescript");
InputStream scriptStream = null;
try {
scriptStream = FileUtils.openInputStream(scriptFile);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Could not find the Output AppleScript file. Please notify Chris McGee", "File not found", JOptionPane.ERROR_MESSAGE);
ConnectionManager.getInstance().close();
System.exit(1);
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(scriptStream));
// These two lines prepare the scripting engine, ready to run the script.
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
// Add the parameters to the engine so they will be passed to the script.
engine.put("javaOrderNum", args[0]);
engine.put("javaShipDate", args[1]);
engine.put("javaInitials", args[2]);
engine.put("javaOverruns", args[3]);
// Run the script and evaluate the result.
log.trace("Run the script and evaluate the result.");
Object result = null;
try {
result = engine.eval(bufferedReader); // Run the script and place the result into an abstract object.
} catch (ScriptException e) {
JOptionPane.showMessageDialog(null, "Either an error occurred with the Output script or the user cancelled it.", "Script error / cancel", JOptionPane.INFORMATION_MESSAGE);
ConnectionManager.getInstance().close();
System.exit(1);
}
log.debug(result); // Check that we received the correct information back from the script.
log.debug("");
.
.
.
Sadly, the engine.put lines, as suggested from a forum I read during my searches to get this problem solved, don't seem to work. The AppleScript file:
-- Get variables passed in
set jOrderNum to item 1 of arguments
set jShipDate to item 2 of arguments
set jInitials to item 3 of arguments
set jOverruns to item 4 of arguments
-- Set the correct folder variable
if (folderExists(POSIX path of "/Volumes/Users/Scripts/")) then
set server_prefix to "/Volumes/Users/Scripts/"
else if (folderExists(POSIX path of "/centralserver/Users/Scripts/")) then
set server_prefix to "/centralserver/Users/Scripts/"
else
display alert "Please connect to the central server, then try again.
If you have already done so, please let Chris McGee know."
end if
with timeout of (30 * 60) seconds
tell application "Adobe InDesign CS6"
set myJavaScript to server_prefix & "sky-artdept/Test/Output.jsx"
set myResult to do script myJavaScript with arguments {jOrderNum, jShipDate, jInitials, jOverruns} language javascript
return myResult
end tell
end timeout
on folderExists(posixPath)
return ((do shell script "if test -e " & quoted form of posixPath & "; then
echo 1;
else
echo 0;
fi") as integer) as boolean
end folderExists
I am given an error that the variable arguments is not defined. What can I try next?
I can't help with the javascript running the applescript. But, you applescript code is missing a declaration. You're asking for "item 1 of arguments" but you never define the variable arguments.
When the script is not inside any handler, it is implicit that it is inside a run() handler. And, since you're needing to pass arguments on run, you should try wrapping your script, minus the on folderExists() handler, inside a run handler that includes the arguments declaration.
on run(arguments)
-- Get variables passed in
set jOrderNum to item 1 of arguments
set jShipDate to item 2 of arguments
…
end timeout
end run
on folderExists(posixPath)
…
end folderExists
I am having an issue where I always get a 0 value returned when I try to use the ScriptEngine eval. By using Logger, I was able to determine that there are NullPointerExceptions being generated. After further inspection, it appears that GAE doesn't always return a valid script engine (if ever), because it throws an exception when you try to use it.
My code looks like:
public double myEval(String JsFormulaStr ) {
double solutionValue = 0;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine eng = mgr.getEngineByName("JavaScript");
if(eng == null) { // Added this block of code to prevent java.lang.NullPointerException...
log.severe("Unable to get Script Engine." );
return 0;
}
try {
Object jsResults = eng.eval(JsFormulaStr);
solutionValue = Double.parseDouble(jsResults.toString());
return solutionValue;
} catch(Exception e) {
log.severe("[ERROR] in getCalculatedSolution_FromJS_ToDouble()::\n\t" +
"Formula String is: " + JsFormulaStr + "\n\t" + e);
return 0;
}
}
Everything works fine if I run it locally as a WebApp (Both in Eclipse & Netbeans. And within Tomcat & Glassfish 4.0).
Some of the strings which I tried to eval:
62.0 / 100
0.0 * 352.0
(0 - 428) * 1000
(0 - 597) * 1000
73.0 / 100
NOTE: The 0's or 0.0's are from other evaluations which have failed in previous calls. Since this function returns 0 on error.
According to Google's JRE Class Whitelist, the ScriptEngineManager and ScriptEngine classes are allowed. So I don't understand why it isn't working as expected.
Any suggestions?
Thanks in advance,
Randy
I've hit the same problem. Although the classes are whitelisted, it seems like their functionality is limited on App Engine. The code works fine on your local machine but fails when deployed to App Engine as there aren't any script engines available (hence the NullPointerException).
Luckily, you can do the same thing using the Rhino engine.
Note: this example builds on that given by Harsha R in https://stackoverflow.com/a/19828128/578821
Download the Rhino Jar and add js.jar to your classpath (you only need js-14.jar if you're using Java 1.4).
/* Example 1: Running a JavaScript function (taken from examples) */
String script = "function abc(x,y) {return x+y;}";
Context context = Context.enter();
try {
ScriptableObject scope = context.initStandardObjects();
Scriptable that = context.newObject(scope);
Function fct = context.compileFunction(scope, script, "script", 1, null);
Object result = fct.call(context, scope, that, new Object[] { 2, 3 });
System.out.println(Context.jsToJava(result, int.class));
}
finally {
Context.exit();
}
/* Example 2: execute a JavaScript statement */
script = "3 + 2 * (4*5)";
context = Context.enter();
try{
Scriptable scope = context.initStandardObjects();
Object result = context.evaluateString(scope, script, "<cmd>", 1, null);
System.out.println(result);
}
finally{
Context.exit();
}
I have a class which takes in various system parameters and prints them out:
public class Test_Class {
public static void main(String[] args){
String fooA = System.getProperty("fooA");
String fooB = System.getProperty("fooB");
String fooC = System.getProperty("fooC");
System.out.println("System Properties:\n"+fooA+"\n"+foob+"\n"+fooC+"\n");
}
}
Then, using IntelliJ, pass in the VM Parameters as such:
-DfooA="StringA" -DfooB="StringB" -DfooC="String C"
Upon running my program I get the following output:
System Properties:
StringA
StringB
String C
Now, if I run the same program through a UNIX server by running the following command:
java -DfooA="StringA" -DfooB="StringB" -DfooC="String C" com.foo.fooUtil.Test_Class
I get the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: C
I have tried a bunch of different ways to pass in fooC, such as -DfooC=\"String C\", -DfooC='String C', -DfooC=\'String C\', basically any idea that came to mind. I have done some research and have been unable to find any solid solution.
For reference, I found the following link online where another person seems to have the same issue but, unfortunately, none of the suggestions work.
http://www.unix.com/shell-programming-scripting/157761-issue-spaces-java-command-line-options.html
How can I pass in a System Parameter with spaces in UNIX? Thank you.
Here is my approach: Why not use a .properties file for storing the system properties instead of passing them through command line? You can access the properties using:
Properties properties = new Properties();
try {
properties.load(new FileInputStream("path/filename"));
} catch (IOException e) {
...
}
And you may iterate as:
for(String key : properties.stringPropertyNames()) {
String value = properties.getProperty(key);
System.out.println(key + " => " + value);
}
Hope that helps!!!