Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing varargs to Java from Python using Py4j

I am trying to pass varargs to Java code from python.

Java code : LogDebugCmd.java

public class LogDebugCmd implements Command {
  private Class clazz;
  private String format;
  private Object[] args;

  public LogDebugCmd() {}
  public void setLog(String format, Object... args) {
    this.format = format;
    this.args = args.clone();
    clazz = getClass();
  }

  @Override
  public void execute() {
    VLog.getLog(clazz).debug(format, args);
  }

CommandEntryPoint.java

public class CommandEntryPoint {
  private LogDebugCmd logDebugCmd;

  public CommandEntryPoint() {
    logDebugCmd = new LogDebugCmd();

  public LogDebugCmd getLogDebugCmd(String str, Object... args) {
    setLog(str, args);
    return logDebugCmd;
  }
  public static void main(String args[]) {
    GatewayServer gatewayServer = new GatewayServer(new CommandEntryPoint());
    gatewayServer.start();
    System.out.println("Gateway Server Started");
  }

Python code test.py:

from py4j.java_gateway import JavaGateway
gateway = JavaGateway()
logDebugCmd = gateway.entry_point.getLogDebugCmd("Step 01 - Test initiated.")
logDebugCmd..execute()

Error :

Traceback (most recent call last):
  File "C:/Python27/Lib/site-packages/py4j-0.10.3-py2.7.egg/py4j/sampleTLStest.py", line 4, in <module>
    logDebugCmd = gateway.entry_point.getLogDebugCmd("Step 01 - Test initiated.")
  File "C:\Python27\lib\site-packages\py4j-0.10.3-py2.7.egg\py4j\java_gateway.py", line 1133, in __call__
    answer, self.gateway_client, self.target_id, self.name)
  File "C:\Python27\lib\site-packages\py4j-0.10.3-py2.7.egg\py4j\protocol.py", line 323, in get_return_value
    format(target_id, ".", name, value))
***Py4JError: An error occurred while calling t.getLogDebugCmd. 
Trace:
py4j.Py4JException: Method getLogDebugCmd([class java.lang.String]) does not exist at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326)
at py4j.Gateway.invoke(Gateway.java:272)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:214)
at java.lang.Thread.run(Thread.java:745)***

Is there a way to pass varargs to Java ? I am trying to pass String as the second argument to getLogDebugCmd() which also errors out.

like image 627
Pooja Avatar asked Nov 03 '16 22:11

Pooja


People also ask

How to get started with py4j?

Getting Started with Py4J ¶ This short tutorial assumes that you have already installed Py4J and that you are using the latest version. In this tutorial, you will write a simple Stack class in Java and then, you will write a Python program that accesses the stack. You will also see how Java lists can be manipulated as Python lists. 2.1.

What is the path to py4j jar in Java?

jarpath – the path to the Py4J jar. Only necessary if the jar was installed at a non-standard location or if Python is using a different sys.prefix than the one that Py4J was installed under. classpath – the classpath used to launch the Java Gateway.

How to pass pure Python list to Java list in py4j?

See what happens if you try to pass a pure Python list that was not returned by the JVM: By default, Py4J does not support the conversion from pure Python lists to Java list. It is possible to ask Py4J to automatically perform this conversion or to use one of the explicit converter.

How do I connect to JVM using py4j?

Start a Python interpreter and make sure that Py4J is in your PYTHONPATH. Next, initialize a JavaGateway. The default parameters are usually sufficient for common cases. When you create a JavaGateway, Python tries to connect to a JVM with a gateway (localhost on port 25333).


1 Answers

Varargs are actually represented as an array so you can do this:

# Pass a None if you have no varargs
logDebugCmd = gateway.entry_point.getLogDebugCmd("Step 01 - Test initiated.", None)

# Create an array of objects
object_class = gateway.jvm.Object
object_array = gateway.new_array(object_class, 2)
object_array[0] = "foo"
object_array[1] = "bar"
logDebugCmd = gateway.entry_point.getLogDebugCmd("Step 01 - Test initiated.", object_array)

There is a pull request to improve varargs support in Py4J, but it has some compilation issues so it has not been merged yet.

like image 113
Barthelemy Avatar answered Oct 19 '22 16:10

Barthelemy