So is there any way to generate simple "Pojo" Python classes from Java code?
I had a go at it and below is the solution:
Considering below simplistic Pojo.java
public class Pojo {
private String string = "default";
public int integer = 1;
public String getString(){
return string;
}
}
The solution will need 3 phases
1. Java Pojo to JSON Schema
I could find below options:
- FasterXML/jackson-module-jsonSchema: This is the base, which below libraries also use internally.
- mbknor/mbknor-jackson-jsonSchema: Officially cited by above to support the v4 of the json schema.
- reinert/JJSchema
With below relevant code with option 1(also go through the site):
ObjectMapper MAPPER = new ObjectMapper();
JsonSchemaGenerator generator = new JsonSchemaGenerator(MAPPER);
JsonSchema jsonSchema = generator.generateSchema(Pojo.class);
System.out.println(MAPPER.writeValueAsString(jsonSchema));
Below output json schema string is got:
{"type":"object","id":"urn:jsonschema:Pojo","properties":{"string":{"type":"string"},"integer":{"type":"integer"}}}
2. JSON Schema post-process
This phase is required mainly because I found that for the simplistic use case(at least), Step 3 below needs a json schema that has a definitions property mandatorily. I guess this is because of the evolving schema definitions @ http://json-schema.org/. Also, we can include a title property to specify the name of the python class that next step will generate.
We can easily accomplish these in the java program of Step 1 above as a post step. We need a json schema string of below form:
{"definitions": {}, "title": "Pojo", "type":"object","id":"urn:jsonschema:Pojo","properties":{"string":{"type":"string"},"integer":{"type":"integer"}}}
Notice that only addition is "definitions": {}, "title": "Pojo"
3. Json schema to Python class
frx08/jsonschema2popo seems to be doing this job quite nicely.
pip install jsonschema2popo
jsonschema2popo -o /path/to/output_file.py /path/to/json_schema.json
Some more points
- The Java-Json schema generators will only include those properties in the output which are either public or have a public getter.
- I assume that for a mass migration annotating the Java classes will be a pain. Otherwise, if this is feasible to you, all the above java libraries provide rich annotations where you can specify whether a property is mandatory and much more.
So is there any way to generate simple "Pojo" Python classes from Java code?
I had a go at it and below is the solution:
Considering below simplistic Pojo.java
public class Pojo {
private String string = "default";
public int integer = 1;
public String getString(){
return string;
}
}
The solution will need 3 phases
1. Java Pojo to JSON Schema
I could find below options:
- FasterXML/jackson-module-jsonSchema: This is the base, which below libraries also use internally.
- mbknor/mbknor-jackson-jsonSchema: Officially cited by above to support the v4 of the json schema.
- reinert/JJSchema
With below relevant code with option 1(also go through the site):
ObjectMapper MAPPER = new ObjectMapper();
JsonSchemaGenerator generator = new JsonSchemaGenerator(MAPPER);
JsonSchema jsonSchema = generator.generateSchema(Pojo.class);
System.out.println(MAPPER.writeValueAsString(jsonSchema));
Below output json schema string is got:
{"type":"object","id":"urn:jsonschema:Pojo","properties":{"string":{"type":"string"},"integer":{"type":"integer"}}}
2. JSON Schema post-process
This phase is required mainly because I found that for the simplistic use case(at least), Step 3 below needs a json schema that has a definitions property mandatorily. I guess this is because of the evolving schema definitions @ http://json-schema.org/. Also, we can include a title property to specify the name of the python class that next step will generate.
We can easily accomplish these in the java program of Step 1 above as a post step. We need a json schema string of below form:
{"definitions": {}, "title": "Pojo", "type":"object","id":"urn:jsonschema:Pojo","properties":{"string":{"type":"string"},"integer":{"type":"integer"}}}
Notice that only addition is "definitions": {}, "title": "Pojo"
3. Json schema to Python class
frx08/jsonschema2popo seems to be doing this job quite nicely.
pip install jsonschema2popo
jsonschema2popo -o /path/to/output_file.py /path/to/json_schema.json
Some more points
- The Java-Json schema generators will only include those properties in the output which are either public or have a public getter.
- I assume that for a mass migration annotating the Java classes will be a pain. Otherwise, if this is feasible to you, all the above java libraries provide rich annotations where you can specify whether a property is mandatory and much more.
TechWalla @https://www.techwalla.com/articles/how-to-convert-java-to-python has detailed instructions. See if it helps you.
Pasting the instructions here Step 1 Download and extract java2python. The file you download is a gzip file, and it contains within it a tarball file; both are compression schemes, and both can be decompressed with 7zip, an open-source program.
Step 2 Place the contents of the java2python folder on the root of your C:\ drive.
Step 3 Open a command prompt and navigate to "C:\java2python\" before typing in "python setup.py install" without quotes. This will tell the Python interpreter to run the setup script and prepare your computer. Change directories to "C:\java2python\bin\" and keep the window open.
Step 4 Copy the Java file to be converted into your bin subfolder, under java2python. In the command line, run "j2py -i input_file.java -o output_file.py," replacing the input_file and output_file with your filenames.
Step 5 Open the new Python folder and read the code. It probably won't be perfect, so you'll need to go over it to make sure it makes sense from a Python point of view. Even spending time manually checking, however, you will have saved large amounts of time from hand-converting
Calling Java from Python - Stack Overflow
How to convert Java class to Python
Importing Java class into a python project - Stack Overflow
how to switch from java to python?
Videos
You could also use Py4J. There is an example on the frontpage and lots of documentation, but essentially, you just call Java methods from your python code as if they were python methods:
from py4j.java_gateway import JavaGateway
gateway = JavaGateway() # connect to the JVM
java_object = gateway.jvm.mypackage.MyClass() # invoke constructor
other_object = java_object.doThat()
other_object.doThis(1,'abc')
gateway.jvm.java.lang.System.out.println('Hello World!') # call a static method
As opposed to Jython, one part of Py4J runs in the Python VM so it is always "up to date" with the latest version of Python and you can use libraries that do not run well on Jython (e.g., lxml). The other part runs in the Java VM you want to call.
The communication is done through sockets instead of JNI and Py4J has its own protocol (to optimize certain cases, to manage memory, etc.)
Disclaimer: I am the author of Py4J
Here is my summary of this problem: 5 Ways of Calling Java from Python
http://baojie.org/blog/2014/06/16/call-java-from-python/ (cached)
Short answer: Jpype works pretty well and is proven in many projects (such as python-boilerpipe), but Pyjnius is faster and simpler than JPype
I have tried Pyjnius/Jnius, JCC, javabridge, Jpype and Py4j.
Py4j is a bit hard to use, as you need to start a gateway, adding another layer of fragility.
ยป pip install java2python
In short, you can't run Java code natively in a CPython interpreter.
Firstly, Python is just the name of the specification for the language. If you are using the Python supplied by your operating system (or downloaded from the official Python website), then you are using CPython. CPython does not have the ability to interpret Java code.
However, as you mentioned, there is an implementation of Python for the JVM called Jython. Jython is an implementation of Python that operates on the JVM and therefore can interact with Java modules. However, very few people work with Jython and therefore you will be a bit on your own about making everything work properly. You would not need to re-write your vanilla Python code (since Jython can interpret Python 2.x) but not all libraries (such as numpy) will be supported.
Finally, I think you need to better understand the K-Means algorithm, as the algorithm is implicitly defined in terms of the Euclidean distance. Using any other distance metric would no longer be considered K-Means and may affect the convergence of the algorithm. See here for more information.
Again, you can't run Java code natively in a CPython interpreter. Of course there are various third party libraries that will handle marshalling of data between Java and Python. However, I stand by my statement that for this particular use case you are likely better to use a native Python library (something like K-Medoid in Scikit-Learn). Attempting to call through to Java, with all the associated overhead, is overkill for this problem, in my opinion.
To "answer" your question directly, Jython will be your best bet if you simply want to import Java classes. Jython strives very hard to be as compatible with Python 2.x as possible and does a good job. So you won't have to spend too much time rewriting code. Just simply run it with Jython and see what happens, then modify what breaks.
Now for the Python answer :D. You may want to use scikit for a native implementation. It will certainly be faster than running anything in Jython.
Update
I think the Py4J module is what you're looking. It works by running a server in your Java code and the Python code will communicate with the Java server. The only good thing about "Py4J" is that it provides the boiler plate code for you. You can very easily setup your own client/server with no extra modules. However I still don't think it's a superior option compared to Pythons native modules.
References
How to import Java class w/ Jython
Scikit - K-Means