16

I am working as a contractor designing enterprise Java application for my client in the role of a technical lead. The application will be used by end users and there will be a support team who will support the application when we leave.

The other technical leads with whom I am working are under the impression that exception handling will make the code dirty. The system should throw checked exceptions only from the Service tier and the rest of the code should throw runtime exceptions from all other tiers so that there is no need to handle the unchecked exceptions.

What is a need to ever throw a unchecked exception in a business application?

From my experience in the past about runtime exceptions:

1) Unchecked exceptions make the code unpredictable because they do not show up even in the Javadoc.

2) Throwing Unchecked exceptions in a business application is non-sense because when you throw it and it goes straight on Users face, how do you explain it to the user? I have seen enough of web application which show 500 -Internal Error. Contact Administrator which means nothing for a end user or to the support team managing the application.

3) Throwing runtime exceptions forces the users of the class throwing the exception to walk through the source code to debug and see why the exception is thrown. This can only be avoided if the Javadoc of the runtime exception happens to be excellently documented which I find is never a case.

6
  • Can you explain what is Service Tier? Is the layer farthest from the user, or nearest to the user?
    – Manoj R
    Jan 25, 2013 at 7:03
  • Why does this question not fit on SO? Jan 25, 2013 at 8:38
  • @Manoj R: Neither. A service tier or layer is where business rules and logic are exectued, separated from both details of DB technology and client presentation. Jan 25, 2013 at 9:14
  • 7
    Unchecked exceptions [...] do not show up even in the Javadoc. => they will appear if you document them with the @throws tag, which by the way is a good practice.
    – assylias
    Jan 25, 2013 at 10:46
  • 4
    @SureshKoya Effective Java, Item 62: Document all exceptions thrown by each method. Extract: Use the Javadoc @throws tag to document each unchecked exception that a method can throw, but do not use the throws keyword to include unchecked exceptions in the method declaration.
    – assylias
    Jan 25, 2013 at 16:55

5 Answers 5

13

Checked exceptions are a failed expriment in language design. They force you to have extremely leaky abstractions and dirty code. They should be avoided as much as possible.

As for your points:

1) Checked exceptions make the code dirty, and no less unpredictable because they show up everywhere.

2) How is a checked exception being shown to the user any better? The only real difference between checked and unchecked exceptions is technical and affects only the source code.

3) Ever heard of stack traces? They tell you exactly where the exception was thrown, no matter whether it's checked or unchecked. Actually, checked exceptions tend to be worse for debugging because they're often wrapped which leads to longer and uglier stack traces, or even lost atogether because the wrapping was done wrong.

There are two kinds of exceptions: those that occur "normally" and are typically handled very close to where they occur, and those that are reallly exceptional and can be handled generically in a very high layer (just abort the current action and log it / show an error).

Checked exceptions were an attempt to put this distinction into the language syntax at the point the exceptions are defined. The problems with this are

  • The distinction is really up to the caller, not the code that throws the exception
  • It's completely orthogonal to the semantic meaning of an exception, but tying it to the class hierarchy forces you to mix the two
  • The whole point of exceptions is that you can decide at what level to catch them without risking to lose an error silently or having to pollute the code at intermediate levels or ; checked exceptions lose that second advantage.
4
  • 1. Well in case of an unchecked exception, you will not even know if a call could result in a unchecked. 2. When you said "It's completely orthogonal to the semantic meaning of an exception, but tying it to the class hierarchy forces you to mix the two", I suppose you meant call hierarchy instead of class hierarchy. Jan 25, 2013 at 16:14
  • 2
    @Suresh Koya: No, I meant class hierarchy, the fact that a declaration SQLException extends Exception means that choosing to throw an SQLException because an error has to do with DB access automatically means the exception is checked. And you can document unchecked exceptions in Javadoc comments just fine. Works out well for all other languages. Jan 25, 2013 at 20:20
  • 2
    @MichaelBorgwardt "Checked exceptions are a failed expriment in language design" , is it your personal opinion if not I would like to read more about it. Any authentic link would be great help.
    – Vipin
    Aug 11, 2014 at 7:43
  • 2
    @Vipin: It's my personal opinion, but one that many other people share, e.g. Bruce Eckel: mindview.net/Etc/Discussions/CheckedExceptions - and the fact that no other language has adopted checked exceptions in the 20 years since Java was introduced speaks for itself... Aug 11, 2014 at 16:08
2

My view is that what type of exception is thrown is dependant on what your code is doing.

I throw checked exceptions when I expect they can happen quite often (users entering dodgy data for example) and I expect the calling code to handle the situation.

I throw unchecked/runtime exceptions (not as often as checked) when I have a rare situation which I do not expect the calling code to handle. An example might be some sort of weird memory related error which I never expect to occur. Unchecked are the sorts of errors that you expect to bring down the application.

No exception should appear in front of a user without some level of support. Even if it's just a "please cut and paste this error dump to an email". Nothing is more annoying to a user than being told there is an error, but being given no details or action they can take to initiate it being fixed.

My guess is that the philosophy you mention comes from one of two sources:

  • Lazy programmers trying to avoid doing work.
  • Or developers who have had to support code which went the other way. i.e. over-error-handling. The sort of code that contains large amounts of exception handling, much of which does nothing, or even worse, is used for flow control and other incorrect purposes.
