Java Exception Handling
Jump to navigation
Jump to search
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?