9

I'm trying to write a job scheduling system in GWT that maintains an array of exceptions (Class<? extends Exception>[] exceptions), that might be resolved by retrying the job. For this, if the scheduler catches an exception, I need to see if this exception matches one of the classes in the array. So, I would like to have a function like this:

boolean offerRetry(Exception exception) {
    for (Class<? extends Exception> e: exceptions)
        if (e.isInstance(exception)) return true;
    return false;
}

Unfortunately Class.isInstance(...) isn't available in GWT.

Is there a good work-around for this? My current best guess is something like this:

public static boolean isInstance(Class<?> clazz, Object o) {
    if ((clazz==null) || (o==null)) return false;
    if (clazz.isInterface()) throw new UnsupportedOperationException();
    Class<?> oClazz = o.getClass();
    while (oClazz!=null) {
        if (oClazz.equals(clazz)) return true;
        oClazz = oClazz.getSuperclass();
    }
    return false;
}

Unfortunately, this approach does not support testing against interfaces, and I don't have any idea how to fix that either as Class.getInterfaces() is also not available. But would this approach at least work the same way as Java's Class.isInstance in all other cases, excluding interfaces? Specifically, if I look at GWT's source for Class.java, the getSuperclass() method contains a check of isClassMetadataEnabled(), which might return false (but I don't know in which cases), as it contains a comment saying "This body may be replaced by the compiler".

Or is there a better way entirely to do this?

Markus A.
  • 12,349
  • 8
  • 52
  • 116
  • GWT does not support reflection but you can use `instanceof` operator. – Ashish Apr 22 '14 at 21:13
  • @Ashish Unfortunately `instanceof` does not work in this case. It can only be used to check against a fixed class type that is known at compile-time (e.g. `instanceof String` or `instanceof List`) but cannot be used to check against a variable of type `Class` (e.g. `instanceof Exception.class` doesn't work. Neither does `Class> ref = Exception.class; return (myTestObject instanceof ref);`). Which is why `isInstance(...)` was introduced in Java in the first place... – Markus A. Apr 22 '14 at 22:24
  • Thanks for clarification. I will remove my answer. – Ashish Apr 23 '14 at 00:28

2 Answers2

5

I use following code:

 public static <T> boolean isInstanceOf(Class<T> type, Object object) {
    try {
         T objectAsType = (T) object;
     } catch (ClassCastException exception) {
         return false;
     }
     return true;
 }
Sergey Bondarev
  • 410
  • 4
  • 7
  • That should work. Very clever. +1. :) Unfortunately, creating, throwing, and catching exceptions is an extremely expensive operation in Java (and I would assume it's not much better in JavaScript). So, depending on how many class-types I need to check, this might get very slow... – Markus A. Sep 23 '14 at 18:10
  • You know? I wonder what the GWT compiler does with this, since JavaScript is dynamically typed. To reproduce the same exact results as Java, it probably needs to perform the cast check itself in extra code... Maybe looking at that code could provide a great solution? – Markus A. Sep 23 '14 at 18:15
  • Actually, this code wouldn't help me at all, unfortunately, since when I iterate over the exception classes as in the first code-example in the question, in this function would simply be erased to `Exception`, and thus the function would always return true... For some reason, SO no longer allows un-up-voting an answer, though, so you're in luck... :) But thanks anyways: When I get the chance, I'll look at what GWT does with this code and that could be very helpful. – Markus A. Sep 23 '14 at 18:29
  • I'll think about it. I'll let you know if I'll found something. – Sergey Bondarev Sep 23 '14 at 19:01
  • It really doesn't work. Sorry for that =) It's interesting. I'll try to make some other workaround. – Sergey Bondarev Sep 26 '14 at 11:35
  • Till now I see only one solution: to write custom generator which will provide class metainfo (about parent classes and interfaces) for specific classes (you could mark them by special interface). Notify me please if you'll find some other solution. Thank you. – Sergey Bondarev Oct 01 '14 at 14:00
  • I've been using the code that I posted in the original question and it's been working fine. The only limitation it seems to have is that it doesn't support interfaces, which is acceptable for my use-case... – Markus A. Oct 01 '14 at 16:55
0

Maybe something like this would help:

boolean offerRetry(Exception exception) {
   try{
      throw exception;
   } catch (SpecException se) {
      return true;
   } catch (SpecException1 se1) {
      return true;
   ...
   } catch (Exception e) {
      return false;
   }   
}

It depends on how you construct the array of exceptions. If the java 7 stuff works properly then you could put all exceptions in one catch:

boolean offerRetry(Exception exception) {
   try{
      throw exception;
   } catch (SpecException | SpecException1 | ... se) {
      return true;
   } catch (Exception e) {
      return false;
   }   
}
dexter
  • 530
  • 7
  • 19
  • I like the creativity in this idea, but unfortunately it won't help me accomplish what I need to, since I won't be able to do `catch (exceptions[0] | exceptions[1] | ... e)`. For one, `catch` only supports class identifier constants that are known at compile-time, and, if it did support dynamic class-types read from variables, I still wouldn't know before hand how many exceptions the array might contain, i.e. how many `exceptions[...]` to include in the catch statement. – Markus A. Apr 30 '14 at 00:39