Jython inherit from Java class

M

Mark Fink

I wrote a Jython class that inherits from a Java class and (thats the
plan) overrides one method. Everything should stay the same.

If I run this nothing happens whereas if I run the Java class it says:
usage: java fit.FitServer [-v] host port socketTicket
-v verbose

I think this is because I do not understand the jython mechanism for
inheritance (yet).

JyFitServer.py:
===========
import fit.FitServer
import fitnesse.components.FitProtocol
from fit.Parse import Parse
from fit.Fixture import Fixture

# Inherit from original Java FitServer Implementation by Robert C.
Martin and Micah D. Martin
class FitServer(fit.FitServer):
# call constructor of superclass
def __init__(self, host, port, verbose):
FitServer.__init__(self, host, port, verbose)

# override process method
def process(self):
self.fixture.listener = self.fixtureListener
print "hello, I am JyFitServer!"
try:
size = FitProtocol.readSize(self.socketReader)
if size > 0:
try:
document =
FitProtocol.readDocument(self.socketReader, size)
tables = Parse(document)
fixture = Fixture()
fixture.listener = self.fixtureListener;
fixture.doTables(tables)
self.counts.tally(self.fixture.counts)
except FitParseException, e:
self.exception(e)
except Exception, e:
self.exception(e)



Please help,
Mark Fink
 
A

Alan Kennedy

[Mark Fink]
I wrote a Jython class that inherits from a Java class and (thats the
plan) overrides one method. Everything should stay the same.

If I run this nothing happens whereas if I run the Java class it says:
usage: java fit.FitServer [-v] host port socketTicket
-v verbose

I think this is because I do not understand the jython mechanism for
inheritance (yet).

1. Are you running jythonc?

If yes, I think your class and file should have the same name, i.e.
Class FitServer should be in a file called "FitServer.py". I recommend
calling your class something different from the base class, e.g.
MyJythonFitServer, to prevent namespace clashes.

2. If your main function in jython? If yes, please post the code so we
can see how you're instantiating your objects?

3. How are you running this? I.e. show us a command line session which
uses your class.
JyFitServer.py:
===========
class FitServer(fit.FitServer):
# call constructor of superclass
def __init__(self, host, port, verbose):
FitServer.__init__(self, host, port, verbose)
^^^^^^^^^
Shouldn't this be:
fit.FitServer.__init__(self, host, port, verbose)

I'm not sure the latter is cause of your problems, but it might be.

HTH,
 
K

Kent Johnson

Mark said:
I wrote a Jython class that inherits from a Java class and (thats the
plan) overrides one method. Everything should stay the same.

If I run this nothing happens whereas if I run the Java class it says:
usage: java fit.FitServer [-v] host port socketTicket
-v verbose

It sounds like the Java class has a main() function. When you run it as
an application, the Java runtime looks for the main() function in the
class you tell it to run.

Even in Java, this behaviour is not preserved by inheritance, a subclass
has to have its own main() to be executable.

Jython (and Python) works a little differently, your module is executed
from start to finish when you run it. Any statements that are not inside
a class or function definition will be executed. (Actually the class and
function definitions are executed to, but not in the same way...)

You might get the behaviour you want if you put the line
import sys
fit.FitServer.main(sys.argv)

at the end of your file. This will run the main() function of the Java
class.

Kent
 
M

Mark Fink

