At what point would you create your own exception class vs. using java.lang.Exception? (All the time? Only if it will be used outside the package? Only if it must contain advanced logic? etc...)
I think you need to ask yourself a slighly different question "What advantage does creating a new exception give me or developers who use my code?" Really the only advantage it gives you or other people is the ability to handle the exception. That seems like an obvious answer but really it's not. You should only be handling exceptions that you can reasonably recover from. If the exception you throw is a truly fatal error why give developers a chance to mis-handle it?
More in depth discussion: Custom exceptions: When should you create them?
Reason one:
Need to catch specific stuff. If calling code needs to deal with a specific exceptional condition, you need to differentiate your Exception, and Java differentiates exceptions with different types, so you need to write your own.
Basically, if someone has to write:
catch(ExistingException e) {
if({condition}) {
{ some stuff here}
}
else {
{ different stuff here}
}
}
You probably want to write a specific extension; catch Exception matching is clearer than conditionals, IMHO.
Remember: your new Exception can be a subclass of RuntimeException
Reason two:
API consolidation. If you write an interface and you have several implementations, it's possible that they will call different APIs with a whole bunch of different non-RuntimeExceptions thrown:
interface MyInterface {
void methodA();
}
class MyImplA {
void methodA() throws SQLException { ... }
}
class MyImplB {
void methodA() throws IOException { ... }
}
Do you really want MyInterface.methodA to throw SQLException and IOException? Maybe then it makes sense to wrap the possible exceptions in a custom Exception. Which again can be a RuntimeException. Or even RuntimeException itself...
I believe that:
catch (Exception e) {
...
}
... is an antipattern that should be avoided. You might want one centralized broad catch somewhere in your application, to log an error and prevent the whole application from terminating - but having them scattered around willy-nilly is bad.
Why:
try {
if(myShape.isHidden()) {
throw new Exception();
}
// More logic
} catch (Exception e) {
MyApp.notify("Can't munge a hidden shape");
}
So you try this, and due to a coding error, myShape is null. A NullPointerException gets thrown when the runtime tries to derefence myShape. This code reports a hidden shape, when it should be reporting a null pointer.
Either make your own exception, or find a suitably specialized exception in the API. It's not as if extending Exception or RuntimeException is onerous.
When I want to treat my exceptions differently from everybody else's. If I want to catch mine and propagate everyone else's, or if I want to catch someone else's and propagate mine, or if I want to catch both but treat them differently, then I will define a separate class for my exceptions. If I want to treat them all the same, either by propagating both or by catching both (and doing the same thing either way with the caught exceptions), the I will use the standard class.
IF there is an existing Exception with the language runtime or libraries, use it ELSE create your own, document it well and that should work in 99% of the cases.
Software captures meaning.
There are almost no reasons for throwing an existing exception: the JVM already does that for you. Your version of their exception isn't really accurate and throwing "Exception" isn't meaningful, either.
You might have a DataFormatException because of a parsing algorithm you wrote. This, however, is rare.
When your program encounters an exceptional situation, it's almost always unique to your program. Why force-fit your exceptional situation into an existing exception? If it's unique to your program, then... well... it's unique. Name it that way.
Do not, however, provide a unique exception class for each unique message. One exception class can have many variant messages and supporting details.
The Python rule of thumb, translated to Java, is to define any unique exceptions at the package level. [In Python, they suggest exceptions at the "module" level, something that doesn't precisely translate to Java.]
Start always by using the common exception classes and then when a need appears to handle it specially, change it.
When creating a method first time, just let exceptions go through.
If there are exceptions that must be handled, those can either be just defined in throws or wrapped to some runtime exception or wrapped own throws exception. I prefer runtime exceptions in many cases. Defining throws definition should be avoided until there is a need for it from API point of view.
Later when a need appears to do specific handling for an exception in some caller, come back and create new exception for it.
The point is to avoid doing extra work before knowing what is needed.
I can't imagine specifically throwing a java.lang.Exception if some object/class/method had a problem. It's too generic - if you're not going to create your own Exception class, seems to me like there ought to at least be a more specific Exception-type in the API.
I would use the exceptions from the Java API when the exception relates to the API. But if an exceptional situation arises that is unique to my own API then I will create an Exception for it. For example if I have a Range object with two properties min and max and the invariant min <= max then I will create an exception InvalidRangeException.
When I am writing code this helps because I know if the exception originates because I violated one of my own conditions or its something from the Java API.
In most cases it doesn't make sense to create your own exception class.
There is a tendency in novice programmers to create their own exception class just so they can use a name that is more indicative of the type of error. So you'll find classes like FTPInitializationException, DAOFactoryException etc. even though such exceptions are not being handled differently than standard exceptions. This is clearly an anti pattern that should be avoided.
Related
What is the guideline for methods declaring runtime exceptions?
Let's say I call a 3rd party routine that throws SQLException. Is it permissible/standard/acceptable for that routine to be able to throw RuntimeExceptions without declaring that it does so?
As always, I am surprised by the confusion my questions cause :-D This is probably because I am confused.
In the following, the callable is a lambda that issues a commit, and this throws SQLException. callable.call throws Exception.
private doThis(Callable<T> callable) throws SQLException {
try {
return callable.call();
} catch (SQLException e) {
// do stuff
throw e;
} catch (Exception e) {
break; // Eats any exception from call() which makes me scream internally.
}
}
What I surmise from this is that the coder wanted doThis to throw a SQLException. However, the nature of using the Callable meant that the routine had to throw an Exception unless the coder did something. So he caught Exception and swallowed it. But Exception is the parent is RuntimeException, so we're eating those too.
What am I to do? Making doThis throw Exception seems clumsy and random. Wrapping any exception being thrown in a RuntimeException and raising that preserves the coder's intent but seems suspect.
EDIT -
ok, I have learned, thank you. Now the question is, what to do about it. Clearly, eating the exception is a bad idea. Diluting the SQLException as declared seems not great.
How does the collective wisdom of SO feel about wrapping the Exception in a RuntimeException?
...
} catch (Exception e) {
throw new RuntimeException(e);
}
What am I to do? Making doThis throw Exception seems clumsy and random. Wrapping any exception being thrown in a RuntimeException and raising that preserves the coder's intent but seems suspect.
This method's sole reason for existence appears to be to perform special handling (// do stuff) in case of a SQLException. To handle that error correctly, some assumptions about what the Callable is doing must hold. For the sake of argument, perhaps the "stuff" is marking a particular database connection for rollback, assuming that the Callable used it do some work that may have partially failed.
Yet, this method accepts Callable. That doesn't impose any limitation on what the called function might do, why it might throw a SQLException, or what a SQLException might mean if it does arise. This code feels wrong, because it is wrong to make these very specific assumptions about an open-ended, black-box function like Callable. And, it's probably unnecessary. This is a private method, so you know everything about the methods that call it, and you can modify them to make it clear how things work together.
Instead, define your own (functional) interface. Declare the specific exceptions your helper method can handle, and document any other requirements for implementations. If, in fact, the "stuff" done in your helper method involves a database connection that is a member of the object, you might define the interface like a Consumer or Function, but with SQLException or other errors.
Here's a hypothetical example:
private final Connection db;
#FunctionalInterface
private interface DatabaseOperation<T> {
T apply(Connection db) throws SQLException;
}
private <T> T withRollback(DatabaseOperation<T> op) throws SQLException {
try {
return op.apply(db);
} catch (SQLException ex) {
db.rollback();
throw ex;
}
}
None of this is to say that Callable or other core functional interfaces are bad. You shouldn't create new, non-standard functional interfaces when the pre-defined interfaces would meet your needs. It's just that they don't in this case.
Not sure what you mean.
Is it okay to stick exception types that extend RuntimeException in the throws clause of a method?
Java implies certain things and usually you can't undo these things.
For example, all java files act like they have import java.lang.*; at the top even if don't write that. All classes that don't have an extends clause act like they have extends java.lang.Object...
and all methods act like you have throws RuntimeException, Error on them whether you write it or not.
It's legal to write import java.lang.*;, although it would be completely pointless to do this. It is similarly legal to write:
void foo() throws RuntimeException {}
even though this is rather pointless. However, unlike import java.lang.*;, adding some specific runtime exception can be useful in the sense that it documents (It has absolutely no effect whatsoever on what the code does). Some linting tools (I would disagree with the style they are espousing, though!) flag it down as 'useless code' but I wouldn't be so hasty. For example, this method:
public static int parseInt(String in) throws NumberFormatException {
..
}
is declaring the NFEx for no programmatic purpose (NFEx is a RuntimeException and all methods trivially can throw those without declaring them), but it is documentary: It highlights that that's an exception you should be taking into consideration when invoking this method / it's the obvious "thing you are looking for" (in the sense that 'soooo... what if I pass a string that does not contain a number to this method, what happens then' - is the obvious question to ask).
So, do it, if that's your intent. Your javadoc should probably have a:
* #throws NumberFormatException If the provided {#code input} is not parseable as an integer number.
or similar, for each explicit RuntimeException you care to state.
Is it okay to wrap SQLException to RuntimeException
Usually: No. The notion of declared checked exceptions is that they are part of your signature. A signature is all about what a method does. It is very much not at all about how it does so.
Thus, the crucial question to ask is: Is the SQLException aspect of it fundamental to what your method does, or fundamental to how it does it?
A trivial example:
saveGame() may simply 'save your game to some persistent storage mechanism'. That's what it does. Perhaps the how involves a database today. Perhaps tomorrow it'll involve the file system. Perhaps next year it's a cloud save system and it involves network access. If the point of this method is merely to force a save, and the method's signature intentionally does not explain how (because you want the future flexibility of changing this, and thus any callers should not assume it's disk, or DB, or network, or anything else), then and only then: SQLException would purely be about the how - and thus it has no place being thrown from the saveGame method. You should wrap it. I highly doubt it's a good idea to wrap that in RuntimeException, I'd invent your own exception (SaveGameException perhaps). Should that exception be checked or unchecked? That depends on too many factors to get into for this answer.
However, something like Files.newOutputStream is different. The what of this method includes the notion that its file based. Fundamentally: It would be nuts if that method doesn't interact with a file system at all and instead opens a database connection. The very name of that method spells it out: It is, after all, in a class named Files - the fact that it interacts with files is a fundamental, unremovable aspect of it. Hence, that method should most absolutely be declared to throws IOException. Similarly, if you have a method called saveToDb, that method should definitely be declared as throws SQLException - and thus, you should not be wrapping your SQLException in anything else.
In rare cases, convenience and intended usage strongly dictates you do not want the exception to be checked. In that case, make an unchecked variant and wrap that. Java itself has UncheckedIOException already - reuse that if it's about IOExceptions. Write the same principle if its about SQLException. However, usually if this comes up you've badly designed your classes - if there's an aspect of your system that is fundamentally tied closely to the notion of interacting with DBs, that entire chain of methods should all be declared to throws SQLException, at which point the need to make that unchecked no longer exists.
Can RuntimeExceptions happen?
Yes, by their nature, RuntimeExceptions can happen at any time. Looking at the greater java ecosystem, RuntimeExceptions cover 3 mostly separate use cases (this isn't getting into what the feature was ever intended for, this is solely about what common java libraries and code actually use them for):
Programming errors (bugs)
The quintessential example is NullPointerException. There is a bug, the bug should cause some kind of RuntimeException to be thrown. We do not want to make such exceptions checked (because nobody likes a catch block that literally is impossible to trigger unless you actively write bugs to do so - what could you possibly stick in the catch block?), but we DO want to throw something: Breaking off the method and 'unrolling' the entire call stack until some general handler deals with the problem (and gets lots of details about where that problem occurred and why) is precisely what we want. Hence, exception good, checked bad - these should be runtime exceptions and generally are.
Similar examples: Many methods that have rules about what you can pass to them which cannot be expressed in the type system (say, a method that requires you pass a non-negative integer) will throw IllegalArgumentException if you pass a negative number to them, for example. Some methods cannot be called when the object is in a certain state, and will throw IllegalStateException or UnsupportedOperationException, both unchecked (subtypes of RuntimeException) - for example, if you attempt to invoke .add() on an immutable list, you'd get that.
Couldn't be bothered
Sometimes checked exceptions can occur but you just don't care, either because you're a lazy programmer who wants to just go home (that'd be quite bad, of course), or because you cannot fathom why a checked exception could occur. For example, an IOException when writing to an OutputStream that is memory based.
IDEs tend to suggest this incredibly stupid 'fix':
try {
code();
} catch (IOException e) {
e.printStackTrace();
}
I do not know why. Mass delusion? At any rate, all IDEs are very wrong, that is bad code, the correct 'I do not want to think about this checked exception right now' handle block is throw new RuntimeException("uncaught", e); - and smart folks have updated their IDEs to auto-generate this. It's wrapping a checked exception in an unchecked one simply for convenience, or because the coder did not think it could happen.
For API/programming model reasons
See UncheckedIOException - usually because the code is designed to be used in stream pipelines which doesn't allow checked exceptions. Somewhat rare.
Unexpected situations
It could be reasonable for the programmer of this library to fail to account for some exotic situation which nevertheless is also reasonable for your specific usage of some library to run into. For example, a third party library could be saving data to whatever OutputStream you provide for it, and that OutputStream might throw a documented unchecked exception for some reason - in which case your library is likely to also throw it. This is rare - you'd presumably know about it, and it comes up only if some library is 'intermediary' - you pass it some object that it, in turn, acts upon, and in that interaction, the runtime exceptions end up getting passed through. Or, the object you pass in doesn't adhere to certain rules. For example, if I hand a comparator that doesn't adhere to the spec (for example, is inconsistent: both a.compareTo(b) and b.compareTo(a) return a negative number - the Comparator spec says you should not do that) to some library, and that library ends up throwing some undocumented unchecked exception for this, I wouldn't blame the library author.
The 'first' case (code bugs) should be documented. For example, Integer.parseInt indeed documents that a NumberFormatException is thrown if you pass a string that doesn't contain something parseable to an int. List's add documents that it might not be supported in which case UnsupportedOperationException will be thrown, etcetera. If your 3rd party routine's docs don't state anything, then it does not apply (or it is badly documented).
The 'second' case (laziness) is hopefully not the case either - that would mean the programmer of it did a bad job.
The third case should also be documented.
That leaves the 4th case, which could happen and won't be documented. You have some control over this, though.
CONCLUSION: Well written libraries will not be throwing undocumented RuntimeExceptions that you didn't expect (i.e. where you aren't the direct cause of it by handing weird objects or things that don't fit clearly documented specs)
I frequently come across the same problem. At the very core of my Java Application, I have methods that throw an exception which cannot be handled by any method caller. I have to bubble those exceptions up to the main method. All those exception summarize so I have many throws statements on higher levels of my Application.
E.g. I have a NodeJsManager.java class at the core of my application:
public class NodeJsManager {
public static void startNodeJs() throws ExecuteException {
// Code to start NodeJs Server goes here
}
}
To start the NodeJs Server, I have to execute something on command line. I can do that with the apache class org.apache.commons.exec.CommandLine. But it throws an ExecuteException, if the execution exited with an error code. Without NodeJs being started my application is useless. No method can catch this exception, it is just a requirement for my application to work. So the exception will bubble up almost the whole application lifecycle. I have other Managers that do the same (a ConfigurationManager that throws an exception, if the config path is wrong). All together it summarizes in many throws statements at every single method on a higher level where I don't even remember the cause of that exception.
How would you handle that problem? I must do something completely wrong because I can't find similar posts that describe my problem!
Regards
Mike
Update
I just unearthed my good old Effective Java book. The Author (a Java architect at Google) wrote the following about Exceptions:
... use checked exceptions for recoverable conditions and runtime
exceptions for programming errors.
...
If it isn't clear whether recovery is possible, you're probably better off using an unchecked exception ...
In my case it is clearly not recoverable, so throwing a runtime exception is the way to go. I always thought runtime exceptions should be prevented, this changes my point of view about exceptions in Java.
One possible approach is to deal with the Exception as close as possible to where it originated, where you have enough information to make a decision on what to do.
As you said if you have all the Exceptions caught at the highest level possible you are losing the context which is really important, because that gives information on why and how the problem occurred (and hopefully a few ways to fix it).
You said for example that your application without a NodeJS server is useless, then probably a way of doing this would be to have the NodeJSManager (if such a thing exists :D, I'm guessing) to not throw, but prevent the application from starting at all, something like
NodeJSManager nodejsManager = new NodeJSManager();
boolean succeeded = nodejsManager.tryToStart();
if (!succeeded) {
// guard, it's useless to proceed
// cleanup and exit
}
I called that method tryToStart because it can happen that the server does not start, you are dealing directly with the executables and the file system so I would say this is not so exceptional any more (but probably this is just a matter of taste).
What's important IMHO is that you specify your application start up as a series of checks, for example the node and the configuration ones, without having to deal with Exceptions to handle the flow of your code.
I don't like checked Exceptions. What I use to do (but is NOT a nice solution) is to catch the checked Exception and re-throw it as a Runtime Exception this way:
catch (ExecuteException e) {
throw new RuntimeException (e);
}
The checked Exception "e" is passed as an parameter to RuntimeException. This way, I convert a checked into an unchecked exception. But as I said, is not a nice solution and it may cause more debugging problems that it solves. When an Exception is "checked" it tends to be because the error described is "serious".
One solution would be to create your own, more general exception class that will extends Exception and wrap unhandled exceptions as causes into your own exception. This way you can at least reduce some exceptions from methods signatures. example:
Create new class StartupException or ConfigurationException and throw it with the main exception after catching it as cause during startup phase.
Moreover if you would make StartupException extends RuntimeException) you would not have to declare such exception.
Another way would be to wrap everything into RuntimeException
If abowe does not suit your needs than this is probably design flaw, (if you really cannot handle it) that you will have to deal with it.
What is the purpose of writing custom exception classes when mostly what it does is same.
For eg, NullPointerException:
class NullPointerException extends RuntimeException {
private static final long serialVersionUID = 5162710183389028792L;
public NullPointerException() {
super();
}
public NullPointerException(String s) {
super(s);
}
}
This is the basic template for most exception classes that I have seen and created.
One purpose I can think of is in handling these exception.But then cant this be based on Exception Message?. Mostly we write single handling code for each exception type. I know there are 'exceptions' to this.
But is there anything more to it? Isnt this repeating yourself where only the class name changes?
Also are there any JDK Exception classes that has some code than this?
I can think of several reasons:
Having multiple exception classes allows the programmer to be specific in their catch clauses, and only catch the exceptions they care about and know what to do with.
An exception class can carry information about the error that's caused the exception. For example, ArrayIndexOutOfBoundsException carries the offending array index, and SQL exceptions tends to carry database-specific error codes and messages.
Exception specifications -- that list exception classes -- can be used to check correctness at compile time.
Well, simply put, if you do not need special exception class, you should not make one. If you do, then you make one. There's no magic to it really.
If you're making a library, then you should of course think from the point of view of the developers using the library (even if it is just you): does your library throw exceptions for specific reasons and could the library user possibly want to catch specifically these, because they can realistically do something about it (just logging isn't reason enough, IMO).
Example with standard exception classes: Caller of a method might want to convert IndexOutOfBoundsException to null return value, while letting other exceptions to propagate normally.
If you want your custom exception to be handled in default ways, you extend right existing exception class, such as IOException. You can then catch your specific IO exception when you want to do something specific just there, but also let it be handled like any other IOException when you don't need special handling (can't do anything useful to recover).
If you have a totally custom exception which should never be caught by a superclass catch, which always should have specific catch block, then you extend Exception directly.
I think it's pretty rare to need to extend RuntimeException, because if it an exception meant to be caught it should be Exception subclass, and if it's meant to end the program or just generate log output, then it should be covered by default RuntimeException implementations with custom message string.
You need to have your client code know what exact exception happens by which part of code. so you need to let exception semantic and distinguished from other code block.
How to do this:
Define new exception class, so the class name tells what happens
Define a unifed/generic exception class which wraps code, message or other info. the code can tells what happens.
To summarize it, Do something let your exception have some meaning/semantics, and let its client know what exactly happens.
We will have a freedom to add few more methods into our Exception class which helps the client like rootCauseOfException(),description(),solution(),suggestions() etc.
Can refer below link:
https://stackoverflow.com/a/22698673
If your project has interdependent modules then you can maintain exception hierarchy also in the same dependency hierarchy so that if you catch single Exception in base layer then all the interdependent modules exceptions will be caught.
You can also mask some sensitive data like ip ,port etc before sending to client side. If custom exceptions are not used then some sensitive data can may get leaked to slient.
You can provide your own exception message which can be easily understandable by client rather than java's exception message sometimes which may be hard to understand .
It is basically to Handle different Exception in different ways. Say, you might want to do some different operation on ArrayIndexOutOfBoundsException than a NumberFormatException.
or more clearly
}catch (ArrayIndexOutOfBoundsException ex){
//operation 1
}catch (NumberFormatException ex){
//operation 2
}
The main purpose would be identify the custom / app-specific errors. You can also provide some additional methods there. For eg, we have custom exceptions that return custom messages, and also extracts cause and location from the stack trace.
I have a class XYZ whose public functions throw Exceptions.
I have been advised that all public functions exposed by XYZ should throw exceptions called XYZDataException or XYZSystemException. So even if I get other exceptions within the public methods they need to be wrapped by these XYZExceptions.
I have a couple of questions:
What is the advantage of wrapping exceptions with XYZException?
What is the advantage of differentiating between System and Data exceptions?
To me it feels right to just throw whatever exception occurs without wrapping it further.
A lot of Exception handling depends on how you plan on extending it later on. For example, if developer B came along and wanted to modify some of your code, it would be a lot easier if he understand what Exception meant what in which case. In that case, having specific Exceptions makes more sense.
As to breaking up System and Data exceptions - a Data exception would basically be something that should be non-fatal that occurs because of bad data. A System exception would be because your System failed in some way. Again, this all points to how you want to use it later on. If you want to use your code solely, and you don't care about how your exceptions come back out, then by all means, go with what is easiest at the time.
I have found that when working with other developers on a project, it is a lot easier for them to grasp what is going on when you subclass your Exceptions and throw them in specific cases.
Hope this helps!
Yes, it means they can be explicitly caught by code that knows how to handle them.
for instance, imagine you had:
class MyRecoverableException extends Exception {
...
}
You could then have code that can differentiate between them automatically, and react accordingly, such as:
try{
// ... do something ...
}catch(MyRecoverableException e) {
// Recover
}catch(Throwable t) {
// Log fatal reason, and exit gracefully.
}
Obviously how many you need is a problem to be solved by you, the application developer, but a clean separation can make all the difference when working out what went wrong, and subclassed exceptions can hold additional properties, used to pass pertinent information to handlers about the exceptional circumstances that brought them about.
Having a base type to extend from for your application/library never hurts either - if for no other reason than to allow separation of source when logging - but the exact hierarchy and complexity required beyond that depends entirely on the project. Some designs have natural and obvious choices, some require a bit more forethought (and occasionally a bit of afterthought and refactoring).
As usual, "it depends". As a general rule it does not make sense to blindly create an exception hierarchy on a per-class basis. App-specific exceptions should group exceptions in a way meaningful to that particular app, so there might be a top-level exception, then sub-classed exceptions for things like the data layer, communication layer, utilities, whatever.
The advantage is that higher levels dealing with those exceptions are not exposed to the implementation details that generate those exceptions. Also, perhaps to a lessor degree, exceptions may be grouped more meaningfully (is it relevant that it was an IOException, or is it enough to know there was a problem writing to whatever output store you're using).
Another great advantage is that app-specific information may be captured in the custom exceptions. Things like user IDs, account numbers, etc.--any application state--which must be stored as part of a string message in a "stock" exception may be assigned to a property. This may avoid random parsing issues if you actually do anything with the exceptions or try to trace through a particular event stream.
According to msdn:
To wrap an exception, you specify it as the inner exception of a new exception and then throw the new exception. This practice should be used only in situations where the original exception is not meaningful to the person who receives the exception, or the call stack for the exception is misleading or uninteresting.
Suppose method M1 is documented as throwing an exception of type X when some condition occurs. M1 calls method M2, which happens to throw an exception of type X which M1 is not prepared to handle. If M1 doesn't catch the exception from M2, the caller is unlikely to figure out that the exception thrown out of M1 isn't an X thrown by M1, but is instead an X thrown by M2, and its practical meaning and implications may be very different. Having M1 throw an exception of a type which will never be thrown by M2 may avoid this issue (though there could still be trouble if M2 could call M1 on some other object).
I find that Java's reflection API is exception verbose, and I often want to catch each specific exception, but just throw Exception. Is this poor practice, or do you really throw all of those exceptions on the method signature? Every method that calls that method must then deal with each of those specific exceptions in some way. Instead, I'm thinking of doing this:
public void someMethod()
throws Exception {
try {
// do a bunch of reflection...
} catch(ClassCastException classCastException) {
throw new Exception("Some specific message.", classCastException);
} catch(InvocationTargetException invocationTargetException) {
throw new Exception("Some specific message.", invocationTargetException);
}
}
Is that poor practice?
Rethrowing different kinds of exceptions that a method throws as a single unified exception can sometimes be a reasonable approach.
Using java.lang.Exception specifically for this is a bad idea, because it's too unspecific.
You might rethrow each different exception as some custom MyException or something like that. That's sometimes a reasonable approach when you're not really interested in why someMethod failed.
Short answer
Reflection is verbose by design
Exception translation is idiomatic (catching lower level exception and abstracting it to a higher level)
... but don't overuse!
Prefer custom exceptions to java.lang.Exception; it's probably too high of an abstraction
Point 1: Avoid reflection if at all possible
Here's a quote from Effective Java 2nd Edition, Item 53: Prefer interfaces to reflection:
[The power of reflection], however, comes at a price:
You lose all the benefits of compile time checking, including exception checking.
The code required to perform reflective access is clumsy and verbose. It is tedious to write and difficult to read.
Performance suffers. Reflective method invocation is much slower than normal method invocation.
[...] As a rule, objects should not be accessed reflectively in normal application at runtime. There are a few sophisticated applications that require reflection. Examples include [omitted on purpose]. If you have any doubts to whether your application falls into one of these categories, it probably doesn't.
Point 2: Exception translation can be a good thing, but don't overuse
Here's a quote from Effective Java 2nd Edition, Item 61: Throw exceptions appropriate to the abstraction.
It is disconcerting when a method throws an exception that has no apparent connection to the task that it performs. This often happens when a method propagates an exception thrown by a lower-level abstraction. [...]
To avoid this problem, higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of higher-level abstraction. This idiom is known as exception translation.
[...] While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused. Where possible, the best way to deal with exceptions from lower layers is to avoid them, by ensuring that lower-level methods succeed. [...]
If it is impossible to prevent exceptions from lower layers, the next best thing is to have the higher layer silently work around these exceptions, insulating the caller of the higher-level method from lower-level problems. Under these circumstances, it may be appropriate to log the exception using some appropriate logging facility. This allows an administrator to investigate the problem, while insulating client code and end user from it.
Point 3: java.lang.Exception is way too general
Looking at the documentation, one can see a long list of direct known subclasses, with a wide-ranging topics from Reflection, RMI, XML parsing, I/O, GUI, cryptography, etc.
Declaring that a method throws Exception is probably a poor API design decision, because it does not immediately tell the user anything useful about what category the exceptions may be, or under what circumstances they may be thrown. Contrast this with a hypothetical ReflectionException; this is a lot more informative, and it also allows user to catch specifically ReflectionException and not, say, an IOException that somehow slipped through.
Related questions
In Java, is using throws Exception instead of throwing mulitple specific exceptions good practice?
Catching several exceptions and rethrowing a general exception
java.lang.Exception vs. rolling your own exception
When should Throwable be used instead of new Exception?
Need authoritative source for why you shouldn’t throw or catch java.lang.Exception
In Java, when should I create a checked exception, and when should it be a runtime exception?
When to choose checked and unchecked exceptions
The case against checked exceptions
I agree with your approach, except I think throwing Exception is not good, eventually every method declaration in your application will end with "throws Exception". For cases like this, where the exception will only occur if you made an error, it's better to make the wrapping exception an unchecked exception.
If the exception thrown by the method (contained in the InvocationTargetException) have the potential to be interesting to you, you could make it the wrapper a different subclass of unchecked exception or create a specific checked exception subclass for it, but wrap things like the ClassCastException in unchecked exceptions.
To use throws Exception is always a bad idea. In your case you have to consider the following things.
Can I recover from the error at the next imediate level? If so use all the different exceptions for clarity.
Can I recover from the error some levels up? If so use a wrapper exception because it would pollute all methods on the way up with technical details to use the explicit ones.
I can't recover from the error or it happens in a completely different place/many levels above. If wrap each exception into RuntimeException or a custom ReflectionFailedRuntimeException to avoid technical exceptions leaking throughout your application.
Alos, normally you should code it in a way that you can expect the reflection to work in most cases without Exceptions, so it would be also considerable to make it RuntimeException wrapping anyway.
Think of what you want to achieve. The caller of your method is not supposed to know you're using reflection to achieve your goal. That's none of its business. If you would just put all those exceptions in your throws clause that would break that encapsulation.
Catching these exceptions and wrapping them in your own is therefore the way to go. Then you just have to decide which exception to throw. Exception itself is a very bad idea (I'm of the opinion it should even be abstract to suggest that) The type of the exception should be related to the problem.
Throw an exception that relates to what you're trying to do and to why it failed (if it failed because a given argument is inappropriate, IllegalArgumentException would be one). Also make an informed decision on whether you would like to throw a checked or an unchecked exception (RuntimeException).
I would in some cases.
The normal way I would decide is look at what methods calling someMethod() would expect or reasonably be expected to know. So if someMethod() was doing something IO related I'd throw an IOException, if it was related to a library I was writing I might throw a custom exception..
I'd only throw the individual exceptions if the callers of someMethod() would reasonably be expected to know it used reflection for its implementation.
I guess the key question is "If someMethod() didn't use reflection, and something went wrong, what would it do?" That will normally give you the answer.
Thats still an acceptable policy if you are collecting all exceptions and throwing a custom exception of yours.
public void someMethod()
throws MyCustomException {
try {
// do a bunch of reflection...
} catch(ClassCastException classCastException) {
MyCustomException ex1 = new MyCustomException("Some specific message.", classCastException);
// Logic to add more details to exception AND/OR handling current exception.
throw ex1;
} catch(InvocationTargetException invocationTargetException) {
MyCustomException ex1 = new MyCustomException("Some specific message.", classCastException);
// Logic to add more details to exception AND/OR handling current exception.
throw ex1;
}
}
Generally catching exception should be for a reason of handling them in some way. Simply re-throwing an exception of larger scope makes no sense anywhere to me.