I have a Java library and I have to build a Python wrapper to it.
I am using py4j, and it's pretty easy to get any instance and any class, complete with method.
The problem is that the type of an object doesn't correspond to its class.
From python:
>>> gw = JavaGateway()
>>> a_circle = gw.jvm.com.geometry.Circle(15)
>>> a_circle.getDiameter()
30
>>> type(a_circle)
<class 'py4j.java_gateway.JavaObject'>
This is almost ok for basic usage, but what if I want to create custom constructors? Should I subclass the JavaObject class? Or it's better to create my classes from scratch and for every method and constructor invoke the corresponding Java method?
Any suggestion for a good way to achieve it? Should i try something different than py4j?
Thank you!
EDIT: for example, I have to wrap a Java class that has 3 methods, one of those methods takes an array as parameter, so I have to inject some code in order to convert.
class Service:
def __init__(self, javaService):
'''
Create a new instance of Service, assigning Java methods as attributes.
Accepts a working instance of Service from Java
This constructor is not meant to be called by the user.
'''
self.subscribe = javaService.subscribe
self.unsubscribe = javaService.unsubscribe
def publish(values):
'''
Wraps the java implementation of this method, converting the list of value from a Python iterable to a Java list.
'''
global java_gateway
parameterValues = ListConverter().convert(values, java_gateway._gateway_client)
return javaService.publish(values)
self.publish = publish
This works, but I am doing only when it is necessary. If the class just works directly, I am not writing anything to wrap it.
Related
I have a spark Scala library and I am building a python wrapper on top of it. One class of my library provides the following method
package com.example
class F {
def transform(df: DataFrame): DataFrame
}
and I am using py4j in the following way to create a wrapper for F
def F():
return SparkContext.getOrCreate()._jvm.com.example.F()
which allows me to call the method transform
The problem is that the python Dataframe object is obviously different from the Java Dataframe object. For this purpose, I need a way to convert a python df to a java one, for which I use the following code from py4j docs
class DataframeConverter(object):
def can_convert(self, object):
from pyspark.sql.dataframe import DataFrame
return isinstance(object, DataFrame)
def convert(self, object, gateway_client):
from pyspark.ml.common import _py2java
return _py2java(SparkContext.getOrCreate(), object)
protocol.register_input_converter(DataframeConverter())
My problem is that now I want to do the inverse: getting a java dataframe from the transform and continue to use it in python. I tried to use protocol.register_output_converter but I couldn't find any useful example, apart for code dealing with java collections.
How can I do that? An obvious solution would be to create a python class F which defines all methods present in java F, forwards all the python calls to the jvm, get back the result and convert it accordingly. This approach works but it implies that I have to redefine all methods of F thus generating code duplication and a lot more maintainance
Suppose I have an interface:
public interface Function {
double function (double input);
}
Now, suppose I have created an instance of this interface somewhere in my main class,
Function f = (x) -> x;
How can I go about printing this function, in plain text?
So, something a bit like this:
int f (double x) {return x}
Running a .toString on this Function prints something like Main$1#6d06d69c. How can I go about getting the java representation of this interface?
Remember that the text of a function (otherwise known as "code") only exists when you write it. You compile this to bytecode which is then run on the Java Virtual Machine. At runtime, the original code which you wrote no longer exists and cannot be easily retrieved.
Unfortunately, the answer (as of Java 9) is that there isn't a simple way to get the toString() method to give you a human-meaningful value for an arbitrary instance of a functional interface.
Here are a couple of alternatives that are applicable for some use-cases:
Instead of using a lambda, implement the interface using a class, and include an appropriate override for the toString() method.
Populate a Map<Function, String> with meaningful names for all of your Function instances.
It would be theoretically possible to build a library that can retrieve the ".class" file for (say) a lambda, analyse it, work out what the bytecodes do, and then produce an appropriate summary. But it would be difficult project.
It would be nice if there was a simple, clean solution to this. Maybe "someone" could suggest it as an RFE for a future version of Java.
You need to call the method in the interface explicitly by supplying a value of double, like below
Function f = (d) -> d;
System.out.print(f.function(2.0));
In JavaScript, you can do this.
String.prototype.removeNumericalCharacters = function(){
...code...
}
or
Number.prototype.addTwo = function(){
...code...
}
var a = 5;
a.addTwo();
//a is now 7
Is there a way to do something similar in Java? (I don't mean the actual function, just using that as an example)
An example in Java would be
int a = 5;
a.addTwo();
//A is now 7
My question is how do I define the .addTwo() method.
It's Friday so lets answer this question. I'm not going to dive into much details (it's Friday!) but hopefully you'll find this useful (to some extend).
You certainly know that Java objects don't have prototypes. If you want to add a field or a method to a Java class you have two options. You either extend the existing class and add the method/ field to it like this:
public class A {
}
public class B extends A {
int addTwo () {...};
}
However that's not changing the parent class. Objects of class A in the example still have no method addTwo.
Second approach is to dynamically change the class (you could use things like javassist) and method/fields to it. It's all fine but to use these new methids/fields you'd have to use reflection. Java is strongly typed and needs to know about class's available methods and fields during the compile time.
Finally and that's when things get really rough - primitive types, in your instance int, are 'hardwired' into JVM and can't be changed. So your example
int a = 5;
a.addTwo();
is impossible in Java. You'd have more luck with dynamic languages on JVM (Groovy is one of them). They're usually support optional typing and allow dynamic method calls.
So enjoy Friday!
In java it is possible to cast an object onto a class.
An good example is found here
Object aSentenceObject = "This is just a regular sentence";
String aSentenceString = (String)aSentenceObject;
I have a program that needs to integrate some java with python. I am trying to do this via the JCC library. The problem that I am encountering is that with JCC, all of the java classes are loaded into the imported library that I created with JCC. So I can create an instance of the base class by passing the necessary argument to the constructor of the java class.
obj = javaLibrary.BaseClass('foo')
However, in my code I need to be able to cast this object onto a a more “specific” type of Object.
How can I accomplish this in python with JCC? It seems like it may be impossible because python is dynamically typed, but that is why I am asking this question.
All comments above valid, but to be specific for your case:
casted_obj = Object.cast_(obj)
Im quite new to Rhino and my question is around how to achieve the following,
Say I have a javascript object that follows something like the following that I can consume within java.
var myObject = new Object();
myObject.string1 = "Hello";
myObject.string2 = "World";
myObject.int1 = 1;
But how do I consume this within java if its dynamic. For .e.g. if you decide to add few more members dynamically to this object within javascript. Is this doable ? My guess is the class defined within java will have to take all the possible members into account to do this ?
Hopefully I have explained what im trying to achieve correctly.
JavaScript objects, when you access them in Java, are all essentially the same class: ScriptableObject which implements the Scriptable interface (GitHub source). There are a few other classes for functions and other specialized objects.
The Scriptable interface includes methods like get, has, and put that correspond roughly to myObject.string1, myObject.hasOwnProperty("string1"), and myObject.string1 = "Hello" in JavaScript. The ScriptableObject class adds some other useful methods for defining properties, etc.
Consider using a library like GSON for converting a javascript object to JAVA.
https://code.google.com/p/google-gson/
you can convert a javascript object to JSON using JSON.stringify
and then use GSON or another such library to generate a Java object.