I am looking for a design pattern to handle Exception instances received as method arguments.
To put some context into the question, I am using GWT and have various asynchronous handlers that usually come in a form similar to:
public interface AsyncCallback<T> {
void onFailure(Throwable caught);
void onSuccess(T result);
}
So, the onFailure method receives a Throwable instance that I need to handle.
Now, I have a number of exceptions I can receive in this method, for example
ConstraintViolationException
TimeoutException
NoSuchElementException
In my handling code I could of course write the following:
void handleException(final Exception e) {
if(e instanceof TimeoutException) {
handleTimeout();
} else if (e instanceof NoSuchElementException) {
handleInvalidElement();
} else {
stopAndCatchFire();
}
}
But to my eye, that looks very ugly. The large if..else if chain combined with heavy usage of instanceof seems like something that should be avoided.
I thought that maybe I could use the try...catch construct to handle the Exception using something like the following:
void handleException(final Exception e) {
try {
throw e;
} catch (TimeoutException te) {
handleTimeout();
} catch (NoSuchElementException nsee) {
handleInvalidElement();
} catch (Exception ex) {
stopAndCatchFire();
}
}
But this seems like an abuse somehow. Do you see any downsides to the second approach or another approach I could go with to avoid the first case?
Could you not have a dictionary of exceptionHandlers keyed by the type of exception they handle, then when you get a exception you look in the dictionary for the handler for the exception type. If there is one, then pass the exception to the handler, if there isn't then use the default handler.
So your handler becomes something like this:
void handleException(final Exception e) {
if (handlers.containsKey(e.getType())
{
handlers[e.getType()].handle(e);
}
else
{
defaultHandler.handle(e);
}
}
My Java is a bit rusty, so the example is c-sharpy but should be simple enough to translate (though I remembered not to capitalise the first letter of everything :))
This approach should have the advantage that you can add new handlers simply.
It will however suffer if you have the same handler for sub types, as you will have to register each subtype explicitly.
To get around this issue simply make each handler responsible for making the decision about whether it can handle an exception:
public interface ExceptionHandler
{
bool canHandle(Exception e);
void handle(Exception e)
}
then just put the handlers in a list an iterate asking each one if it can handle the current exception and when you find one that can, get it to handle it.
But to my eye, that looks very ugly. The large if..else if chain combined with heavy usage of instanceof seems like something that should be avoided.
I don't agree. I think this snippet of code is using both language constructs exactly how they were intended. If the code becomes unmanageable (too many clauses) then you should question the approach to error handling generally, rather than the specifics of this method. At that stage you might want to consider AOP.
The second approach on the other hand is horrible ;)
You can make it more elegant just by handling the if statements inside the exceptions inside the function.
void handleException(Exception e){
handleOne(e)
handleTwo(e)
...
}
It looks prettier. Of course, every function is always called, but its first line is just an if statement. There are variations - e.g. make your handle functions guava function objects, put them in a list, and iterate through them until you get the first one that returns "true". Something like:
public class handlerOne implements Function<Exception, Boolean> {
Boolean apply(Exception input) {
return handlerOne();
}
}
Then your handle function can be something like:
void handleException(Exception e){
list<Function<Exception, Boolean> list = Object.getHandlers(); //store your handlers somewhere
for(Function<Exception, Boolean> f : list){
if(f.apply(e)){
break
}
}
}
That way you insure only one handler which works is called, and you can control the order by changing the order of the list, since the list iterator will return them in order.
Control flow on exceptions should be avoided, and should certainly not be in the onFailure. the onFailure method should be as simple as possible.
Modify whatever code is run asynchronously to handle the exception cases there. The ElementNotFound-exception could be handled by just checking if an element exists prior to doing anything. Timeout-exception could be handled by surrounding the code that can timeout (calling a webservice or something)?) by a try .. catch block.
Then extend the result-type T to contain extra information that a timeout occurred or an element is not found - if needed.
Related
I have a method which under certain conditions may throw an exception, but most of the time will not. I would like to require anyone who calls this method to catch the exception if they call it under the "dangerous" conditions, but not have to worry about it under "safe" conditions.
public static boolean dangerousSituation; // set somewhere else
public sometimesDangerousMethod() throws MyException {
// some code
// may throw MyException if dangerousSituation == true
// will never throw MyException if dangerousSituation == false
}
otherMethod() {
dangerousSituation = false;
sometimesDangerousMethod(); // shouldn't have to worry about MyException
// if it can't possibly happen
dangerousSituation = true;
try {
sometimesDangerousMethod(); // should be required to handle
// MyException if it may possibly happen
} catch(MyException e) {
// handle MyException
}
}
That is, I would like to require a try/catch block around sometimesDangerousMethod() if and only if dangerousSituation == true.
The reason I want this is because I don't want to bother developers with exception handling if they stick to safe situations anyway. But of course, if a developer does use a dangerous situation, the compiler should let him know.
Is there some way to get this behavior in Java?
I have considered breaking up sometimesDangerousMethod() into two methods: one dangerous, one safe. But I don't think this makes sense since this would require developers to be aware of two methods which do basically the same thing.
The functionality you're looking for doesn't exist. You can either split it into two methods, or your coworkers will have to use a try-catch. Sorry, but sometimes the answer is just "No".
#mypetlion is accurate on the most part.
There are a couple of other options for you to consider is:
Would it be possible to handle the exception inside of sometimesDangerousMethod() instead of otherMethod()? If so, then you could pass in the logging/metric object to the method, try/catch inside of the method, and log an error message or update a metric when this occurs. This way, you don't have to worry about try/catch in the case that the exception doesn't occur.
You could break it up into 2 methods like #mypetlion mentioned and with a bit of organization, it may be good enough code:
`
public class Solution {
public static boolean dangerousSituation; // set somewhere else
public void notDangerousMethod(){
// will never throw MyException
}
public void dangerousMethod() throws MyException {
// throws MyException
}
public void sometimesDangerousMethod() throws MyException {
if(dangerousSituation){
dangerousMethod();
} else {
notDangerousMethod();
}
}
public void otherMethod() {
dangerousSituation = false;
// Option 1:
if(dangerousSituation){
try{
dangerousMethod();
} catch(MyException e) {
// handle MyException
}
} else {
notDangerousMethod();
}
// Option 2:
try {
sometimesDangerousMethod(); // should be required to handle
// MyException if it may possibly happen
} catch(MyException e) {
// handle MyException
}
}
`
Depending on contents of sometimesDangerousMethod(), this may be overkill. If it is a few very simple lines of logic, it might be worth it to implement your original design. I don't think the developers would mind :)
You're missing the point of the word Exception. Your code should not throw an Exception unless there is an exceptional situation. Properly designed code that consumes your code still needs to handle the possibility of an exceptional situation.
You shouldn't worry so much about the users of your method having to worry about exceptions.
If your method can fail for whatever reason, it should declare the exception (or use an unchecked exception) and throw the exception if it really fails. That's exactly what exceptions are for.
So I think dangerousSituation is in fact a very dangerous flag. In the code you propose, setting the flag translates to "do not tell me if the method fails [because I know better than the method's implementation that there will not be a failure]".
So, the only reason for not throwing can be a method that will surely succeed. And any decent Java developer should know how to handle exceptions (typically by letting them pass through to a top level where all exceptions are caught and logged).
I have dozens of methods that I want to wrap with the same try/catch handling. I think lambdas can help me out here, but I'm having difficulty figuring out the syntax.
Here's the context of what I'm trying to achieve.
method1(..., result -> method2(result, ...));
method2 is a handler for the results of method1. I would like to wrap method2 with a common try/catch statement that's common to a large number of handlers, without having to copy/paste the statement to all handlers.
Note: These are unchecked exceptions.
*edit - Concrete example of what I'm trying to do.
I'm using Vert.x, and they use a common design pattern of Handlers. Here's an example of their SQL interface
query(String sql, Handler<AsyncResult<ResultSet>> resultHandler)
Handler is a simple 1 function interface:
void handle(E event)
So basically, the query defined in "sql" is executed, and the results are sent to the resultHandler. Here would be an example of this in use:
connection.query("SELECT * from table1", asyncResult -> {
// do something with results
}
The above uses their documentation's standard coding style. I personally prefer to handle the results in named functions various reasons, so it changes to:
connection.query("SELECT * from table1", asyncResult -> method1(asyncResult));
void method1(AsyncResult<ResultSet> asyncResult) {
// do something with results
}
I do not have control over the query() interface, so I'm stuck with this pattern. I'm not sure if Tagir's solution will work in this context, but I'll play around with it in the morning.
*edit2 - I should note that I'm trying to wrap method1 in the above example in the exception wrapper, so ideally, I'd add the wrapper call inside the query() call. So what I'm looking for is something like:
connection.query("SELECT * from table1", wrap(asyncResult -> method1(asyncResult)));
Obviously, I can't use it that way, because it'll evaluate the original lambda as a parameter, but conceptually, that's where I want the wrapping to be added.
You may use Runnable functional interface to implement the method which handles exceptions:
public static void handleExceptions(Runnable r) {
try {
r.run();
}
catch(RuntimeException ex) {
ex.printStackTrace();
}
}
And call it like this:
handleExceptions(() -> method2(foo, bar));
If your method2 produces a result, you should determine what will be the default result in case if exception occurred (and you don't rethrow it in the handler). You may use the Supplier functional interface for such case:
public static <T> T handleExceptions(Supplier<T> r, T defaultValue) {
try {
return r.get();
}
catch(RuntimeException ex) {
ex.printStackTrace();
return defaultValue;
}
}
And call like this:
// set result to null if exception occurred
result = handleExceptions(() -> method2(foo, bar), null);
Or
// do not modify the result if exception occurred
result = handleExceptions(() -> method2(foo, bar), result);
We need to have two functions. They do the same thing but one handles the exceptions and one throws the exception. Note: If to handle exception, the exception has to be handled in the commonFunc() below. It would not work to handle the exception in functionHandlesEx() because to handle the function it needs the variable only available in commonFunc(). In order to re-use code, we got the following. Do you see any problem with it (I can see one problem is: the function throws exception but actually no exception is thrown when isExceptionHandled is true----but Java allows this)? Any better way to do this? We are in Java 6. Thanks.
public void functionThrowsEx() throws Exception e
{
commonFunc(false); //false means does not handle exception
}
public void functionHandlesEx()
{
try
{
commonFunc(true); //true means handle exception
}
catch (Exception e)
{
// do nothing as exception handled
}
}
private void commonFunc(final boolean isExceptionHandled) throws Exception
{
try
{
....
}
catch (Exception e)
{
if (isExceptionHandled)
{
//handle the exception
}
else
{
throw e;
}
}
}
This seems like an overly complicated approach to handling the exception. I understand its toy code to show what you are doing, but I haven't encountered many reasons to create nested calls in order to handle exceptions.
Ideally, the code that can cause the exception should have the means to handle the exception in it, using try...catch, and maybe finally. This logical flow looks like it would be pretty complex in a non-trivial application, and would lead to increased complexity and difficulty in debugging.
You should get rid of the two functions, and avoid nesting try/catch blocks. If you must nest them, make it has straigtfoward as possible by keeping the logic in the same method.
From the code, I'm guessing you want to handle the exception differently based on the state of the program. This code is too complex, and will be difficult to understand for a non trivial app. A better way would be to keep functionHandlesEx and put the exception recovery logic in the handler function.
public void functionHandlesEx() {
try {
//logic here;
}
}
catch (Exception e) {
if(iWantToHandleException) {
//handle exception
}
//do nothing otherwise. Use the finally block for anything else they have in common.
}
}
This is much simpler to understand, and it shouldn't be too hard to refactor it into this form.
I have a method which is getting an exception as a parameter to a particular method. This method needs to do perform different logic based on the type of exception. Between below two ways of handling this.. what is the most efficient way (is there a third better way).. and why
public void processException(Exception ex) {
try {
throw ex;
} catch(CustomException e1) {
//do something
} catch (CustomException2 e2) {
//do something else
}
}
or
public void processException(Exception ex) {
if (ex instanceof CustomException) {
// do something
} else if (ex instanceof CustomException2) {
// do something else
}
}
Efficiency aside, the second way is preferred, because the exception is not thrown in a non-exceptional situation. The first way to "dispatch" uses exception throwing in a regular control flow, which makes it harder to read your program.
Besides, the two methods are not identical: the first program must be declared as throwing a checked exception, because not all subtypes are handled by the catch blocks.
If you are dealing with custom exceptions that your program defines, you have a way to avoid checking the subtype: since Exception objects are regular classes, you could add a package-visible method to them, and have them implement a package-visible interface holding that method. Exceptions would then be able to override that method, letting you use a regular "virtual" dispatch rather than checking for the exact class type at runtime.
Here is an illustration of this approach: let's say you want your exceptions to write themselves to a log file. You can do this as follows:
interface LoggableException {
void logToFile();
}
public class CustomExceptionOne extends Exception implements LoggableException {
...
public void logToFile() {
// Do something
}
}
public class CustomExceptionTwo extends Exception implements LoggableException {
...
public void logToFile() {
// Do something else
}
}
public void processException(Exception ex) {
if (ex instanceof LoggableException) {
LoggableException lEx = (LoggableException)ex;
lEx.logToFile();
}
}
The first one is a very bad idea. Logic should not be expressed as exception catching. They're expensive, whether you realize it or not.
I don't like the second one, either. When you see if/else logic, you should think about polymorphism.
Obviously the second option is better. All the Exceptions are eventually objects and it is better, safe and recommended to perform instance of check to determine the type of object.
Throwing and catching Exceptions are expensive operations and should only occur in exceptional circumstances. In addition, your method to handle the exception is probably being called because the exception was already thrown. I wouldn't throw it again.
Either instanceof, or overloaded processException like rgettman suggests. Another alternative is
public void processException(Exception e) {
Class eClass = e.getClass();
if (eClass == CustomeException.class) { // This exception is most likely.
// do something
} else if (eClass == CustomException2.class) {
// do something
} else if (eClass == CustomException3.class) {
// do something
} else if (eClass == CustomException4.class) {
// do something
}
}
I would suggest short circuiting the if/else if statements with the most likely exception class.
I am currently working on the maintenance of a piece of code that is a little bit "Exception Happy." Basically, ever method or anything throws Exception. I'm going to work to take care of that, but, in the meantime, I am wondering what is the best way to handle individual exceptions within a smaller block of code, such as a method. Is it better to do something like this:
public void aMethod()
try {
//Lots of code in here. Many lines.
} catch(Exception e) {
// TODO - Handle All Exceptions, but fairly generically
}
}
Or something like this:
public void bMethod() {
try {
// One line of code.
} catch(Exception e) {
// TODO - Handle a specific Exception (may even involve rethrowing it with more information)
}
// More code.
try {
// Another line of code.
} catch(Exception e) {
// TODO - Handle another specific exception.
}
}
I realize this is a pretty basic question, but after looking at hundreds of methods with Exceptions coming out of every one, I'm starting to wonder how best to handle all of them and what a best practice may be here.
First off, you should only put code in try/catch blocks that is exception worthy. For instance, having an unexpected value is not necessarily an exception, but trying to read from a file that doesn't exist is.
To answer your main question, you should put the exceptionable code in the same try {} block and catch specific questions in order of granularity in multiple catch blocks after the main try.
//Regular code that doesn't need to be covered by a try/catch block
try {
//critical code only
} catch (NullPointerException npe) {
//Code
} catch (RandomException re) {
//code
} catch (Exception e) {
//code
}
The answer to your question is: it depends.
if the code in the try block is coherent where it makes no sense to proceed in the event of an error, the first approach is best
if the code is taking seperate steps that are relatively unrelated (parsing numbers for instance) and can be recovered without aborting the rest of the method the seconds appraoch makes sense
A general remark on the code you inherited; it sounds like exceptions are abused to pass state around, I would refactor so that exceptions are caught at the spot where they can be handled and introduce return values or attributes to handle the state.
your bMethod isn't very useful illustration. Try to reprase it. Anyway, you have two options:
catch exceptions and log them.
catch exceptions and throw new RuntimeException(ex) (rethrow a runtime exception, setting the original as a cause)
Also, you will need to differentiate between exceptions. If your system has many custom exceptions, they are probably defined for a reason, and specific behaviour is expected when one of them is thrown.
If the try/catch block isn't adding useful information, just allow the method to throw the exception and have it handled where the caller can sensibly do something with the exception. This could cut down the number of try/catch significantly (by an order of magnitude).
BTW a trick for rethrowing any exception is.
try {
// do something
} catch (Throwable t) {
Thread.currentThread().stop(t); // rethrow any exception.
}
In addition to the suggestions already made you may also want to consider extracting try/catch blocks from the "meat" of the function.
public void delete(Page page) {
try {
deletePageAndAllReferences(page);
}
catch (Exception e) {
logError(e);
}
}
private void deletePageAndAllReferences(Page page) throws Exception {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
private void logError(Exception e) {
logger.log(e.getMessage());
}
This lets you focus your attention on the function you are really interested in without the exception handling getting in your way.