I am running a multithreaded testing program and would like to add some extra details to exceptions throw for it to be clear which thread is the one that threw the exception. In order to do this I created the following generic function to take any Callable function as a parameter and return it's value; however, in the case it throws an exception, it is caught and extra details are added to the Exception message and then thrown again for the calling function to catch.
public <U> U enhanceThrownException(@NonNull Callable<U> callable) throws Exception {
try {
return callable.call();
} catch (Exception e) {
throw new Exception(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
}
}
Now this works great for what I needed it for, however, I do not want calling functions to need to catch a generic Exception. I wanted to clearly specify exceptions that I know the function will throw, so I added to the code and have this:
public <U, V extends Exception> U enhanceThrownException(@NonNull Callable<U> callable,
Class<V> exceptionType) throws V {
try {
return callable.call();
} catch (Exception e) {
try {
throw (V) e.getClass().getDeclaredConstructor(String.class, Throwable.class)
.newInstance(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
} catch (ReflectiveOperationException rException) {
e.printStackTrace();
throw new RuntimeException(controller.getFullScenarioMessage(rException.getLocalizedMessage()), rException);
}
}
}
This works perfectly for a function that has only one throwable exception, but if I want to handle multiple thrown exceptions, how would I go about doing so? Is it necessary to do this, or would using the generic Exception case be enough? Also, if I can specify, is it possible to get the possible thrown exceptions form the function itself without the user needing to input them as parameters? The following does not work because all entered Exceptions would have to be of the same type, which is kind of useless since different Exception derivatives are of different types.
public <U, V extends Exception> U enhanceThrownException(@NonNull Callable<U> callable,
Class<V> exceptionType,
Class<V>... exceptionTypes) throws V {
try {
return callable.call();
} catch (Exception e) {
try {
throw (V) e.getClass().getDeclaredConstructor(String.class, Throwable.class)
.newInstance(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
} catch (ReflectiveOperationException rException) {
e.printStackTrace();
throw new RuntimeException(controller.getFullScenarioMessage(rException.getLocalizedMessage()), rException);
}
}
}
(Update)
After looking further into this, I realized I may have been overthinking it all. I simply created an custom Exception class:
public class EnhancedException extends Exception {
public EnhancedException(String message, Throwable cause) {
super(message, cause);
}
}
And then I edited the previous code to:
public <U> U enhanceThrownException(@NonNull Callable<U> callable) throws EnhancedException {
try {
return callable.call();
} catch (Exception e) {
throw new EnhancedException(controller.getFullScenarioMessage(e.getLocalizedMessage()), e);
}
}
If needed, the calling functions can check for this custom Exception and then further check if the cause is an Exception it is specifically looking for. This would actually just work with a generic Exception, but maybe there are some uses for having a custom Exception class.
I might have solved my own issue, but if anyone believes there is a better approach or just has some good programming practice advice, I'm all ears.