I am bridging a C Api to a Java Api. The C Api uses error codes for exceptional cases. Since every function returns such a error code and there are a lot of error codes (about 100), i wrote a error code handler that translates the error codes to a bunch of more general runtime exceptions:
public class ErrorCodeHandler {
public static void handle(int status) {
switch(status) {
case SUCCESS:
return; // In case of success, simply return
case NO_VALID_DATA:
throw new DataError("No valid data");
...
case NO_CONNECTION:
throw new ConnectionError("No connection");
}
}
}
All my custom Exception classes inherit from a base Exception class specific to my application:
public class MyException extends RuntimeException { ... }
public class DataException extends MyException { ... }
...
My methods simply call handle on the error code returned from the call to the C API:
public void someMethod() {
int status = cBinding.someMethod();
ErrorCodeHandler.handle(status);
}
If an error occured, the method will throw the appropriate exception. If not, it will simply return.
Now i am faced with the problem on how to document this kind of exception handling. I read that you don't add runtime exceptions as a throws clause, but document it using the Javadoc #throws tag.
Now my question is, should i add a #throws tag for every different exception i know can be thrown from a method (indirectly by looking up the possible error codes), or should i just document a generic #throws MyException? I feel like the first approach will clutter my documentation with a lot of mostly useless #throws tags (a lot of these error codes are very rare) and it will be a very high effort to document these. The second approach would be mostly copy-pasting, but i would lose the advantage the exception hierarchy gives me.
Has anyone ever done something similar? Any advice on how to document this kind of stuff?
It is perfectly reasonable to just write something like #throws MyException if underlying service fails in your javadoc. It’s fairly common in Java SE; for example:
Files.copy only has #throws clauses for IOException and two subclasses of IOException, even though it can throw many other subclasses of IOException.
The JDBC method Statement.execute has a #throws clause for SQLException and one subclass of SQLException, even though there are many other subclasses of SQLException that can be thrown.
I am currently implementing a system in which I am using aspectJ to check whether a user is allowed to call a method or not. My methods look something like this:
#Constrained(
mayUsers = {Constrained.Types.ADMIN,
Constrained.Types.SELLER, Constrained.Types.ORGANIZER}
)
public boolean save() {
/* code */
}
I am able to use AspectJ to intercept the message call and do the check, but if the call is not allowed I want to throw an exception. If I just throw the Exception the user of the method is not informed about the Exception which might be thrown.
Now my question is:
Is it possible to enforce that the every method that has the #Constrained Annotation throws a specific Exception?
Is it possible to enforce that the every method that has the
#Constrained Annotation throws a specific Exception?
No it is not possible to do that right now. But what you can do is that at runtime you can check that all the methods that have this annotation must throw exception. If any of method does not declare throws clause, you can throw some Illegal*Exception to tell the developer that each method must declare throws clause.
You have two solutions:
Compile time annotation checking using APT (Annotation Processing Tool)
Runtime checks (pre-conditions)
I hate functions that declare to throw exceptions that are not thrown by this functions in any case. This happens in refactorings if throw statements are removed in the function body without removing it from the throws definitions.
Thats why I activated the setting Java -> Compiler -> Errors/Warnings -> Unnecessary code -> Unnecessary declaration of thrown exception.
This leads to false positive warnings if exceptions are defined in interfaces or super methods. If implementation A of the interface does not throw one exception type, but implementation B does, eclipse warns about the unnecessary declaration in implemantation A. Thats equally for super and overriden methods. Thats why I activate the suboption "Ignore in overriding and implementing methods".
Perfeclty fine till here. But I have the oposite case. The overridden method throws a exception type, that is not used in the super method. See this minimal example:
class Vehicle {
protected int getStatus() throws GeneralException, StatusException {
throw new GeneralException("One exception type in super type only");
}
}
class Car extends Vehicle {
#Override
protected int getStatus() throws GeneralException, StatusException {
throw new StatusException("Special case, that gets special handling");
}
}
Now StatusException in Vehicle is warned in eclipse.
Of course one could argue that this is bad design etc., but from a pragmatic point of view this will happen again and most probably one can accept to not change the architecture, but to simply add the new exception type to the super type. But howto get rid of the false positive warning in this case? Of course one could use the suboption with the javadoc, but this would also ignore most real positive hits. Another option is to add the SuppressWarning annotation "unused", but other users could get unneeded warnings for that suppression.
Personally I'd activate the second option under the warning setting: "Ignore exceptions documented..." and just document those:
/**
* #throws GeneralException when general stuff goes wrong
* #throws StatusException when status stuff goes wrong
*/
protected int getStatus() throws GeneralException, StatusException {
throw new GeneralException("One exception type in super type only");
}
Maybe include a slightly more useful explanation, but it'll basically boild down to this.
I am curious about if I should add throws ExceptionClass or not after the method's signature.(ExceptionClass extends RuntimeException)
For instance:
public void foo() // throws ExceptionClass
{
// ...
throw new ExceptionClass("");
}
If you use the JDK as a guidance, RuntimeException are not in the methods signature but are documented in the javadoc. You can have a look at collections for example.
Ideally you don't need to add runtime exception in method's throws clause. Since you want the consumer of this method to be aware of chances that this method may throw exception , i would say use javadoc either. Below is example of how you should use :
/**
*
* #throws ExceptionClass
*/
public void foo()
{
// ...
throw new ExceptionClass("");
}
Runtime exceptions do not need to be listed in the throws clause. Place it there only if you need to document this behaviour, if it's in some way important to know for the client of this class, that this exception might appear (but if that's the case, perhaps it needs to be changed to a checked exception, or only be mentioned in the javadocs).
In the past I'd read tons of code with methods like:
public Object doSomething() throws Throwable {
...
}
Is it common practice to do that?
What are pros & cons?
throws Trowable seemed to me like the "Agent Orange" way of getting the Exception- matter done
EDIT
Handle expected Exceptions in the Method
Throw unexpected Exceptions (one by one)
Don't care of Errors
Is that the way to go?
You should not throw Throwable. Here's why.
Throwable is the top of the hierarchy of things that can be thrown and is made up of Exceptions and Errors. Since Errors by definition arise from unsalvagable conditions, it is pointless to include them in your method declaration. That leaves just Exception.
You should declare your method with throws Exception instead.
Note that the narrower the range of throws the better.
Declaring your method to be throws Exception is ok if your method doesn't generate the exceptions, but instead calls other code that is declared as throws Exception and you want exceptions to percolate up the call stack.
If your method is the generating the exception, then declare a narrower range, eg throws IOException, MyProcessingException, etc
That's a loaded question. This isn't so much about exception handling as it is about code readability.
It depends where you get your code samples from. Professionals prefer to be more specific when throwing out of a method. The main reason is that it keeps your APIs more readable. For example, if your method throws Throwable, that basically means anything could happen and your method doesn't want to deal with it, no matter what. But really, only a limited number of things could happen:
Whatever checked exceptions resulting from other calls you are making in your method
Whatever checked exceptions you are throwing on purpose based on your own assertions
Whatever unchecked exception you didn't plan for
Errors (java.lang.Error) that are more global to the JVM and the environment
By specifically stating the exceptions you want to throw, you are telling the users of your API about what they should beware of. For example, when you use InputStream, you'll notice most methods throw at least java.io.IOException, which gives you some useful information about what you should watch for.
When coding, as a general rule, you want to try to keep your APIs as expressive as possible. You've got essentially one line of code to show the public API of a method (i.e. its signature, annotations too I guess), so you want it completely expressive (return type, name, parameters, but also the thrown exceptions).
As far as catching the throwables and printing the stack trace, I'd say that you should not catch the exception unless you can do something about it. Instead, let it roll up the call stack until some class catches it to do something about it. Sometimes, it may roll all the way up to your main class, which I guess would have to catch it and print the stack trace as last resort. Basically, if you can't act upon the exception, then let it go up the call stack. Also it is extremely rare that you find yourself in a situation where you should silence an exception (i.e. catch it but do nothing about it). That's usually inviting problems when comes time to troubleshoot issues.
Here is a fun but interesting article around misuse of exception handling in general.
In some rare cases it is acceptable to throw Throwables. For example, #Around advices in Spring AOP are usually declared to throw a Throwable.
The following example is copied verbatim from Spring AOP docs:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
#Aspect
public class AroundExample {
#Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}
Why is doBasicProfiling declared to throw a Throwable? Because the original method (i.e. the execution join point), might throw an Error, RuntimeException, or a checked exception. So it only makes sense to declare doBasicProfiling to throw a Throwable.
Functionally, it is equivalent with throws Exception, since errors are unchecked.
I see no reason to declare a method to throw Throwable. However, this doesn't mean that catch and printStackTrace is a good alternative.
Usually, you want to catch throwables where you can do something sensible with them.
Code that throws a throwable you don't expect should explode gloriously, so you can see the error and fix the bug.
Is it common practice to do that?
In the JDK it is rare. This is mostly used when it is not clear how to handle checked exceptions.
What are pros & cons?
The pros is that you get your code to compile without worrying about checked exception.s
The cons is that exception you should be handling are being ignored.
Isn't it better to catch and printStackTrace()?
Unhandled exception are usually printed anyway so catching them doesn't help much.
You should catch an exception when you can add some value by doing so and add the exception to the throws clause when you can't.
It is really debatable matter.
Having method throwing too many exceptions will result in lot of error handling code. Some times it is not intended.
But because I don't like too many exception in signature does not mean that Lets use Parent of all exceptions and we are done!! It will not work.
What one can do is categorise exceptions such as BusinessException,ServiceException so that if you have a business rule which says that minimum balance in account can not be less than say 100$ then InsufficientBalance exception will be generated which will be child of BusinessException
so you method will be like
public Object doSomething() throws BusinessException {
if(!hasMinimumbalance())
{
throw new InsufficientBalance(ErrorCode);
}
}
What this will do is club related exceptions together and whenever API user wants to detect exception specific error then he can do it, else generic error handling is possible.
The core point here is on the UI you should display to the user that You have run out of balance and you can not withdraw money
You can say on the larger aspect to display human readable form of error it is really necessary to have separation of exceptions.
Are you asking about Throwable specifically? If so, then it's not good practice. It doesn't provide any useful information to class (method) user.
Throwing (and catching) Throwable (or Exception) is generally bad practice because it 'blankets' any specific exceptions you might want to catch. Then you would have to resort to ugliness like below:
public void myMethod() throws Throwable {
if (x) {
throw new MyException1();
}
if (y) {
throw new MyException2();
}
}
public void callingMethod() {
try {
myMethod();
}
catch(Throwable t) {
if (t instanceof MyException1) {
// handle exception 1
}
else if (t instanceof MyException2) {
// handle exception 2
}
else {
// handle other exceptions
}
}
}
Which is error prone (and flagged by CheckStyle as a code violation). It is much preferrable to have code like this:
public void myMethod() throws MyException1, MyException2 {
if (x) {
throw new MyException1();
}
if (y) {
throw new MyException2();
}
}
public void callingMethod() {
try {
myMethod();
}
catch(MyException1 e) {
// handle exception 1
}
catch(MyException2 e) {
// handle exception 2
}
}
Handling an exception just by calling printStackTrace() is usually not a good idea. printStackTrace() sends the stacktrace to standard error, which may not be read at all. A better option is to use the application's logging facility (like log4j) to report the exception. Even then, just logging it might no be enough.
My rule of thumb is:
If you can handle an exception locally, do so. For example when parsing a String as an Integer you could catch the NumberFormatException and return a default value:
prvate int parseAmount(String amountValue) {
int amount;
try {
amount = Integer.parseInt(amountValue);
}
catch(NumberFormatException e) {
// default amount
amount = 0;
}
return amount;
}
If you cannot handle an exception locally, consider if you should expose the exception type that is being thrown. If this type is some obscure (implementation-dependent) type, then wrapping it in your own generic exception type is probably a good idea:
private Customer getCustomer(int customerId) throws ServiceException {
try {
return customerService.getCustomer(customerId);
}
catch(CustomerServiceSpaghettiTangledException e) {
throw new ServiceException("Error calling the customer service", e);
}
}
Here 'ServiceException' is a subclass of Exception created by you. Spring also offers an exception hierarchy specifically for this purpose.
By wrapping the exception you hide the implementation details, making your service layer much simpler to use.
If you decide to throw an exception from your method, you will need to handle it 'higher up' in the callstack. This can be a generic error page in your web application stating that something went wrong and possibly providing an error message or code. In some cases the higher level code can attempt a retry or possibly an alternative way to obtain the required result.
The only use case I can think of would be for test code like unit tests. But Adam's counterpoint still stands "If so, then it's not good practice. It doesn't provide any useful information to class (method) user."