The nsjava::try Command


Usage:

nsjava::try script ?catch exception_pair script? ?finally script?

The nsjava::try command provides access to Java's try-catch-finally construct. In Tcl, the catch command is used to manage exceptional runtime conditions. Unfortunatly, the catch command is not able to deal with multiple error conditions without complex and ugly code. This makes it difficult to use the catch command with Java methods because Java methods can raise exceptions of multiple types. The nsjava::try command solves this problem by providing a way to manage multiple exceptional conditions in Tcl, just like Java programmers can do with the try-catch-finally construct.

The script argument is evaluated in the interpreter. If a Tcl error or a Java exception is raised during the evaluation of script then each catch clause is searched to determine if a match to the exceptional condition is found. A match is found if a Tcl error was generated and the first element of the exception_pair list is TclException, or if the error was a Java exception and the first element of the exception_pair list is a Java class name that exactly matches or is a superclass of the thrown exception. If a match for the exceptional condition is found then the script argument is executed to handle the exception. After each catch clause has been processed the optional finally clause will be checked and if given, the script for the finally clause will be executed. It is important to note that if a finally clause is given, the script for the finally clause will be executed even if the exceptional condition was not caught in any of the catch clauses and that after the evaluation the original exceptional condition will be raised again. It is also important to note that at least one catch clause must be given if the optional finally clause is not provided.

Examples:

Lets assume we have a Tcl proc called "bad" that raises an exceptional condition.

proc bad {} { do something bad }

We could use the catch command around an invocation of bad to protect the script from errors.

if {[catch {bad} err]} {
    puts "error in procedure bad: $err"
}
If we wanted to do the same thing using the nsjava::try command we could use the following code.
nsjava::try {
    bad
} catch {TclException err} {
    puts "error in procedure bad: $err"
}

Of course this example does not really demonstrate why the nsjava::try command is any better then using catch. To see why we need the nsjava::try command we need to look at an example where multiple exceptional conditions could be raised.

Suppose we wanted to call a Tcl command that was implemented with a combination of Tcl and Java code. For this example we assume a jcombo command already exists in the interpreter. We could then use the nsjava::try command to manage exceptional conditions that could be raised while processing the jcombo command.

nsjava::try {
    jcombo
} catch {TclException e} {
    puts "a Tcl error occurred"
} catch {IOException e} {
    puts "a Java IOException occurred"
} catch {NumberFormatException e} {
    puts "a Java NumberFormatException occurred"
}

It is possible to use the catch command to catch both Tcl and Java errors, but the code would be very complex and would not be as easy to understand as this simple example.

An experienced user might notice that the name of the exception type in the above example is not fully qualified. For instance, the fully qualified name of IOException is java.io.IOException. The nsjava::try command will accept either form of the exception type name. The following two examples are equivalent.

nsjava::try {
    #some code
} catch {java.io.IOException e} {
}

nsjava::try {
    #some code
} catch {IOException e} {
}

Here is an example of using nsjava::try with a finally clause. The finally script will be evaluated once the main script has been evaluated and all of the exception handlers have been checked.

nsjava::try {
    #some code
} catch {TclException e} {
    #handle Tcl error
} finally {
    #do local cleanup
}

The finally clause can also be used without a catch clause.

nsjava::try {
    #some code
} finally {
    #do local cleanup
}

One important thing to note about the nsjava::try command is that as long as the finally script does not raise an exceptional condition, the value returned by the command will be the return value of the main script or a catch script. This example demonstrates the behavior.

nsjava::try {
    set i 1
} finally {
    set j 2
}

The value returned by the nsjava::try command in this example will be 1 not 2. If an exceptional condition is raised inside the finally script, it will be propagated normally.

Copyright © 1997-1998 Sun Microsystems, Inc.