|
Sorry for opening old wounds (and the lengthy post) but...if you're one of the many who participated previously...... Various posts have discussed how to "catch" or "monitor" java errors in RPG applications. As suggestions ranged from simply using the MONITOR opcode to setting Environment variables, I thought I'd share another option. First, as Barbara Morris suggests in the following post: http://archive.midrange.com/rpg400-l/200309/msg00071.html There does appear to be a limitation in the RPG/Java interface where exceptions are not "thrown" to STDERR. While Barbara suggests the future possibility of adding an environment variable triggering the RPG runtime to call the JNI's "ExceptionDescribe" function, I would opt to have this as the default behavior verses adding yet another environment variable. Just my 2 cents... Secondly, there are java methods that, even when called by the RPG runtime, do "throw" errors to STDERR (by default). Some that I use regularly are in IBM's MQSeries Java classes. In lieu of direct RPG calls, you could use the JNI to invoke java methods verses traditionally prototyped method calls. This then provides the option to "throw" errors to STDERR via "ExceptionDescribe". While this may provide a layer of granularity in error handling, it does require a fair amount of extra coding. Next, none of the above enables your RPG application to directly access STDERR. While previous posts on this topic have demonstrated how, using an environment variable, you can redirect STDERR output to an IFS file, this technique also inclusively redirects STDOUT. If you don't insert the "os400.stdout=file:" entry in your SystemDefault.properties file, STDOUT output vanishes. As this approach also assigns STDERR & STDOUT redirection for the system or session, this may not be desirable at a particular application level (no to mention any IFS housekeeping). In an effort to provide some sense of error handling granularity in RPG, I prefer to use a java technique that is reminiscent of re-directing S/38 command output to QTEMP (S/38 programmers probably remember those days prior to IBM adding all the API functions). Starting with JDK 1.2, java provides the "java.io.File.createTempFile" method. This allows java applications to create a work file in the "/tmp" directory. Additionally, it allows the application to specify predefined "prefix" & "suffix" values for the file. When specifying a NULL suffix value, the suffix defaults to ".tmp". For STDERR files (createTempFile serves more than STDERR) I prefer to use the prefix of "STDERR", thus temporary files are named in the form of "STDERRnnnnn.txt". Also for STDERR, I recommend combining the "createTempFile" call with a "java.io.File.deleteOnExit" call. This instructs the JVM to dynamically purge your temporary file when the JVM (not your program) ends. Once you've constructed (and retrieved the label of) your temporary file, you can use the "java.lang.System.setErr" method to redirect all "thrown" STDERR output to your file. Well that takes care of redirecting STDERR output, but what how does that provide my RPG program access to the errors? Simple. You associate your STDERR file with Input Stream, Reader and Buffer handles for later reading. There are no restrictions against "reading" STDERR. For simplicity and re-use, I encapsulate the creation and reading of STDERR in subprocedures. Assume the following snippet has successfully created and redirected STDERR to a temporary file. In addition, corresponding stream, reader and buffer handles have been established with STDERR. Where: Thingclass = java.lang.Class (Object) JLT = 'java/lang/Thing' ASCII signature JNIEnv_P = Pointer to JVM JNI_Error = 'java.lang.Throwable' (Object) errmsg = 'java.lang.String' (Object) Using the JNI to invoke a non-existent method called "java.lang.Thing": C eval Thingclass = FindClass (JNIEnv_P:JLT) C EVAL JNI_error = ExceptionOccurred(JNIEnv_P) C if JNI_error <> *NULL C callp ExceptionDescribe(JNIEnv_P) C callp ExceptionClear(JNIEnv_P) C callp JavaErr C endif results in execution of subprocedure JavaErr: P JavaErr B D JavaErr PI * C dou errmsg = *NULL * C Monitor C eval errmsg = readLine(Buff_Reader) * C if errmsg = *NULL C ITER C endif * (java.lang.String.length) C EVAL String_long = GetStringLng(errmsg) C on-error C ITER C endmon * C eval text = *BLANKS * convert Java string to character (java.lang.String.getBytes) C callp GetStringChar(errmsg:0:String_long: C text:0) * C enddo * P JavaErr E Because 2 STDERR entries are "thrown", field "text" would contain: java.lang.NoClassDefFoundError: java/lang/Thing then: java/lang/Throwable.<init>(Ljava/lang/String;)V+4 (Throwable.java:94) Unfortunately, defining a prototype for the "java.lang.Thing" method fails to provide any feedback to STDERR or your RPG program (except RNX0301). This, I suspect, is what Barbara Morris described in the a fore mentioned post. Lastly, this approach may not be as flexible as using "catch" in Java, however, it does provide RPG programmers with some ability for monitoring errors encountered when invoking java methods from your RPG program. Michael Rooney CitiGroup International Tampa, Florida P.S. If there is still enough interest on this topic, I will post a sample program demonstrating the entire technique.
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.