While working on some support recently for our compiler (Micro Focus COBOL compiler that is), I became annoyed with the lack of a reasonable error messages/stack trace output from our Java/COBOL Object support.
I have no idea why our default exception handler for Java exceptions just displays a such a simple message with little or no information.
For those who have not seen it, display something similar to:
Exception 65537 not trapped by the class javaexceptionmanager.
Description: "Java exception"
Test error
Hit T to terminate program. Hit any other key to continue.
instantiated - test
Exception 65537 not trapped by the class javaexceptionmanager.
Description: "Java exception"
Test error
Hit T to terminate program. Hit any other key to continue.
Luckily for me and you, we do expose a mechanism for replacing the default exception handler.
Anyway, with very little effort I created a different “default” system exception handler that display this instead:
instantiated - test 1
java.lang.Exception: Test error
at SimpleClass.TestException(SimpleClass.java:10)
WARNING: JavaException: Test error
instantiated - test 2
java.lang.Exception: Test error
at SimpleClass.TestException(SimpleClass.java:10)
WARNING: JavaException: Test error
The key difference being that a Java stack trace is included, boy did this help me.
The program below is the code that implements the exception handler. I am sure someone else can take this example and make it much nicer and provide more features but for this blog I will keep it simple.
$set ooctrl (+p-f) case
program-id. ExceptionCatcher.
class-control.
EntryCallback is class "entrycll"
JavaExceptionManager is class "javaexpt"
ExceptionManager is class "exptnmgr"
Javasup is class "javasup"
.
working-storage section.
01 wsCallback object reference.
01 wsIterator object reference.
01 theJavaException object reference.
local-storage section.
01 filler pic x. *> dummy storage item to allow recursion
linkage section.
01 lnkException object reference.
01 lnkErrorObject object reference.
01 lnkErrorTextCollection object reference.
01 lnkErrorNumber pic x(4) comp-5.
01 anElement object reference.
procedure division.
*>---Set up system level Exception handler
invoke EntryCallback "new" using
z"JException"
returning wsCallback
end-invoke
invoke ExceptionManager "register" using
javaexceptionmanager
wsCallback
end-invoke
invoke EntryCallback "new" using z"DispError"
returning wsIterator
end-invoke
goback.
entry "Jexception" using
lnkException
lnkErrorNumber
lnkErrorTextcollection
.
invoke javasup "exceptionOccurred"
returning theJavaException
end-invoke
if theJavaException not equal null
invoke theJavaException "printStackTrace"
end-if
invoke lnkErrorTextCollection "do" using wsIterator
goback.
.
entry "DispError" using anElement
display "WARNING: JavaException: " with no advancing
invoke anElement "display"
display " "
goback.
.
To use the above code, you just have to first cut-paste to code into a file called ExceptionCatcher.cbl and include this in your project, and then add the directive INITCALL”ExceptionCatcher”, then away you go.
My test programs for the above example are:
$set ooctrl (+p-f) case
program-id. jtest.
class-control.
SimpleClass is class "$JAVA$SimpleClass"
.
working-storage section.
01 theInstance object reference.
local-storage section.
01 filler pic x. *> dummy storage to allow the local entry
procedure division.
*>---Instantiate the class
invoke SimpleClass "new" returning theInstance
display "instantiated - test 1"
invoke theInstance "TestException"
display "instantiated - test 2"
invoke theInstance "TestException"
stop run.
and the Java class itself:
import java.lang.* ;
public class SimpleClass {
public SimpleClass() { }
public void TestException() throws Exception {
throw new Exception ("Test error" );
}
}
References: Studio Enterprise 6.0 Document for COBOL/Java Interop