I have a python app and java app. The python app generates input for the java app and invokes it on the command line.
I'm sure there must be a more elegant solution to this; just like using JNI to invoke C code from Java.
Any pointers? (FYI I'm v. new to Python)
Clarification (at the cost of a long question: apologies) The py app (which I don't own) takes user input in the form of a number of configuration files. It then interprits these and farms work off to a number of (hidden) tools via a plugin mechanism. I'm looking to add support for the functionality provided by the legacy Java app.
So it doesn't make sense to call the python app from the java app and I can't run the py app in a jython environment (on the JVM).
Since there is no obvious mechanism for this I think the simple CL invocation is the best solution.
-
so uh... why cant the java program invoke the Python to produce the input it needs?Alex Lim– Alex Lim2009年01月25日 00:44:12 +00:00Commented Jan 25, 2009 at 0:44
-
1I'm not sure I would consider JNI to be "elegant". :)Greg Hewgill– Greg Hewgill2009年01月25日 00:50:48 +00:00Commented Jan 25, 2009 at 0:50
-
See stackoverflow.com/questions/454182/…, stackoverflow.com/questions/299249/…, stackoverflow.com/questions/438594/…S.Lott– S.Lott2009年01月25日 00:53:06 +00:00Commented Jan 25, 2009 at 0:53
7 Answers 7
Sorry to ressurect the thread, but there was no accepted answer...
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, 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 communication is done through sockets instead of JNI.
Disclaimer: I am the author of Py4J
3 Comments
from py4j.java_gateway import JavaGateway; gateway = JavaGateway(); gateway.gateway_parameters.port = 4040; gateway.jvm.java.lang.System.out.println('Hello World!') but I get the following error py4j.protocol.Py4JError: java does not exist in the JVM. Can you explain what I need to do here? Question link Take a look at Jython. It's kind of like JNI, but replace C with Python, i.e. you can call Python from Java and vice versa. It's not totally clear what you're trying to do or why your current approach isn't what you want.
Wrap your Java-Code in a Container (Servlet / EJB).
So you don ́t loose time in the vm-startup and you go the way to more service-oriented.
For the wraping you can use jython (only make sense if you are familiar with python)
Choose a communication-protocoll in which python and java can use:
- json (see www.json.org)
- rmi (Python: JPype)
- REST
- SOAP (only for the brave)
Choose something you or your partners are familliar with!
Comments
If you really want to embed your Java app within your Python process, have a look at JPype. It provides access to Java through JNI.
Comments
How about using swig: http://www.swig.org/Doc1.3/Java.html ?
Comments
Give JCC a try http://pypi.python.org/pypi/JCC/2.1
JCC is a code generator for calling Java directly from CPython. It supports CPython 2.3+, several JREs (Sun JDK 1.4+, Apple JRE 1.4+, and OpenJDK 1.7) on OS X, Linux, Solaris, and Windows. It's produced by the Open Source Application Foundation (OSAF, the people making Chandler) and is released under an Apache-style license.
From the package description:
JCC is a C++ code generator for producing the glue code necessary to call into Java classes from CPython via Java's Native Invocation Interface (JNI).
JCC generates C++ wrapper classes that hide all the gory details of JNI access as well Java memory and object reference management.
JCC generates CPython types that make these C++ classes accessible from a Python interpreter. JCC attempts to make these Python types pythonic by detecting iterators and property accessors. Iterators and mappings may also be declared to JCC.
Comments
You can use a library called BridgeService that exposes (for now) Java code as Rest API.
https://github.com/adobe/bridgeService
You can either put your library in the project itself or if it is a project of your, you can add the bridgeService to your project and make it accessible.
For example if you want to send a call to the java class (This example will work if you launch the project as it is following Running a DEMO ):
If you send the following payload with the POST call http://localhost:8080/call:
{
"callContent": {
"call1": {
"class": "com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods",
"method": "methodAcceptingStringArgument",
"args": [
"A Real"
]
}
}
}
In the example abobe the code will execute the method methodAcceptingStringArgumentin the class com.adobe.campaign.tests.bridge.testdata.one.SimpleStaticMethods.
The return value will be :
{
"returnValues": {
"call1": "A Real_Success"
},
"callDurations": {
"call1": 7
}
}