Calling jython script from java - java

I am currently working on a simple hello world program using jython and java.
The program is designed in way that a jython method accepts a name parameter and returns welcome message.
My problem is whenever I am accessing the jython method from java, it shows nullponter exception
My jython Script (JythonHello.py):
class JythonHello:
def __init__(self, name):
self.name = name
def sayHello(self):
return "Hello "+ self.name
and my java code:
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile("src/jython/JythonHello.py");
PyObject callFunction = interpreter.get("sayHello");
PyObject result = callFunction.__call__(new PyString("Boban"));
String msg = (String) result.__tojava__(String.class);
System.out.println("output: " + msg);
}
Any suggestions?

Looking at your code; your python code defines a class and a member method:
class JythonHello:
def __init__(self, name): ...
def sayHello(self): ...
And it seems that you intend to call that method:
PyObject callFunction = interpreter.get("sayHello");
PyObject result = callFunction.__call__(new PyString("Boban"));
But please note: sayHello() doesn't take any arguments. That self parameter is an indication that you have to call it on an object; but without any other parameters!
So, in pure python you would say:
helloVar = JythonHello("Boban")
helloVar.sayHello()
But your java code tries to call it like
sayHello("Boban")
So, the real answer is: step back; and re-think what you really intend to do; and then write code that works that way.
I would start by not adding the "class" part on the python side; instead try to simply invoke a function that takes a string argument for example!
And finally: could it be that you are on the wrong path altogether? The main point of jython is to write simply python code to do "debug" work within a running JVM. You are writing complicated Java code to use a bit of python code on the other hand ...

Related

How do I evaluate a Groovy string within a script?

I'm essentially trying to create a CLI with Groovy. I have a whole JavaFX GUI set up in Java and I want to be able to type in groovy script to run different functions inside a groovy script.
For example, say I have this script:
void meow() {
println "walrus"
}
I want to be able to type in "meow();" and press enter and evaluate it using the script as a reference.
I've tried using
shell.evaluate(inputStr, "src/Server/Scripting/CommandLineScript.groovy");
but to no avail; it just comes up with the error:
groovy.lang.MissingMethodException: No signature of method: CommandLineScript.meow() is applicable for argument types: () values: []
I can call other standard functions, such as:
shell.evaluate("println 'Hello World!';");
but I just can't run my own methods... How to solve it?
The following worked for me.
evaluate(new File("/Users/jellin/meow.groovy"))
I did change the meow.groovy file to execute the method within the file.
void meow() {
println "walrus"
}
meow()
One issue is I don't see a way to pass a parameter to the calling script.
I have used the following before, you can pass parameters as part of the binding.
String script = "full path to the script"
GroovyScriptEngine gse = new GroovyScriptEngine()
Binding binding = new Binding();
Object result = gse.run(script, binding)
Also, you might be able to simply reference the other scripts as classes and execute the run method on them.
There is also an AST transformation that can be used to have scripts extend a base script.
See here for more info
http://mrhaki.blogspot.com/2014/05/groovy-goodness-basescript-with.html
Thanks for your time guys; after a little more searching (always after posting a question do I find the answer in research >,<), I found that you can set a base class for the GroovyShell... I did it this way:
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
loader.addClasspath("src/ScriptLoc/");
binding = new Binding();
CompilerConfiguration compConfig = new CompilerConfiguration();
compConfig.setScriptBaseClass("ScriptName");
shell = new GroovyShell(loader, binding, compConfig);
I thought there would be a way to do it, and there it is... Now whenever I need to evaluate a script from the text box, I can just evaluate it and it evaluates it in the context of the base script.

Jython Decorators: 1st arg can't be coerced to org.python.core.PyFunction

