Exceptions

Exceptions are caught and thrown in exactly the same way as Java exceptions. If an exception is defined in SIDL, Babel will generate the code for it, and the exception can be thrown in Java. The only difference is that SIDL exception constructor cannot take a String. Instead, the message must be set with SIDL's setNote method, the message is gotten with SIDL's getNote method. This is important because SIDL exceptions inherit from the Java Class Exception. The Java compiler will not give an error if getMessage is called, but the message returned will not have been from SIDL.

The other problem is that regular Java exceptions cannot be passed on by Babel. Of course, it's not possible to throw normal non-SIDL exceptions from a SIDL Java function, the Java compiler will throw an error. (Unless you have changed the Java method ``throws'' statement outside the splicer blocks, which you should never do.) However, Java runtime exceptions, such as ArrayIndexOutOfBoundsException can be thrown. In this case, an error message and stack trace are printed to stderr, the method returns 0, the values of any out or inout arguments are set to NULL, and the program proceeds.

Finally, SIDL Exceptions may be interfaces, where as Java exceptions are always classes. This means Babel allows you to throw an interface. However, in Java we actually need to throw the interface's Wrapper class.

In this example we have a class FibException which implements two exception interfaces, NegativeValueException and TooDeepException. These two Exceptions are thrown by a babelized method named getFib. getFib is a standard recursive Fibonacci number generating function, in which if something goes wrong, it throws one of these two exceptions. First, server side:


public int getFib_Impl ( /*in*/ int n) 
throws NegativeValueException.Wrapper, TooDeepException.Wrapper {
  if (n < 0) {
    FibException fex = new FibException();
    NegativeValueException.Wrapper neg = (NegativeValueException.Wrapper) 
      NegativeValueException.Wrapper._cast(fex);
    neg.setNote("n negative");
    throw neg; 
  }
  
  //  .... Do Fibonacci stuff ....
}

You can see here some of the hoops you have to jump though to throw an interface. First, since we cannot create an interface, or it's Wrapper, directly, we first create a new FibException and cast it to the interface we want. Secondly, we have to refer to the Wrapper's full name in this case, because it is impossible to throw interfaces in Java. Finally, as with all SIDL Exceptions, we use setNote to set the exception's message, as we cannot pass in a message with the constructor.

Next the client side:


try {
  fib.getFib(-1);
} catch (NegativeValueException.Wrapper ex) {
  System.err.println(ex.getNote());
} catch (TooDeepException.Wrapper ex) {
  System.err.println(ex.getNote());
} catch (java.lang.Exception ex) {
  if (((sidl.BaseInterface)ex).isType("sidl.SIDLException")) {
    check(PASS, true, "Unexpected SIDL Exception thrown");
  } else {
    check(PASS, false, "Unexpected and unkown exception thrown");
  }
}

In order to differentiate between the two different interfaces in this case we must catch the Wrappers explicitly by their fully qualified names. In the exceptions regression test we discover the types of the Exceptions by calling the SIDL function isType on them. However, because SIDL can cast between the two interfaces, in this case isType would return true no matter what the exception originally was. The final catch java.lang.Exception ex should not ever be executed in out example code. getFib does not throw any other kinds of exceptions, and babel cannot throw non-SIDL Exceptions. This was included because it demonstrates the most basic way to differentiate a SIDL exception from a Java exception.



babel-0.10.2
users_guide Last Modified 2005-03-23

http://www.llnl.gov/CASC/components
components@llnl.gov