Issue2547

classification
Title: PyException only uses default constructor; doesn't initialize the cause
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.7, Jython 2.5
Milestone:
process
Status: open Resolution: works for me
Dependencies: Superseder:
Assigned To: stefan.richthofer Nosy List: jason_s, jeff.allen, stefan.richthofer, zyasoft
Priority: normal Keywords:

Created on 2017-02-02.02:31:29 by jason_s, last changed 2018-03-23.08:28:41 by jeff.allen.

Messages
msg11060 (view) Author: Jason Sachs (jason_s) Date: 2017-02-02.02:31:28
https://github.com/jythontools/jython/issues/54

If I do this in Jython: (tried with both 2.5.3 and 2.7.0 standalone)

import java.lang.Exception
for k in xrange(10):
   print k
if k > 3: raise java.lang.Exception("Hey")
it works fine; Jython raises a wrapped instance of java.lang.Exception. It appears to be an org.python.core.PyException. Unfortunately this class uses the default constructor of its superclass.

Why does this matter? If the object raised within Jython is a Jython object, rather than a Java exception class, it doesn't matter. But if the object raised within Jython is some Java exception object E, and Jython is embedded within a larger Java program P, then Jython doesn't allow the larger program P to use the standard Throwable.getCause() method to access the Java exception object E: it's been wrapped up opaquely, and unless the program P has special logic that knows about org.python.core.PyException and can somehow access E, it can't benefit from the information contained in E.
msg11063 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2017-02-02.15:14:52
Jason, it would be helpful if you could write a test-example Java-code that catches such a PyException and asserts that the cause is set as expected. Ideally such that we can include it into our test-suite with minimal effort.
Then if there are no concerns I would merge the solution I proposed in https://github.com/jythontools/jython/issues/54.
msg11071 (view) Author: Jason Sachs (jason_s) Date: 2017-02-02.21:54:23
>Jason, it would be helpful if you could write a test-example Java-code that catches

agreed, but unfortunately I can't publish the code my company is using, and it took a lot of work to get it all working together. I can't remember which features need to be present to get it to do this sort of thing...

I suppose there's some sort of minimal test case, if I can get to it I will but that depends on the workload at my job.
msg11074 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2017-02-05.12:45:58
Jason,

I wrote a test-case on my own for this and it appears like Jython already features the behavior you request (maybe this changed since 2.7.0).

Write WrapJavaExceptionTest.java like this:

import org.python.core.PyModule;
import org.python.core.imp;

public class WrapJavaExceptionTest {

	public interface JavaExceptionTester {
		public void raiseTest();
		public void raiseTest2();
	}

	public static String testWrapJavaException() {
		PyModule module = (PyModule) imp.importName("WrapJavaExceptionTest_module", true);
		JavaExceptionTester jt = module.newJ(JavaExceptionTester.class);
		try {
			jt.raiseTest();
			return "no exception";
		} catch (Exception exc) {
			System.out.println("Cause: "+exc.getCause());
			System.out.println("Class: "+exc.getClass());
			return exc.toString();
		}
	}

	public static String testWrapJavaException2() {
		PyModule module = (PyModule) imp.importName("WrapJavaExceptionTest_module", true);
		JavaExceptionTester jt = module.newJ(JavaExceptionTester.class);
		try {
			jt.raiseTest2();
			return "no exception2";
		} catch (Exception exc) {
			System.out.println("Cause: "+exc.getCause());
			System.out.println("Class: "+exc.getClass());
			return exc.toString();
		}
	}
}


Then write WrapJavaExceptionTest_module.py like this:

import WrapJavaExceptionTest
from java.lang import System, RuntimeException

class JavaExceptionTester:
    def raiseTest(self):
        raise RuntimeException("Exceptional message")

    def raiseTest2(self):
        System.getProperty(None)

if __name__ == '__main__':
    print WrapJavaExceptionTest.testWrapJavaException()
    print WrapJavaExceptionTest.testWrapJavaException2()


Run it on current trunk version. You will see that Java catches the exception directly as java.lang.RuntimeException or java.lang.NullPointerException.
Is this scenario still somehow different from what you aim to achieve? In that case, can you modify it to demonstrate the issue?

> I suppose there's some sort of minimal test case, if I can get to it I will but that depends on the workload at my job.

I suppose you'll have to, because it appears I cannot reproduce it ;)
msg11846 (view) Author: Jeff Allen (jeff.allen) Date: 2018-03-23.08:28:40
This may be the same as #1684, where the OP gave us an example and I recently attached a modified version.

The key phrase in Jason's original post is surely "if the object raised within Jython is some Java exception object E, and Jython is embedded within a larger Java program P, then Jython doesn't allow the larger program P to use the standard Throwable.getCause() method".
History
Date User Action Args
2018-03-23 08:28:41jeff.allensetnosy: + jeff.allen
messages: + msg11846
milestone: Jython 2.7.1 ->
2017-02-12 23:59:38stefan.richthofersetresolution: works for me
2017-02-05 12:45:59stefan.richthofersetmessages: + msg11074
2017-02-02 21:54:23jason_ssetmessages: + msg11071
2017-02-02 15:16:40stefan.richthofersetassignee: stefan.richthofer
2017-02-02 15:16:30stefan.richthofersetpriority: normal
nosy: + zyasoft
type: behaviour
milestone: Jython 2.7.1
2017-02-02 15:14:52stefan.richthofersetnosy: + stefan.richthofer
messages: + msg11063
2017-02-02 02:31:29jason_screate