3
  • If something can happen quite often, it's not exception. But agreed that error should not be thrown, which the user has no clue about.
    – Manoj R
    Jan 25, 2013 at 6:52
  • I agree on your philosophy. On an application which you are developing for users, what will be a need for throwing a Runtime exception? Jan 25, 2013 at 15:53
  • Also, Even if a Runtime exception is thrown, I prefer the convention @assylias pointed to. Jan 25, 2013 at 15:55
1

If you do not want unchecked runtime exceptions, then why are you using java? There is the possibility of runtime exceptions almost everywhere - notably NullPointerException, ArithmeticException, ArrayIndexOutOfBounds exceptions, etc.

And when you once read the log files of some J2EE system, like, for instance, a SAP NetWeaver installation, you'll see that such exceptions happen literally all the time.

2
  • From Java language specification: "The runtime exception classes (RuntimeException and its subclasses) are exempted from compile-time checking because, in the judgment of the designers of the Java programming language, having to declare such exceptions would not aid significantly in establishing the correctness of programs. Many of the operations and constructs of the Java programming language can result in runtime exceptions." Jan 25, 2013 at 15:57
  • 1
    The runtime exception that you are talking are those which arise from Java since Java runtime system does not have a clue of why you are trying to do the specific call. Eg: A NullPointerException would arise if you are calling a method which is null. In that case the Java runtime system does not have a right word for the programmers folly and would slap the caller with a NullPointerException. The sad part is caller has sold the Netweaver product to you and you as a user are now a victim of poor programming. The testers are to equally blame since they did not do all the boundary tests. Jan 25, 2013 at 16:30
1

There are a few rules for exception handling that you should bear in mind. But first, you need to remember that exceptions are part of the interface exposed by the code; document them. This is especially important when the interface is a public one, of course, but it's a very good idea in private interfaces as well.

Exceptions should only be handled at the point where the code can do something sensible with them. The worst handling option is to do nothing at all about them, which should only be done when that is exactly the correct option. (When I have such a situation in my code, I include a comment to that effect so I know not to worry about the empty body.)

The second worst option is to throw an unrelated exception without the original attached as a cause. The issue here is that the information within the original exception that would allow diagnosis of the problem is lost; you're creating something that nobody can do anything with (other than complain that “it doesn't work”, and we all know how we hate those bug reports).

Much better is logging the exception. That lets someone find out what the problem is and fix it, but you should only log the exception at the point where it would otherwise be lost or reported over an external connection. That's not because logging more often is a major problem as such, but rather because excessive logging means you just get the log consuming more space without containing more information. Once you've logged the exception, you can report a précis to the user/client with a good conscience (as long as you also include the time of generation — or other correlation identifier — in that report so that the short version can be matched up with the detail if necessary).

The best option is, of course, to completely handle the exception, dealing with the error situation in its entirety. If you can do this, by all means do it! It might even mean that you can avoid having to log the exception.

One way to handle an exception is to throw another exception that provides a higher-level description of the problem (e.g., “failed to initialize” instead of “index out of bounds”). This is a good pattern so long as you don't lose the information about the cause of the exception; use the detailed exception to initialize the cause of the higher-level exception or log the detail (as discussed above). Logging is most appropriate when you're about to cross an inter-process boundary, such as an IPC call, because there's no guarantee that the low-level exception class will be present at all on the other end of the connection. Keeping as an attached cause is most appropriate when crossing an internal boundary.

Another pattern you see is catch-and-release:

try {
    // ...
} catch (FooException e) {
    throw e;
}

This is an anti-pattern unless you've got type constraints from other catch clauses that mean you can't just let the exception go past on its own. Then it's just an ugly feature of Java.

There's no real difference between checked exceptions and unchecked ones other than the fact that you must declare checked exceptions that cross method boundaries. It's still a good idea to document unchecked exceptions (with the @throws javadoc comment) if you know they're being thrown deliberately by your code. Don't deliberately throw java.lang.Error or its subclasses (unless you're writing a JVM implementation).

Opinion: An unexpected error case always represents a bug in your code. Checked exceptions are a way of managing this threat, and where developers are deliberately using unchecked exceptions as a way to avoid the trouble of handling error cases, you're building up a lot of technical debt that you'll have to clean up some time if you want robust code. Sloppy error handling is unprofessional (and looking at the error handling is a good way to determine how good a programmer really is).

0

I think you should ONLY throw checked exception when the application can recover. So, users of your library must catch those exceptions and do what it needs to recover. Anything else should be unchecked.

As a example,

If your app loads data either from an file or a database. Then,..

try {
  File data = new File(...);
  // parse file here
} catch (Exception ex) {
  throw new MissingDataFileException("data file not found");
}

the caller could always catch the checked MissingDataFileException and then try to load the data from the database.

try {
  Connection con = DriverManager.getConnection( host, username, password );
  // query data here
} catch (Exception ex) {
  throw new RuntimeException("better call Saul!");
}
1
  • 1
    Saul died in a car crash 3 years ago. Fail! ;-) Mar 31, 2013 at 19:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.