title: rethrow java exception with new message, preserving the exception type if it is in the method declaration list
body: <p>I am trying to create a helper method that will eliminate the need of having code like this:</p>
  
  <pre><code>void foo() throws ExceptionA, ExceptionB, DefaultException {
    try {
       doSomething(); // that throws ExceptionA, ExceptionB or others
    } catch (Exception e) {
      if (e instanceof ExceptionA)
          throw new ExceptionA("extra message", e);
      if (e instanceof ExceptionB)
          throw new ExceptionB("extra message", e);
  
      throw new DefaultException("extra message", e);
    }
  }
  </code></pre>
  
  <p>The problem is that I need to maintain the throws list in the function declaration and in the body of the function at the same time. I am looking how to avoid that and to make changing the throws list sufficient and my code to looks like:</p>
  
  <pre><code>void foo() throws ExceptionA, ExceptionB, DefaultException {
    try {
       doSomething(); // that throws ExceptionA, ExceptionB or others
    } catch (Exception e) {
      rethrow(DefaultException.class, "extra message", e);
    }
  }
  </code></pre>
  
  <p>Where rethrow method will be smart enough to recognize the throws list from the method declaration.</p>
  
  <p>This way when I change the list of type that my method propagates in the throws list I to not need to change the body.</p>
  
  <p>The following is a function that could solve the problem. The problem is because it does not know what type of exception it will throw its throws declaration has to say Exception, but if it does this, the method that is going to use it will need to specify it as well, and the whole idea of using the throws list goes to hell.</p>
  
  <p>Any suggestions how this could be solved?</p>
  
  <pre><code>@SuppressWarnings("unchecked")
  public static void rethrow(Class&lt;?&gt; defaultException, String message, Exception e) throws Exception
  {
    final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
  
    final StackTraceElement element = ste[ste.length - 1 - 1];
  
    Method method = null;
  
    try {
       method = getMethod(element);
    } catch (ClassNotFoundException ignore) {
       // ignore the Class not found exception - just make sure the method is null
       method = null;
    }
  
    boolean preserveType = true;
  
    if (method != null) {
  
       // if we obtained the method successfully - preserve the type 
       // only if it is in the list of the thrown exceptions
       preserveType = false;
  
       final Class&lt;?&gt; exceptions[] = method.getExceptionTypes();
  
       for (Class&lt;?&gt; cls : exceptions) {
          if (cls.isInstance(e)) {
             preserveType = true;
             break;
          }
       }
    }
  
    if (preserveType)
    {
       // it is throws exception - preserve the type
       Constructor&lt;Exception&gt; constructor;
       Exception newEx = null;
       try {
          constructor = ((Constructor&lt;Exception&gt;) e.getClass().getConstructor());
          newEx = constructor.newInstance(message, e);
       } catch (Exception ignore) {
          // ignore this exception we prefer to throw the original
          newEx = null;
       }
  
       if (newEx != null)
          throw newEx;
    }
  
    // if we get here this means we do not want, or we cannot preserve the type
    // just rethrow it with the default type
  
    Constructor&lt;Exception&gt; constructor;
    Exception newEx = null;
  
    if (defaultException != null) {
       try {
          constructor = (Constructor&lt;Exception&gt;) defaultException.getConstructor();
          newEx = constructor.newInstance(message, e);
       } catch (Exception ignore) {
          // ignore this exception we prefer to throw the original
          newEx = null;
       }
  
       if (newEx != null)
          throw newEx;
    }
  
    // if we get here we were unable to construct the default exception
    // there lets log the message that we are going to lose and rethrow
    // the original exception
  
    log.warn("this message was not propagated as part of the exception: \"" + message + "\"");
    throw e;
  }
  </code></pre>
  
  <hr>
  
  <p>Update 1:
  I can use <code>RuntimeException</code> to avoid the need of throws declaration, but in this case I am losing the type of the exception which is one of the most important points.</p>
  
  <p>Ideas how I can resolve this?</p>