#714 FFI: How to dal with java exceptions

tcolar Mon 10 Aug 2009

I was wondering what happens to exceptions that happened in a java FFI ?

Do they get wrapped in, or replaced by, a Fan (unchecked) exception ? which one ?

Also if a method signature has a checked exception and I want to overload it? I suppose I just skip the exception in the fan signature ... but if i want to catch it, what do i try/catch on?

Will the Fan exception thrown have useful infos about the base cause(java) exception ?


brian Mon 10 Aug 2009

That is a good question.

Common Java exceptions are mapped to their Fan equivalents:

NullPointerException          => NullErr
ClassCastException            => CastErr
IndexOutOfBoundsException     => IndexErr
IllegalArgumentException      => ArgErr
InterruptedException          => InterruptedErr
IOException                   => IOErr
UnsupportedOperationException => UnsupportedErr

I should probably document that.

The Fan exception wraps the Java exception with Err.actual - but I don't really have a way to expose that cleanly. If I did you still wouldn't be able to catch on a Java type, but then you could use is:

catch (Err e)
  if (e.java is SomeJavaException) ...
  else e.trace

You might want to poke around "Err.java"

I'm open to other suggestions

tcolar Mon 10 Aug 2009

I think that's ok. I'm thinking it would be nice to get the Java exception "class" somehow, I think not as a type(we don't want t propagate java types inside fan), but would be nice if we could at least get it as a string like say:

Err.type := "java.lang.NoSuchMethodException" // java exception or Err.type := "InterruptedErr" // fan exception

I don't know if that's too nice, but that would allow to do something like

   //some java ffi call that might throw an exception
   if(e.actual?.type == "java.lang.NoSuchMethodException") {/*do something special*/}

I'm not sure that's too good, but lots of Java API's have pretty complicated exceptions(often checked at that), as you know, so a way to ignore/handle them would be useful maybe even a must in some case. At the same time we don't want FFI stuff to leak deep into fan. I don't know much about C#, but i guess same idea would work.

Not sure if this implementation is clean enough, open to better ideas :)

brian Mon 10 Aug 2009

OK, I added two new methods to fanx.interop.Interop

 * Given a Java exception instance translate to a Fan exception.
 * If the exception maps to a built-in Fan exception then the
 * native Fan type is used - for example NullPointerException will
 * return a NullErr.  Otherwise the Java exception is wrapped
 * as a generic Err instance.
public static Err toFan(Throwable ex)

 * Given a Fan exception instance, get the underlying Java exception.
public static Throwable toJava(Err err)

You can use these methods to switch b/w Fan and Java exceptions:

using [java] java.lang
using [java] fanx.interop
class Play
  Void main() {
    try { Class.forName("badname") }
    catch (Err e) {
      je := Interop.toJava(e)
      echo(je is ClassNotFoundException)

This program will print:

java.lang.ClassNotFoundException: badname

tcolar Mon 10 Aug 2009

Thanks, that's nice & simple.

Should be pretty helpful when dealing with Exception-happy Java libs.

Login or Signup to reply.