Difference between revisions of "Java Exception Handling"
Jump to navigation
Jump to search
m |
|||
(9 intermediate revisions by the same user not shown) | |||
Line 50: | Line 50: | ||
=== No distinction between exceptions and errors/checked and unchecked exceptions === | === No distinction between exceptions and errors/checked and unchecked exceptions === | ||
Compare [http://java.sun.com/javase/6/docs/api/java/lang/Exception.html Exception] and [http://java.sun.com/javase/6/docs/api/java/lang/Error.html Error] | Compare [http://java.sun.com/javase/6/docs/api/java/lang/Exception.html Exception] and [http://java.sun.com/javase/6/docs/api/java/lang/Error.html Error] | ||
=== Different interface boundaries handle exceptions differently === | |||
* Java --> Java exception handling | |||
* EJB --> partly controlled Java exception handling (RemoteException, EJBException) | |||
* SOAP --> eventually generating exception classes | |||
* REST --> error communication via status codes | |||
== Conclusion == | == Conclusion == | ||
=== Distinguish between repairable exceptions and errors === | === Distinguish between repairable exceptions and errors === | ||
Decide whether your module is able to fix the exception (take default values, look somewhere else, try again, ...) or not. | |||
=== | === Only catch repairable exceptions === | ||
* If an exception is somehow repairable, try this in the catch-block | |||
* If the repairing is critical in some respect, at least log a warning message (e.g. logger.warn("Value for xyz not found, taking default value")) | |||
* If repairing fails treat the exception as an error | |||
=== | === Inside a module, prefer unchecked exceptions === | ||
Turn checked exceptions from third-party modules into unchecked exceptions, e.g. | |||
<code> | |||
private void myMethod() | |||
try | |||
{ | |||
connection.executeStatement(sql); | |||
} | |||
catch (SQLException sqle) | |||
{ | |||
throw new RuntimeException("Error executing statement '" + sql + "'", sqle); | |||
} | |||
} | |||
</code> | |||
=== Inside a module, always throw errors up as they are === | === Inside a module, always throw errors up as they are (alternatively) === | ||
Do not care for exceptions at all, just declare them to be thrown, e.g. | |||
<code> | |||
private void myMethod() throws SQLException | |||
connection.executeStatement(sql); | |||
} | |||
</code> | |||
=== When catching exceptions, log appropriately === | === When catching exceptions, log appropriately === | ||
Line 67: | Line 96: | ||
** <s>logger.error("Error geting server.name property");</s> --> Exception information is lost | ** <s>logger.error("Error geting server.name property");</s> --> Exception information is lost | ||
** <s>logger.error(ex);</s> --> Only ex.toString() is logged, other exception information is lost | ** <s>logger.error(ex);</s> --> Only ex.toString() is logged, other exception information is lost | ||
* when an exception is rethrown, do not log (except when throwing out of the module) | |||
=== | === Throw self-defined exceptions that are defined inside the throwing module === | ||
* For exceptions concerning the logic of the module, exceptions should be defined and checked | |||
* No third module should be necessary to define these exceptions | |||
=== Between modules, throw only generic exceptions === | === Between modules, throw only generic exceptions === | ||
e.g. [http://java.sun.com/javase/6/docs/api/java/lang/IllegalArgumentException.html IllegalArgumentException], [http://java.sun.com/javase/6/docs/api/java/lang/IllegalStateException.html IllegalStateException], [http://java.sun.com/javase/6/docs/api/java/lang/RuntimeException.html RuntimeException] | e.g. [http://java.sun.com/javase/6/docs/api/java/lang/IllegalArgumentException.html IllegalArgumentException], [http://java.sun.com/javase/6/docs/api/java/lang/IllegalStateException.html IllegalStateException], [http://java.sun.com/javase/6/docs/api/java/lang/RuntimeException.html RuntimeException] | ||
== Open questions == | |||
* Shall interfaces define checked exceptions? | |||
** If so, shall self-defined exceptions be used? | |||
== Links == | == Links == | ||
* [http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html OnJava: Best Practices for Exception Handling] | * [http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html OnJava: Best Practices for Exception Handling] | ||
* [http://www.ibm.com/developerworks/library/j-ejbexcept.html IBM: Best practices in EJB exception handling] | * [http://www.ibm.com/developerworks/library/j-ejbexcept.html IBM: Best practices in EJB exception handling] | ||
* [http://today.java.net/pub/a/today/2003/12/04/exceptions.html Sun: Three Rules for Effective Exception Handling] | |||
[[Category:Best_Practice]] |
Latest revision as of 13:50, 27 November 2008
Problem description[edit]
Modules need dependencies of other modules only because of their exception classes[edit]
From validation/ItemValidating:
String validateItemXml(final String itemXml) throws
ValidationSchemaNotFoundException,
TechnicalException;
From importmanager/ImportHandler:
byte[] doFetch(String sourceName, String identifier) throws FileNotFoundException,
IdentifierNotRecognisedException,
SourceNotAvailableException,
TechnicalException,
FormatNotRecognizedException;
Stacktraces are sometimes swallowed[edit]
try
{
...
}
catch (MalformedURLException e)
{LOGGER.error("Error when replacing regex in fetching URL"); e.printStackTrace(); }
catch(UnsupportedEncodingException e)
{e.printStackTrace();}
try
{
...
}
catch (JiBXException e)
{
e.getCause();
}
Sometimes, excessive stacktraces are shown, even without useful information[edit]
Example from coreservices: File:Exception1.txt
Logger.error, System.out and e.printStackTrace are mixed up happily[edit]
see above
No distinction between exceptions and errors/checked and unchecked exceptions[edit]
Different interface boundaries handle exceptions differently[edit]
- Java --> Java exception handling
- EJB --> partly controlled Java exception handling (RemoteException, EJBException)
- SOAP --> eventually generating exception classes
- REST --> error communication via status codes
Conclusion[edit]
Distinguish between repairable exceptions and errors[edit]
Decide whether your module is able to fix the exception (take default values, look somewhere else, try again, ...) or not.
Only catch repairable exceptions[edit]
- If an exception is somehow repairable, try this in the catch-block
- If the repairing is critical in some respect, at least log a warning message (e.g. logger.warn("Value for xyz not found, taking default value"))
- If repairing fails treat the exception as an error
Inside a module, prefer unchecked exceptions[edit]
Turn checked exceptions from third-party modules into unchecked exceptions, e.g.
private void myMethod()
try
{
connection.executeStatement(sql);
}
catch (SQLException sqle)
{
throw new RuntimeException("Error executing statement '" + sql + "'", sqle);
}
}
Inside a module, always throw errors up as they are (alternatively)[edit]
Do not care for exceptions at all, just declare them to be thrown, e.g.
private void myMethod() throws SQLException
connection.executeStatement(sql);
}
When catching exceptions, log appropriately[edit]
- use log4j, not System.out
- use the two-argument methods:
- logger.error("Error geting server.name property", ex);
logger.error("Error geting server.name property");--> Exception information is lostlogger.error(ex);--> Only ex.toString() is logged, other exception information is lost
- when an exception is rethrown, do not log (except when throwing out of the module)
Throw self-defined exceptions that are defined inside the throwing module[edit]
- For exceptions concerning the logic of the module, exceptions should be defined and checked
- No third module should be necessary to define these exceptions
Between modules, throw only generic exceptions[edit]
e.g. IllegalArgumentException, IllegalStateException, RuntimeException
Open questions[edit]
- Shall interfaces define checked exceptions?
- If so, shall self-defined exceptions be used?