Reputation: 1017
I am developing some background program that every now and then does 'something'. However, 'something' may go wrong and I want to write a log so that I can figure out what is going wrong and there could be different reasons for the error. I am using a closed source lib (with no documentation available right now) and I do not know the structure of the exception(s) thrown and the stacktrace does not give me a sufficient amount of information.
Question: How can I generally make 'all possible information' visible for an Exception class I do not 'wish' to know?
I.e. is there some way to make the exception explain itself without any further knowledge?
Example (caution, lengthy :-)):
Let us consider the following example of a bank account. The account has a function offers a function 'withdraw' which obviously (or should I say sadly) throws the exception InsufficientFundsException:
public class Account {
[...]
private double balance;
public void withdraw(double amountWithDraw) throws InsufficientFundsException {
if(amountWithDraw <= balance) {
balance -= amountWithDraw;
} else {
throw new InsufficientFundsException(balance, amountWithDraw);
}
}
}
and the exception class looks like
public class InsufficientFundsException extends Exception {
private double balance;
private double amountWithDraw;
public InsufficientFundsException(double balance, double amountWithDraw) {
this.amountWithDraw = amountWithDraw;
}
public double getBalance() {
return amountWithDraw;
}
public double getAmountWithDraw() {
return amountWithDraw;
}
}
Now in the main calling code I would probably be doing something like
try {
account.withdraw(amountWithDraw);
} catch (InsufficientFundsException e) {
System.out.println("Tried to reduce " + e.getBalance() + " by " + e.getgetAmountWithDraw() + " but taking this much amount of money from the account is not possible!");
}
Until that, everyhing is fine but let us say that the main code gets a lot of different 'requests' (add money, subtract money, send information out how much money the account contains, ...). Every of these requests may have different possible failure situations like AddMoneyException, NetworkUnreachableException, ... So the main code would look like
try {
handleRequest(...);
} catch (InsufficientFundsException e) {
System.out.println("Tried to reduce " + e.getBalance() + " by " + e.getgetAmountWithDraw() + " but taking this much amount of money from the account is not possible!");
} catch (NetworkUnreachableException e) {
System.out.println("Network unreachable.");
} catch (AddMoneyException e) {
...
} and so on and so on
So, on the one hand, the code becomes very clumsy (I need to drag many different Exceptions through the calling stack of functions) and on the other hand, I do not know the Exceptions AddMoneyException and NetworkUnreachableException (except from their name I do not know how to find the reason why the network was unreachable or why we were not able to add some money to the account).
So I thought it would be a good Idea to dispatch the exceptions at the point where they are thrown and then just create one new Exception 'RequestFailedException' which then can be handled uniformly like this:
try {
handleRequest(...);
} catch (RequestFailedException e)
System.out.println("Request failed. Reason=" + e.getReason());
}
Now the withdraw function looks like this:
public void withdrawUnified(double amountWithDraw) throws RequestFailedException{
try {
widthDraw(amountWithDraw);
} catch (InsufficientFundsException e) {
throw new RequestFailedException("Tried to reduce " + e.getBalance() + " by " + e.getgetAmountWithDraw() + " but taking this much amount of money from the account is not possible!");
} catch (NetworkUnreachableException e) {
throw new RequestFailedException("Network is unreachable!");
}
}
So I somehow need to cast every of the possible exceptions into a string containing all the information about the exception (i.e. also 'custom properties' like balance and amountWithdraw, not only the StackTrace). However, I do not know/would have to guess these properties. Is there a uniform function that somewhat gets overwritten like toString? Just doing
public void withdrawUnified(double amountWithDraw) throws RequestFailedException{
try {
widthDraw(amountWithDraw);
} catch (Exception e) {
throw new RequestFailedException("Exception=" e);
}
}
does not work as this just prints out the first line of the stacktrace.
Regards + thanks in advance,
FW
Upvotes: 3
Views: 684
Reputation: 6126
What I would suggest to do if you are intended to use the customized exception also as kind of message bearer is to override the getMessage in the class to reflect what you want to say about the reason of failure:
public class InsufficientFundsException extends Exception {
private double balance;
private double amountWithDraw;
public InsufficientFundsException(double balance, double amountWithDraw) {
this.amountWithDraw = amountWithDraw;
}
public double getBalance() {
return amountWithDraw;
}
public double getAmountWithDraw() {
return amountWithDraw;
}
public String getMessage() {
"Tried to reduce " + balance() + " by " + amountWithDraw() + " but taking this much amount of money from the account is not possible!"
}
}
And in your code:
public void withdrawUnified(double amountWithDraw) throws RequestFailedException{
try {
widthDraw(amountWithDraw);
} catch (Exception e) {
throw new RequestFailedException("Request Failed", e);
}
}
Upvotes: 2
Reputation: 140417
You are mixing up two things here:.
The real solution is to step back and clearly separate the two issues. What you can do for example: create your own exception base class, and add methods to it such as getErrorMessageForUser()
. Now each of your subclasses can provide a specific, human understandable error description.
At the same time, your top-level code only catches that specific exception, to then use the message coming from the exception.
( I suggest to not use the built-in exception messages. At least in larger systems, you quickly start to think about internationalization, as in: how to make sure that error messages are given in the specific language of the user )
Upvotes: 1