I'm building a way to script CraftBukkit (Minecraft modded server software) with Python.
I do this by loading a Python script with Jython, and then having decorators for events, etc.
I'm currently implementing the event decorators, but I have a problem: Decorators with no arguments work fine, but as soon as I add an argument, it starts complaining about there not being enough arguments.
This works:
#script.event
def test(event):
print "hi" # Works
public void event(PyFunction func) {
return func;
}
This does not:
#script.event("player.PlayerMoveEvent", "normal")
def test(event):
print "player moved!" # TypeError: event(): 1st arg can't be coerced to org.python.core.PyFunction
public void event(PyFunction func, PyString eventType, PyString priority) {
// Do all kinds of crap
return func;
}
Here's my Java code:
http://pastebin.com/GsULYdJr
This has nothing to do with Jython. The equivalent pure Python code shows the actual problem (I'm leaving out the class or namespace script for simplicity):
def event(func, event_type, priority):
# ...
return func
#event("player.PlayerMoveEvent", "normal")
def test(event):
print "player moved"
The error is
Traceback (most recent call last):
...
TypeError: event() missing 1 required positional argument: priority
and it's caused by a misunderstanding of decorators. You expect the decorated function definition to be executed like this
def test(event):
print "player moved"
test = event(test, "player.PlayerMoveEvent", "normal")
but it's executed like this:
__decorator = event("player.PlayerMoveEvent", "normal")
def test(event):
print "player moved"
test = __decorator(test)
The part behind the # is evaluated in isolation, and the result of that is called with the test function as argument. The normal fix in Python is to use a closure, but that's probably cumbersome in Java. It's probably easiest to write part of the decorator in Python and leave the Java code as it currently is:
def script(event_type, priority):
def decorate(func):
return script.event(func, event_type, priority)
return decorate

Reflect on functions declared in a Groovy script

Is there a way to obtain reflection data on functions declared in a Groovy script that has been evaluated via a GroovyShell object? Specifically, I want to enumerate the functions in a script and access annotations attached to them.
Put this to the last line of Groovy script - it will serve as a return value from the script, a-la:
// x.groovy
def foo(){}
def bar(){}
this
Then, from Java code you can do the following:
GroovyShell shell = new GroovyShell();
Script script = (Script) shell.evaluate(new File("x.groovy"));
Now it seems that there's no option to introspect the annotations of Groovy script from Java directly. However, you can implement a method within the same Groovy script and call that one from Java code, for instance:
//groovy
def test(String m){
method = x.getMethod(m, [] as Class[])
assert method.isAnnotationPresent(X)
}
//java
script.getMetaClass().invokeMethod(script, "test", "foo");
After some experimenting, I found this to be the easiest way:
GroovyShell shell = new GroovyShell();
Script script = (Script)shell.parse(new FileReader("x.groovy"));
Method[] methods = script.getClass().getMethods();
The method array has all of the functions defined in the script and I can get the annotations from them.

How to call a user defined Matlab from Java using matlabcontrol.jar

I am trying to call a user defined Matlab Function(M file) which takes 3 arguments(Java Strings) from my Java application which is developed in Eclipse. At the moment I am able to call proxy.eval and proxy.feval methods with the functions/commands like disp or sqr. But when i try to invoke a user-defined function it says on the matlab console that there is no such function defined like that and on the Java console MatlabInvocationException occurs.
Then I tried with a simple user-defined function which takes no arguments and just has single line disp('Hello') but still the result is same. So I think rather than a type conversion problem there is something wrong with how user-defined functions are getting invoked.
Please can anyone help me soon? I am meeting the deadline very soon for this project. I would be so thankful if someone can come up with a solution. (Mr Joshuwa Kaplan, is there any guide on solving an issue like this in your posts? I tried but found nothing)
Thanks in advance
You must have any user-defined m-files on the MATLAB search path, just as if you were working normally inside MATLAB.
I tested with the following example:
C:\some\path\myfunc.m
function myfunc()
disp('hello from MYFUNC')
end
HelloWorld.java
import matlabcontrol.*;
public class HelloWorld
{
public static void main(String[] args)
throws MatlabConnectionException, MatlabInvocationException
{
// create proxy
MatlabProxyFactoryOptions options =
new MatlabProxyFactoryOptions.Builder()
.setUsePreviouslyControlledSession(true)
.build();
MatlabProxyFactory factory = new MatlabProxyFactory(options);
MatlabProxy proxy = factory.getProxy();
// call builtin function
proxy.eval("disp('hello world')");
// call user-defined function (must be on the path)
proxy.eval("addpath('C:\\some\\path')");
proxy.feval("myfunc");
proxy.eval("rmpath('C:\\some\\path')");
// close connection
proxy.disconnect();
}
}
We compile and run the Java program:
javac -cp matlabcontrol-4.0.0.jar HelloWorld.java
java -cp ".;matlabcontrol-4.0.0.jar" HelloWorld
a MATLAB session will open up, and display the output:
hello world
hello from MYFUNC
You could also add your folder to the path once, then persist it using SAVEPATH. That way you won't have to do it each time.

how to pass java output as a matlab variable?

I have written a Java program which is invoked using system() function, thus it runs on the command window of Matlab. Now I want to know if there's another way to run a Java program other than running it on command window? Can it be run on any user made GUI in Matlab? Another problem is, I want to know if my program has some string value as output, which is generally displayed on command window, how can i store it in variable in Matlab?
Hope to hear from you very soon.
The Hello World solution by The MathWorks provides some insights on how to run a simple 'Hello World' java application inside MATLAB. You may change the Java code a bit, in order to have a method that returns a String.
public class HelloWorld
{
public String hello()
{
String helloWorld = "Hello World!";
return helloWorld;
}
}
Once this simple class is compiled and on the MATLAB JVM classpath create an instance and invoke the method with the following two commands.
o = HelloWorld
output = o.hello;
The String returned by the HelloWorld instance is assigned to the MATLAB variable output.
There is no need for a system command with Java code in MATLAB. You have direct access to the JVM from inside MATLAB. For an application with a complex GUI, break out to Java.
Undocumented Java is a valuable source on MATLAB, Java and GUIs.
Yes the classpath set is correct.
I modified the code, using it without main..
class HelloWorld
{
public String Hello()
{
String helloWorld="Hello World!";
return helloWorld;
}
}
Now, as per guided i try to create instance obj in Matlab, with following command:
o = HelloWorld;
Here I get following err:
??? No constructor 'HelloWorld' with
matching signature found.
The next command indicated it this:
output = o.hello;
which wouldnt work unless instance is created.

Categories