Can an IllegalStateException be used to capture all sub-exceptions?
I wonder if using an IllegalStateException in this scenario is a good design choice for an API.
Scenario: I have a function which checks if an XML document is well formed with the following signature:
public boolean isXMLDocumentWellFormed(InputStream inXMLDocument)
This function uses the following snippet to load the XML document:
boolean isXMLDocWellFormed = false;
// Setup document builder
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
if (docBuilderFactory == null)
throw new IllegalStateException(
"The DocumentBuilderFactory cannot be instanciated");
try {
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
// Parse document
Document doc = docBuilder.parse(inXMLDocument);
if (doc != null)
isXMLDocWellFormed = true;
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IllegalStateException(e);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IllegalStateException(e);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IllegalStateException(e);
}
return isXMLDocWellFormed;
The API is designed to be very easy to use. However, I would like to provide to API users the possibility to know why an XML document cannot be checked (example: DocumentBuilderFactory cannot create a DocumentBuilder object) without overwhelming them with tons of checked exception that they will have to deal with.
My concerns regarding this开发者_如何学C design are:
a) Does using one single Exception type (i.e IllegalStateException) to return every possible caught exceptions to indicate a failure to perform the check a good idea ? I would say yes since users would except 2 things out of this function:
- To know if the XML document is well formed or not.
- To know in the event that the function cannot return the answer (due to an exception for instance) why the function failed to provide the answer.
b) If the answer to a) is no, then what would be the most appropriate exception name or solution and why ?
Regards,
My first recommendation to people is to not catch exceptions just to effectively re-throw. Catch when you can actually do something about them. So think about that. But in your example where you are catching checked exceptions and wrapping them in a runtime exception, I'd ask the question - how often will this occur? If the exceptions are likely to be common (or serious) then you want programmers to ensure that they deal with them, so checked is the way to go. However if they are not common (and not serious) then throwing a wrapping runtime may be acceptable. This is something that you need to think about because nothing annoys a developer more than unexpected exceptions.
Having said nothing by saying all that :-) if you are going to wrap I'd consider creating your own exception because you want to be clear that it is yours and not Java's. You could even create a hierarchy with a generalised exception extending runtime, and then more specific ones extending your genralised exception. Thus allowing API users the option to catch at different levels.
If its an API that your developing then you should wrap all exceptions in one main exception. This way you don't bleed implementation details. However your personal taste may differ
However I don't think IllegalStateException fits well here. Its very generic and doesn't explain the problem (An IO Exception is Illegal state?). Best solution is to create your own custom Exception class and throw that.
As a side node to you or anyone else, please don't print the exception if your throwing it.
I would suggest that it's probably most helpful to have a routine leak four types of exceptions:
- CleanFailureException: The requested operation failed, but the attempt did not have any side-effects. The entity throwing the exception is expected to be in a valid state from its own perspective, though it's possible it does not comply with some invariants the user of the class may be expecting. Example: retrieving a non-existent key from a Dictionary. The Dictionary's data structures may be perfectly valid, as a Dictionary, but the application may expect it to be in a state containing the requested key (it's also possible that the Dictionary is in the right state, and something else gave the application a wrong key).
- PartialOperationException: The requested operation did not complete, but may have completed to some unknown degree. As above, the entity throwing the exception is probably in a valid state from its own perspective, but the caller will have to check whether it's in a state the caller would consider valid.
- StateCorruptException: The requested operation did not complete, and the object upon which it was attempted, or some nested object, seems to have a corrupt state.
- SystemOnFireException: The state of anything and everything in the system should be considered suspect.
An exception caused by something like an out-of-bounds array index could fall into any of the above categories. What matters is not that an out-of-bounds index was accessed, but rather what it means about other objects. Catch, wrap, and rethrow would be a very useful pattern, since resolving an exception into one of the above categories will give the caller a much better idea what to do with it.
精彩评论