Related
please verify me if I am right: when a program encounters a exception we should write code to handle that exception, the handler should do some recovery job, like rerun the program, but is not just telling us where we went wrong in real world application.
When you throw an exception you're saying:
"Something happened and I can't handle it here. I'm passing the buck!"
When you catch you say:
"Ok I can do something. Perhaps loop around and try again; maybe log an error message".
You can even choose to ignore the error but that's usually discouraged.
In general the thrower captures the state of the failure and the catcher acts on the failure.
In real life, exceptions don't always make error handling easier; but it helps keeps errors out of the main line code path. It's an alternate execution flow. You often hear this: "Exceptions should be used only for exceptional things."
This is a controversial topic, so I expect some to disagree with what I'm going to say.
Exceptions are for exceptional circumstances, namely, the following two classes of problems:
Program Bug
External Problems
In the former case, your program has gotten into a state it shouldn't be in. So you throw an exception and catch it at a level high enough where the program can gracefully continue. In general, this should be fairly high in your program. The reality is, if there's a bug in the middle of an operation, there's not much you can do to recover (after all, if you knew there was a bug, you'd fix it!). Best is to log it, let the user know and move on, if possible. Terminate the current operation, dialog, whatever, or even the whole program.
In the latter case, you are dealing with capricious and fickle universe. Things might go wrong through no fault of your own. In this case, you should try to detect errors as close to the source as you can and deal with them as best you can. If you sending an email to a flaky server results in an exception, it might be reasonable to try again (warning the user). If the database connection goes down, you could try again, but it might be better to give up and kill the current operation. It depends on how well you understand the external problems that might arise and what can actually be done about them.
If you have known error conditions, such as errors in user input or other data sources (e.g., XML parse error, user picked wrong choice on a form, etc.), it's probably best not to throw an exception, but instead gather and report the errors in a more structured fashion. In one project of mine, I have an error reporter class that can gather errors without interrupting program flow. Then those errors can be reported to the user, or logged.
Often times, I think the best approach is not to catch the error, especially if you don't have a specific response for the error. In general, I think the approach of "catch and try again" is flawed. The cause should be identified and corrected. You shouldn't just keep ramming into a brick wall.
Exceptions should be thrown when, and only when, a method/property/whatever is unable to fulfill its contract. The only time an exception should be caught without either rethrowing it or wrapping it in a new exception and throwing that is when the method that caught the exception can fulfill its contract despite the inner method's failure to fulfill its contract. While it may be hard to determine the optimal contract for a routine, once the contract is in place, deciding whether to throw an exception will be easy: do what the contract says.
It really depends on the error and how you want to handle it. In a lot of my automation systems, if something goes wrong, I want the program to send an email out with a specific error and then terminate. Other times I want to catch the error and run a different process to back out data that I had previously entered.
Sounds like you have the general idea down.
I read several posts on exception handling/rethrowing exceptions on here (by looking at the highest voted threads), but I am slightly confused:
-Why would you not want the immediate catch block to handle an exception but rather something above it?
-Also, I read quite frequently that you should only handle exceptions which you can "handle". Does that mean actually doing something about it, such as retrying the operation?
You might want to catch an exception (e.g. file not found) and do some processing - e.g. if you open two files and the second file is missing, you will want to close the first file again before you continue, so that it isn't left open.
You might then want to tell the caller that an error occurred, so you re-throw the same exception or throw a new exception, describing the problem.
In some cases, if you get an exception, your code has no way of knowing if it is an error or not (e.g. if you are asked to load an XML file, but you get a File Not Found exception, is that an error, or should you return a blank XMl result?). In these cases you either want to re-throw the exception, or not handle it all all, and let the calling code decide how to deal with the problem.
Your second point is the answer to the first. Sometimes the lower-level functionality does not know enough about the context of the application to know what the right action should be. For example, if opening a file for reading fails because there is no file of that name, then the application might want to ask for a different file, or abort the whole operation, or whatever. At some level, some part of the application will take the responsibility to do the right thing, unless of course just having the program crash is an acceptable action to take.
Answering to your second question - you need to handle the exception in the immediate block only if can do anything about it: for example close connection to db, close streams, retry or retry with different params, log exception (if there will not be an exception generic handler on the higher levels). Probably only immediate block of code knows such details and can handle them. Calling blocks need to know that the error occurred they might know better what to do with exception.
For example immediate block works with a file. A caller might try to open a file from different locations(In the process of "probing") and ignore several errors as long as at least one succeeds. Another part of code might consider the very first failed attempt as an error. Caller block might chose to notify the user that an error is occurred, probably let her/him know some helpful info on how to fix the problem. Also it is nice to provide the means to notify support of the problem – some kind of dialog allowing user to ask for help, describe problem and send a message. In this message you might attach logs, some info about the environment like OS, versions of frameworks, programs, browser capabilities whatever you need to diagnose the problem (if user permits you to do so).
An exception is "handled" if the method which caught it can satisfy its construct. For example, the contract for a routine OpenRecentDocument which is called when the user selects an item from the "recent files" menu might specify that it must either (1) successfully open a document window, or (2) try unsuccessfully to open a document window, roll back any side-effects resulting from the attempt, and notify the user of the what happened. If OpenRecentDocument catches an exception while trying to open the file, but it is able to roll back any side effects from the attempt and notify the user, the routine will have satisfied its contract and should thus return without rethrowing the exception.
One unfortunate "gotcha" in all this is that there isn't any standard means by which routines which throw an exception can indicate whether their attempted operation has resulted in side-effects which could not be rolled back. There is no inherent way, for example, of distinguishing an InvalidOperationException which occurs unexpectedly while updating a shared data structure (which would imply that other open documents may have been corrupted), from an InvalidOperationException which occurs while updating the data associated with the document being loaded, even if one has anticipated the latter possibility and provided for it. The best one can do is either try to catch any InvalidOperationException which might occur in the latter situation near the spot that it occurs, encapsulate that exception in some other exception type, and throw that, or else have data structures maintain an "object corrupted" flag and ensure that if a data structure is found to be corrupt, all future operations on it will fail as cleanly as possible. Neither approach is at all elegant. The more common approach, which could probably be described as "hope for the best", usually works.
My VS just told me;
Warning 2 CA1031 : Microsoft.Design : Modify 'Program.Main(string[])' to catch a more specific exception than 'Exception' or rethrow the exception.
Why should I do that? If I do so, and don't catch all exceptions to handle them, my program crashes with the all-popular report-screen. I don't want my users to get such error-crap!
Why should I not catch all exceptions at once to display a nice warning to the user saying: "Something went wrong, don't care about it, I will handle it, just be patient"?
Edit: Just saw I have a dupe here, sorry for that Dupe
Edit2: To clarify things; I do exit the program after any exception has been catched! I just don't want my user to see that "report to microsoft" dialog that show up when an unhandled exception is raised in a console-application!
Swallowing exceptions is a dangerous practice because:
It can cause the user to think something succeeded when it actually failed.
It can put your application into states that you didn't plan for.
It complicates debugging, since it's much harder to find out where the failure happened when you're dealing with bizarre/broken behavior instead of a stack trace.
As you can probably imagine, some of these outcomes can be extremely catastrophic, so doing this right is an important habbit.
Best Practice
First off, code defensively so that exceptions don't occur any more than necessary. They're computationally expensive.
Handle the expected exceptions at a granular level (for example: FileNotFoundException) when possible.
For unexpected exceptions, you can do one of two things:
Let them bubble up normally and cause a crash
Catch them and fail gracefully
Fail Gracefully?
Let's say you're working in ASP.Net and you don't want to show the yellow screen of death to your users, but you also don't want problems to be hidden from the dev team.
In our applications, we usually catch unhandled exceptions in global.asax and then do logging and send out notification emails. We also show a more friendly error page, which can be configured in web.config using the customErrors tag.
That's our last line of defense, and if we end up getting an email we jump on it right away.
That type of pattern is not the same as just swallowing exceptions, where you have an empty Catch block that only exists to "pretend" that the exception did not occur.
Other Notes
In VS2010, there's something called intellitrace coming that will allow you to actually email the application state back home and step through code, examine variable values at the time of the exception, and so on. That's going to be extremely useful.
Because programs that swallow (catch) exceptions indiscriminately, (and then continue), cannot be relied upon to do what it is they are expected to do. This is because you have no idea what kind of exception was "ignored". What if there was an overflow or memory access error that causes the wrong amount to be debited from a financial account? What if it steers the ship into the iceberg instead of away from it ? Unexpected failures should always cause the application to terminate. That forces the development process to identify and correct the exceptions it finds, (crashes during demos are a wonderful motivator), and, in production, allows appropriately designed backup systems to react when the software experiences an "unexpected" inability to do what it was designed to do.
EDIT: To clarify distinctions between UI components, and service or middleware componentrs.
In Service or Middleware components, where there is no user interacting with the code component from within the same process space that the code is running in, the component needs to "pass On" the exception to whatever client component imnitiated the call it is currently processing. No matter the exception, it should make every possible attempt to do this. It is still the case, however, tjhat in cases where an unexpected, or unanticipated exception occurs, the component should finally terminate the process it is running in. For anticipated or expected exceptions, a velopment analysis should be done to determine whether or not, for that specific exception, the component and it's host process can continue to operate (handling future requests), or whether it should be terminated.
You should handle the exact exceptions you are capable of handling and let all others bubble up. If it displays a message to the user that means you don't quite know what you can handle.
Having worked on equipment used by emergency responders, I would rather the user see an ugly error message than to accidently swallow an exception that misleads the user into believing everything is "ok". Depending on your application, the consequence could be anything from nothing to a lost sale to a catastrophic loss of life.
If a person were going to catch all exception, show a better error dialog, and then quit the application, that's ok.. but if they are going to continue running after swallowing an unknown exception, I would fire a person for that. It's not ok. Ever.
Good coding is about practices that assume humans make mistakes. Assuming all "critical" exceptions have been caught and handled is a bad idea.
Simple answer: you are supposed to fix your bug. Find the place that throws the exception and unless it is beyond your control - fix it.
Also catching (without rethrowing) all kinds of exception violates exception neutrality. In general you do not want to do this (although catching exceptions in main does look like special case)
Since your warning message shows that this is in Main(), I'll assume that in lower levels, you do catch only more specific Exceptions.
For Main(), I'd consider two cases:
Your own (debugging) build, where you want all the exception information you can get: Do not catch any Exceptions here, so the debugger breaks and you have your call stack,
Your public releases, where you want the application to behave normally: Catch Exception and display a nice message. This is always better (for the average user) than the 'send report' window.
To do this nicely, just check if DEBUG is defined (and define it, if VS doesn't do this automatically):
#if DEBUG
yadda(); // Check only specific Exception types here
#else
try
{
yadda();
}
catch (Exception e)
{
ShowMessage(e); // Show friendly message to user
}
#endif
I'd disable the warning about catching general Exceptions, but only for your Main() function, catching Exception in any other method is unwise, as other posters have said already.
There is a way to suppress certain messages from code analysis. I've used this for this exact reason (catching the general exception for logging purposes) and it's been pretty handy. When you add this attribute, it shows you've at least acknowledged that you are breaking the rule for a specific reason. You also still get your warning for catch blocks that are incorrect (catching the general exception for purposes other than logging).
MSDN SuppressMessageAttribute
I am all for catching specific known exceptions and handling state...but I use general catch exceptions to quickly localize problems and pass errors up to calling methods which handle state just fine. During development as those are caught, they have a place right next to the general exception and are handled once in release.
I believe one should attempt to remove these once the code goes into production, but to constantly be nagged during the initial code creation is a bit much.
Hence turn off (uncheck) the warning by the project settings as found in Microsoft.CodeQuality.Analyzers. That is found in the project settings under Code Analysis:
All answers are good here. But I would mention one more option.
The intention of author to show some fancy message is understandable.
Also, default Windows error message is really ugly. Besides, if application is not submitted to "Windows Excellence Program" the developer will not receive information about this problem. So what is the point to use default runtime handler if it does not help?
The thing here is that default exception handler of CLR host ( https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/9x0wh2z3(v=vs.90)?redirectedfrom=MSDN ) works in a very safe way. The purpose of it is clear: log the error, send it to developer, set the return code of your process and kill it. The general way of how to change that is to write your own host. In this case you can provide your own way of handling exceptions.
Still, there is an easy solution which satisfies CA1031 and still most of your needs.
When catching the exception, you can handle it your own way (log, show the message etc) and at the end you can set the process result code and do the exit (using the mix of Thread.Abort and "Exit" methods, for example). Still, at the end of your catch block you can just put "throw;" (which will never be called because of ThreadAbortedException, but will satisfy the rule). Still there are some cases, like StackOverflowException, which can't be handled like that and you will see that default message box, for fixing which you need to fallback to custom CLR host option.
Additionally, just for your information, you application can run several threads (besides that one which execute Main method). To receive exceptions from all of them you can use AppDomain.UnhandledException. This event does not allow you to "mark" the exception as handled, still you can freeze the thread using Thread.Join() and then do the job (log, msgbox, exit) using another (one more) thread.
I understand all this looks a little tricky and may be not right, but we have to deal with the implementation of AppDomain.UnhandledException, ThreadAbortException, CorruptedState exceptions and default CLR host. All of this eventually does not leave us much of choice.
When you catch general exceptions, you get the side effect of potentially hiding run-time problems from the user which, in turn, can complicate debugging. Also, by catching general exception, you're ignoring a problem (which you're probably throwing elsewhere).
You can set up your try catch to catch multiple different behavior types and handle the exception based on the type. For most methods and properties in the framework, you can also see what exceptions they are capable of throwing. So unless you are catching an exception from an extremely small block of code, you should probably catch specific exceptions.
In VS you can setup a custom error page to show your users when something goes wrong instead of catching it in a try-catch. I'm assuming since you're using VS that you're using ASP .NET. If so add this tag to your Web.Config under the System.Web tag:
<customErrors mode="RemoteOnly" defaultRedirect="~/CustomErrorPage.aspx" redirectMode="ResponseRewrite" />
You can also catch all uncaught exceptions in the Global.asax file (if you don't have it already: Right-click on web project, select Add Item, and search for it). There are a bunch of application wide event handlers in that file like "Application_Error" that catches every exception that isn't caught within your application so you don't have to use Try-Catch all the time. This is good to use to send yourself an email if an exception occurs and possibly redirect them to your homepage or something if you don't want to use the customErrors tag above.
But ultimately you don't want to wrap your entire application in a try-catch nor do you want to catch a general Exception. Try-catches generally slow down your application and a lot of times if you catch every general exception than it could be possible that you wouldn't know a bug exists until months or years later because the try-catch caused you to overlook it.
What are the best practices for exceptions over remote methods?
I'm sure that you need to handle all exceptions at the level of a remote method implementation, because you need to log it on the server side. But what should you do afterwards?
Should you wrap the exception in a RemoteException (java) and throw it to the client? This would mean that the client would have to import all exceptions that could be thrown. Would it be better to throw a new custom exception with fewer details? Because the client won't need to know all the details of what went wrong. What should you log on the client? I've even heard of using return codes(for efficiency maybe?) to tell the caller about what happened.
The important thing to keep in mind, is that the client must be informed of what went wrong. A generic answer of "Something failed" or no notification at all is unacceptable. And what about runtime (unchecked) exceptions?
It seems like you want to be able to differentiate if the failure was due to a system failure (e.g. a service or machine is down) or a business logic failure (e.g. the user does not exist).
I'd recommend wrapping all system exceptions from the RMI call with your own custom exception. You can still maintain the information in the exception by passing it to your custom exception as the cause (this is possible in Java, not sure about other languages). That way client only need to know how to handle the one exception in the cause of system failure. Whether this custom exception is checked or runtime is up for debate (probably depends on your project standards). I would definitely log this type of failure.
Business type failures can be represented as either a separate exception or some type of default (or null) response object. I would attempt to recover (i.e. take some alternative action) from this type of failure and log only if the recovery fails.
In past projects we'd catch all service layer (tier) exceptions at the very top of the layer, passing the application specific error codes/information to the UI via DTO's/VO's. It's a simple approach in that there's an established pattern of all error handling happening in the same place for each service instead of scattered about the service and UI layers.
Then all the UI has to do is inspect the DTO/VO for a flag (hasError?) and display the error message(s), it doesn't have to know nor care what the actual exception was.
I would always log the exception within my application (at the server side as defined in your question).
I would then throw an exception, to be caught by the client. If the caller could take corrective action to prevent the exception then I would ensure that the exception contained this information (e.g. DateTime argName must not be in the past). If the error was caused by some outage of a third party system then I might pass this information up the call stack to the caller.
If, however, the exception was essentially caused by a bug in my system then I would structure my exception handling such that a non-informative exception message (e.g. General failure) was used.
Here's what I did. Every Remote Method implementation catches all Exceptions on the server side and logs them. Then they are wrapped in a Custom Exception, which will contain a description of the problem. This description must be useful to the client, so it won't contain all the details of the caught Exception, because the client doesn't need them. They have already been logged on the server side. Now, on the client, these Exceptions can be handled how the user wishes.
Why I chose using Exceptions and not return codes is because of one very important drawback of return codes: you can't throw them to higher levels without some effort. This means you have to check for an error right after the call and handle it there. But this may not be what I want.
I've seen the following code many times:
try
{
... // some code
}
catch (Exception ex)
{
... // Do something
throw new CustomException(ex);
// or
// throw;
// or
// throw ex;
}
Can you please explain the purpose of re-throwing an exception? Is it following a pattern/best practice in exception handling? (I've read somewhere that it's called "Caller Inform" pattern?)
Rethrowing the same exception is useful if you want to, say, log the exception, but not handle it.
Throwing a new exception that wraps the caught exception is good for abstraction. e.g., your library uses a third-party library that throws an exception that the clients of your library shouldn't know about. In that case, you wrap it into an exception type more native to your library, and throw that instead.
Actually there is a difference between
throw new CustomException(ex);
and
throw;
The second will preserve the stack information.
But sometimes you want to make the Exception more "friendly" to your application domain, instead of letting the DatabaseException reach your GUI, you'll raise your custom exception which contains the original exception.
For instance:
try
{
}
catch (SqlException ex)
{
switch (ex.Number) {
case 17:
case 4060:
case 18456:
throw new InvalidDatabaseConnectionException("The database does not exists or cannot be reached using the supplied connection settings.", ex);
case 547:
throw new CouldNotDeleteException("There is a another object still using this object, therefore it cannot be deleted.", ex);
default:
throw new UnexpectedDatabaseErrorException("There was an unexpected error from the database.", ex);
}
}
Sometimes you want to hide the implementation details of a method or improve
the level of abstraction of a problem so that it’s more meaningful to the caller
of a method. To do this, you can intercept the original exception and substitute
a custom exception that’s better suited for explaining the problem.
Take for example a method that loads the requested user’s details from a text file. The method assumes that a text file exists named with the user’s ID and a suffix of “.data”. When that file doesn’t actually exist, it doesn’t make much sense to throw a FileNotFoundException because the fact that each user’s details are stored in a text file is an implementation detail internal to the method. So this method could instead wrap the original exception in a custom exception with an explanatory message.
Unlike the code you're shown, best practice is that the original exception should be kept by loading it as the InnerException property of your new exception. This means that a developer can still analyze the underlying problem if necessary.
When you're creating a custom exception, here's a useful checklist:
• Find a good name that conveys why the exception was thrown and make sure that the name ends with the word “Exception”.
• Ensure that you implement the three standard exception constructors.
• Ensure that you mark your exception with the Serializable attribute.
• Ensure that you implement the deserialization constructor.
• Add any custom exception properties that might help developers to understand and handle your exception better.
• If you add any custom properties, make sure that you implement and override GetObjectData to serialize your custom properties.
• If you add any custom properties, override the Message property so that you can add your properties to the standard exception message.
• Remember to attach the original exception using the InnerException property of your custom exception.
You typically catch and re-throw for one of two reasons, depending on where the code sits architecturally within an application.
At the core of an application you typically catch and re-throw to translate an exception into something more meaningful. For example if you're writing a data access layer and using custom error codes with SQL Server, you might translate SqlException into things like ObjectNotFoundException. This is useful because (a) it makes it easier for callers to handle specific types of exception, and (b) because it prevents implementation details of that layer such as the fact you're using SQL Server for persistence leaking into other layers, which allows you to change things in the future more easily.
At boundaries of applications it's common to catch and re-throw without translating an exception so that you can log details of it, aiding in debugging and diagnosing live issues. Ideally you want to publish error somewhere that the operations team can easily monitor (e.g. the event log) as well as somewhere that gives context around where the exception happened in the control flow for developers (typically tracing).
I can think of the following reasons:
Keeping the set of thrown exception types fixed, as part of the API, so that the callers only have to worry about the fixed set of exceptions. In Java, you are practically forced to do that, because of the checked exceptions mechanism.
Adding some context information to the exception. For example, instead of letting the bare "record not found" pass through from the DB, you might want to catch it and add "... while processing order no XXX, looking for product YYY".
Doing some cleanup - closing files, rolling back transactions, freeing some handles.
Generally the "Do Something" either involves better explaining the exception (For instance, wrapping it in another exception), or tracing information through a certain source.
Another possibility is if the exception type is not enough information to know if an exception needs to be caught, in which case catching it an examining it will provide more information.
This is not to say that method is used for purely good reasons, many times it is used when a developer thinks tracing information may be needed at some future point, in which case you get try {} catch {throw;} style, which is not helpful at all.
I think it depends on what you are trying to do with the exception.
One good reason would be to log the error first in the catch, and then throw it up to the UI to generate a friendly error message with the option to see a more "advanced/detailed" view of the error, which contains the original error.
Another approach is a "retry" approach, e.g., an error count is kept, and after a certain amount of retries that's the only time the error is sent up the stack (this is sometimes done for database access for database calls that timeout, or in accessing web services over slow networks).
There will be a bunch of other reasons to do it though.
FYI, this is a related question about each type of re-throw:
Performance Considerations for throwing Exceptions
My question focuses on "Why" we re-throw exceptions and its usage in application exception handling strategy.
Until I started using the EntLib ExceptionBlock, I was using them to log errors before throwing them. Kind of nasty when you think I could have handled them at that point, but at the time it was better to have them fail nastily in UAT (after logging them) rather than cover a flow-on bug.
The application will most probably be catching those re-thrown exceptions higher up the call stack and so re-throwing them allows that higher up handler to intercept and process them as appropriate. It is quite common for application to have a top-level exception handler that logs or reports the expections.
Another alternative is that the coder was lazy and instead of catching just the set of exceptions they want to handle they have caught everything and then re-thrown only the ones they cannot actually handle.
As Rafal mentioned, sometimes this is done to convert a checked exception to an unchecked exception, or to a checked exception that's more suitable for an API. There is an example here:
http://radio-weblogs.com/0122027/stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html
If you look at exceptions as on an alternative way to get a method result, then re-throwing an exception is like wrapping your result into some other object.
And this is a common operation in a non-exceptional world. Usually this happens on a border of two application layers - when a function from layer B calls a function from layer C, it transforms C's result into B's internal form.
A -- calls --> B -- calls --> C
If it doesn't, then at the layer A which calls the layer B there will be a full set of JDK exceptions to handle. :-)
As also the accepted answer points out, layer A might not even be aware of C's exception.
Example
Layer A, servlet: retrieves an image and it's meta information
Layer B, JPEG library: collects available DCIM tags to parse a JPEG file
Layer C, a simple DB: a class reading string records from a random access file. Some bytes are broken, so it throws an exception saying "can't read UTF-8 string for record 'bibliographicCitation'".
So A won't understand the meaning of 'bibliographicCitation'. So B should translate this exception for A into TagsReadingException which wraps the original.
THE MAIN REASON of re-throwing exceptions is to leave Call Stack untouched, so you can get more complete picture of what happens and calls sequence.