Alan, Kent, many thanks this really helped!
But there is still a problem I guess with inheritance. I use the java
testsuit supplied with the original to test the server. If I use the
Java FitServer the testsuite can be completed. I commented everything
out from my class and it does not work??
Thats the trace when I run the JUnit testsuit:
java.io.IOException: CreateProcess: jython
D:\AUT_TEST\workspace\JyFIT\fit\JyFitServer.py
-Dpython.path='D:\AUT_TEST\workspace\JyFIT'
D:\AUT_TEST\fitnesse\fitnesse.jar localhost 1234 23 error=2
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
at java.lang.ProcessBuilder.start(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at
FitServerTest.FitServerTest.prepareSessionProcess(FitServerTest.java:163)
at
FitServerTest.FitServerTest.testSimpleStartUp(FitServerTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

Unfortunately I do not get much information at the prompt because both
Java FitServer and JyFitServer behave the same there.
D:\AUT_TEST>jython D:\\AUT_TEST\\workspace\\JyFIT\\fit\\JyFitServer.py
-Dpython.path='D:\\AUT_TEST\\workspace\\JyFIT'
D:\\AUT_TEST\\fitnesse\\fitnesse.jar localhost 1234 23
Traceback (innermost last):
File "D:\\AUT_TEST\\workspace\\JyFIT\\fit\\JyFitServer.py", line 42,
in ?
java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at
java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:507)
at java.net.Socket.connect(Socket.java:457)
at java.net.Socket.<init>(Socket.java:365)
at java.net.Socket.<init>(Socket.java:178)
at fit.FitServer.establishConnection(Unknown Source)
at fit.FitServer.establishConnection(Unknown Source)
at fit.FitServer.run(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at
org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java)
at org.python.core.PyMethod.__call__(PyMethod.java)
at org.python.core.PyObject.__call__(PyObject.java)
at org.python.core.PyInstance.invoke(PyInstance.java)
at
org.python.pycode._pyx0.f$0(D:\\AUT_TEST\\workspace\\JyFIT\\fit\\JyFitServer.py:42)
at
org.python.pycode._pyx0.call_function(D:\\AUT_TEST\\workspace\\JyFIT\\fit\\JyFitServer.py)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyCode.call(PyCode.java)
at org.python.core.Py.runCode(Py.java)
at org.python.core.__builtin__.execfile_flags(__builtin__.java)
at
org.python.util.PythonInterpreter.execfile(PythonInterpreter.java)
at org.python.util.jython.main(jython.java)

java.net.ConnectException: java.net.ConnectException: Connection
refused: connect

###### And the Java FitServer:
D:\AUT_TEST>java -cp D:\\AUT_TEST\\fitnesse\\fitnesse.jar fit.FitServer
localhost 1234 23
Exception in thread "main" java.net.ConnectException: Connection
refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at fit.FitServer.establishConnection(Unknown Source)
at fit.FitServer.establishConnection(Unknown Source)
at fit.FitServer.run(Unknown Source)
at fit.FitServer.main(Unknown Source)

.... not to bad.
That is the code with everything commented out:
import sys
import fit.FitServer
import fitnesse.components.FitProtocol
from fit.Parse import Parse
from fit.Fixture import Fixture

# Inherit from original Java FitServer Implementation by Robert C.
Martin and Micah D. Martin
class JyFitServer(fit.FitServer):
"""
# call constructor of superclass
def __init__(self, host, port, verbose):
fit.FitServer.__init__(self, host, port, verbose)

# override process method
def process(self):
self.fixture.listener = self.fixtureListener
print "hello, I am JyFitServer!"
try:
size = FitProtocol.readSize(self.socketReader)
if size > 0:
try:
document =
FitProtocol.readDocument(self.socketReader, size)
tables = Parse(document)
fixture = Fixture()
fixture.listener = self.fixtureListener;
fixture.doTables(tables)
self.counts.tally(self.fixture.counts)
except FitParseException, e:
self.exception(e)
except Exception, e:
self.exception(e)
"""

# this is main
jyFitServer = JyFitServer()
sys.argv.pop(0) # remove first parameter
sys.argv.pop(0) # remove first parameter
sys.argv.pop(0) # remove first parameter
sys.argv.pop(0) # remove first parameter
#print sys.argv
jyFitServer.run(sys.argv)
#return jyFitServer.exitCode()

I have the feeling that I am almost there. Yust something small
missing.
 
M

Mark Fink

I observed something strange when I tried to compile the jython class:
D:\AUT_TEST\workspace\JyFIT\fit>jythonc JyFitServer.py
processing JyFitServer

Required packages:
fitnesse.util
java.io
java.net
fitnesse.components*

Creating adapters:

Creating .java files:
JyFitServer module
JyFitServer extends fit.FitServer

Compiling .java to .class...
Compiling with args: ['C:\\Programme\\Java\\jdk1.5.0_06\\bin\\javac',
'-classpath',
'D:/AUT_TEST/JyFIT_port/fit;D:\\AUT_TEST\\Jython21\\jython.jar;C:\\Programme\\Java\\jdk1.5.0_06\\lib\\tools.jar;C:\\
Java\\jboss-4.0.0\\server\\default\\lib\\mysql-connector-java-2.0.14-bin.jar;C:\\Java\\jboss-4.0.0\\client\\jboss-j2ee.jar;C:\\Java\\jboss-4.0.0\\client\\jboss-client.jar;C:\\Java\\jboss-4.0.0\\client
\\jbosssx-client.jar;C:\\Java\\jboss-4.0.0\\client\\jnp-client.jar;C:\\Java\\jboss-4.0.0\\client\\jnet.jar;C:\\Java\\jboss-4.0.0\\client\\jboss-common-client.jar;C:\\Java\\jboss-4.0.0\\tomcat-4.1.x\\c
ommon\\lib\\servlet.jar;D:\\AUT_TEST\\Jython21\\jython.jar;D:\\AUT_TEST\\fitnesse\\fitnesse.jar;D:\\AUT_TEST\\JyFIT_port;%CLASSPATH%;.\\jpywork;;D:\\AUT_TEST\\Jython21\\Tools\\jythonc;D:\\AUT_TEST\\wo
rkspace\\JyFIT\\fit\\.;D:\\AUT_TEST\\Jython21\\Lib;D:\\AUT_TEST\\workspace\\JyFIT;D:\\AUT_TEST\\fitnesse\\fitnesse.jar;D:\\AUT_TEST\\Jython21',
'.\\jpywork\\JyFitServer.java']
1 D:\AUT_TEST\Jython21\org\python\core\Py.java:989: as of release 1.4,
'assert' is a keyword, and may not be used as an identifier
(try -source 1.3 or lower to use 'assert' as an identifier)
public static void assert(PyObject test, PyObject message) {
^
D:\AUT_TEST\Jython21\org\python\core\Py.java:995: as of release 1.4,
'assert' is a keyword, and may not be used as an identifier
(try -source 1.3 or lower to use 'assert' as an identifier)
public static void assert(PyObject test) {
^
D:\AUT_TEST\Jython21\org\python\core\Py.java:996: ')' expected
assert(test, Py.None);
^
D:\AUT_TEST\Jython21\org\python\parser\PythonGrammar.java:6739: as of
release 1.5, 'enum' is a keyword, and may not be used as an identifier
(try -source 1.4 or lower to use 'enum' as an identifier)
for (java.util.Enumeration enum = jj_expentries.elements();
enum.hasMoreElements();) {
^
D:\AUT_TEST\Jython21\org\python\parser\PythonGrammar.java:6739: as of
release 1.5, 'enum' is a keyword, and may not be used as an identifier
(try -source 1.4 or lower to use 'enum' as an identifier)
for (java.util.Enumeration enum = jj_expentries.elements();
enum.hasMoreElements();) {
^
D:\AUT_TEST\Jython21\org\python\parser\PythonGrammar.java:6740: as of
release 1.5, 'enum' is a keyword, and may not be used as an identifier
(try -source 1.4 or lower to use 'enum' as an identifier)
int[] oldentry = (int[])(enum.nextElement());
^
D:\AUT_TEST\Jython21\org\python\core\Py.java:996: incompatible types
found : org.python.core.PyObject
required: boolean
assert(test, Py.None);
^
D:\AUT_TEST\Jython21\org\python\core\PyBeanProperty.java:36: warning:
non-varargs call of varargs method with inexact argument type for last
parameter;
cast to java.lang.Object for a varargs call
cast to java.lang.Object[] for a non-varargs call and to suppress this
warning
Object value = getMethod.invoke(iself, Py.EmptyObjects);
^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
7 errors
1 warning

ERROR DURING JAVA COMPILATION... EXITING

D:\AUT_TEST\workspace\JyFIT\fit>
Looks like something in the Jython core causes the problem
(org\python\core\Py.java) any Ideas what I can do?
 
K

Kent Johnson

Mark said:
I observed something strange when I tried to compile the jython class:
'assert' is a keyword, and may not be used as an identifier
(try -source 1.3 or lower to use 'assert' as an identifier)
public static void assert(PyObject test, PyObject message) {
Looks like something in the Jython core causes the problem
(org\python\core\Py.java) any Ideas what I can do?

I think jythonc is not compatible with Java 1.5, try compiling with 1.4.

Kent
 
M

Mark Fink

Please enlighten me. This seemed so easy yust inherit from a Java class
overwrite one method - done. At the moment I do not know how to proceed
:-((
Jython or jythonc?
==================
In general is it better to run programms with the jython interpreter or
is it better to compile them first? I had the impression that the
inheritance does not work with the interpreter. Is that right?

2.1 or 2.2a
===========
The programm did not compile with the 2.1 version and Java 1.5. But
with 2.2a it compiled but 2.2a is an alpha version. Assuming the
programm would compile with the Java 1.4 version would it be better
(saver, more stable, performance) to use 2.1 or 2.2a?

Inherit from java baseclass or reimplement the whole thing in jython?
=====================================================================
All the problems with Jython stated when I wanted to inherit from a
Java baseclass. I wounder if I would have more success when
implementing it in pure Jython. Regarding the inheritance I had an
empty wrapper arround the Java baseclass and 70% of the unit test
passed. But the performance was ~ factor 10 slower than using the base
class directly. Does this mean that there is overhead with the
inheritanc construct and that this implementation path would always be
so slow. On the other hand would a 100% Jython solution be faster?

Mark
 
K

Kent Johnson

Mark said:
Please enlighten me. This seemed so easy yust inherit from a Java class
overwrite one method - done. At the moment I do not know how to proceed
:-((

It should be easy.
Jython or jythonc?
==================
In general is it better to run programms with the jython interpreter or
is it better to compile them first? I had the impression that the
inheritance does not work with the interpreter. Is that right?

I personally avoid jythonc, I have not had success with it. Others
apparently have and use it.

Inheritance works fine without jythonc. The limitation in non-compiled
Jython is in the methods that are visible to Java code. Java code will
only see methods of a Jython class that are declared in a Java class or
interface that the Jython class extends or implements.

For example:

Java:

public class Foo {
public int value() { return 3; }
}

public interface Bar {
public int anotherValue();
}

Jython:
class Baz(Foo, Bar):
def value(self): return 5
def anotherValue(self): return 7
def somethingCompletelyDifferent(self): return 42

Now, a Java client that has an instance of Baz will be able to call
baz.value()
baz.anotherValue()
but
baz.somethingCompletelyDifferent()
will not be possible even using Java introspection.

OTOH a Jython client will be able to access all three methods of baz.
2.1 or 2.2a
===========
The programm did not compile with the 2.1 version and Java 1.5. But
with 2.2a it compiled but 2.2a is an alpha version. Assuming the
programm would compile with the Java 1.4 version would it be better
(saver, more stable, performance) to use 2.1 or 2.2a?

IMO Jython 2.2a1 is not near ready for production use. Jython 2.1 is
very stable and usable.
Inherit from java baseclass or reimplement the whole thing in jython?
=====================================================================
All the problems with Jython stated when I wanted to inherit from a
Java baseclass. I wounder if I would have more success when
implementing it in pure Jython. Regarding the inheritance I had an
empty wrapper arround the Java baseclass and 70% of the unit test
passed. But the performance was ~ factor 10 slower than using the base
class directly. Does this mean that there is overhead with the
inheritanc construct and that this implementation path would always be
so slow. On the other hand would a 100% Jython solution be faster?

Inheritance from Java works well and I have never seen performance
problems like this.

Java JUnit uses introspection to find test methods so it won't find
methods of a Jython class.

HTH,
Kent
 
K

Kent Johnson

Mark said:
Alan, Kent, many thanks this really helped!
But there is still a problem I guess with inheritance. I use the java
testsuit supplied with the original to test the server. If I use the
Java FitServer the testsuite can be completed. I commented everything
out from my class and it does not work??

Since you are getting the same error from the Java server and the Jython
subclass maybe you should figure out the Java problem first? It seems to
be a problem making a socket connection of some kind.

Kent
 
M

Mark Fink

Hi Kent,
many thanks for your help! In the meantime I received my "Jython
Essentials" book and hope that I have much fewer questions in the near
future.
One last question for this thread. I tried to inherit from a Java class
and override on method. I figured that this approach was nonsense
because the method used private attributes of the Java class. Now I
read that there is injection used in Jython. Jython uses setter and
getter methods to do the injection, right? Unfortunately the Java class
has no setters and getters for the private members. Is there another
way to override the method besides rewriting the Java class or is this
approach really doomed?

Cheers,
Mark
 
K

Kent Johnson

Mark said:
Hi Kent,
many thanks for your help! In the meantime I received my "Jython
Essentials" book and hope that I have much fewer questions in the near
future.
One last question for this thread. I tried to inherit from a Java class
and override on method. I figured that this approach was nonsense
because the method used private attributes of the Java class. Now I
read that there is injection used in Jython. Jython uses setter and
getter methods to do the injection, right? Unfortunately the Java class
has no setters and getters for the private members. Is there another
way to override the method besides rewriting the Java class or is this
approach really doomed?

I don't know what you mean by injection in this context. But Jython has
a property "python.security.respectJavaAccessibility" which may help -
if you set it to false (on the command line or the Jython registry (see
the docs)) then Jython code can access private members of Java objects.

It seems a bit of a hack but it might help you out. Changing the Java
class to make the private members be protected seems like a better fix
if you can do it.

Kent
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top