I am unsure how best to structure custom exceptions. Say i have a situation where there's some library that throws its own custom exception class, with a custom field in it:
public class CustomException extends RuntimeException {
private final String additionalInfo;
public CustomException(String message, String additional) {
super(message);
this.additionalInfo = additional;
}
public String getAdditionalInfo() {
return additionalInfo;
}
}
Dealing with this is pretty straightforward:
try {
something();
} catch (CustomException e) {
LOGGER.error(e.getMessage());
LOGGER.error(e.getAdditionalInfo());
}
So far, so good, but what about when this is wrapped up many layers deep into some sort of service and handled in this way:
// in a subclass of a theoretical ServiceHandler interface
public void handle() throws OperationFailedException {
try {
something();
} catch (RuntimeException e) {
throw new OperationFailedException("The operation failed.", e);
}
}
Further down the callstack the service dispatch code catches this new exception, returns the generic (safe) message to the external caller, and logs the full exception trace somewhere internal, including the cause (our original custom exception type). The problem now is that the extra field in CustomException has gone missing from the logs, because the logging framework is only interested in getMessage() and the callstack.
try { // call to the ServiceHandler
sendResponseToClient(findServiceHandler(rpcName).handle(args));
} catch (Throwable th) {
LOGGER.error(th);
sendErrorToClient("An internal error occurred with incident ID: <id>");
}
I can think of a few of solutions:
1) Make the thing that logs the service exceptions aware of this special exception type so it can log it
2) Override getMessage() so it returns super.getMessage() + getAdditionalInfo()
3) Everywhere something is called that could throw one of these i rethrow it as something else with the additional field baked into the message:
try {
something();
} catch (CustomException ce) {
throw new OperationFailedException("The operation failed because " + ce.getAdditionalInfo(), ce);
} catch (RuntimeException e) {
throw new OperationFailedException("The operation failed", e);
}
The actual use case is a native code library with a few hundred functions, and they're called literally everywhere throughout this app. This exception type is a general "the api has failed in an unexepected way" error, so it's unchecked, and in day to day operation i wouldn't expect to ever see one.
(1) seems like it's easy to miss out new types in future, if in a year's time someone adds another custom exception type they need to be aware of all places that might log it and write the corresponding handler code there. (2) feels a little fishy, since you'd be creating an exception with one message, and getting a different message back. Applying the pattern in (3) to it seems like it will produce a lot of clutter, particularly if i have a couple of these custom exception types to worry about.
Which approach should i use? Are there other options, or would you recommend restructuring something to get around this?
There are essentially two cases for an exception:
1) You can recover
2) You can't, you just want your application to exit
If you can recover, you may want to think about using a checked exception.
Then you have to deal with the exception and the compiler will tell you where to catch it.
Otherwise, if the application just crashes you may want to add this additional info to the message you're giving to the superclass constructor.
Related
Let's suppose I have this class:
public class Obj1{
...
public void do_Something(int someParameter) throws SomeException {
if(...) throw new SomeException();
...
}
...
}
then, somewhere
public class Obj2{
...
public void do_SomeOtherThing(Obj1 obj1){
obj1.do_Something();
//apparently the only solution is try-catching it directly, even if I'm not in the main...
...
}
I've learned that exceptions should only be thrown by METHOD, and catched by MAIN, so, my question is: is try-catch the unique way to handle sub-method exceptions, or the most external method (do_SomeOtherThing) will throw it, so that I can try-catch it directly in main, deleting the try-catch in Object2 class?
Basically, can I do as follows?
public static void main(String[] args){
Object1 obj1 = new Object1();
Object2 obj2 = new Object2();
try{
obj2.do_SomeOtherThing(obj1);
}
catch(SomeException e){
...
}
}
or not?
A checked exception is part of the contract that a method has with its caller, and a thrown exception will always need to be handled one way or another.
The correct answer depends on the exact situation:
The caller can handle the exception:
String getStringFromRemoteServer() throws IOException { ... }
String getConfigString() {
try {
return getStringFromRemoteServer();
} catch (IOException e) {
LOG.warn("Failed to contact server, using local version.", e);
return getLocalString();
}
}
In this case we have an alternative source of the data we need, so if the preferred method fails we catch the exception, log it (so that we know a problem exists with our network) and call the alternative.
The exception is fatal, and we don't want any function higher in the call tree to try to handle it.
Configuration parseConfiguration(String configString) throws ParseException { ... }
void loadConfiguration() {
try {
this.globalConfig = parseConfiguration(getConfigString());
} catch (ParseException e) {
throw new RuntimeException("Corrupted config", e);
}
}
In this case an exception means that the configuration of our application is fatally broken. There is no point in trying to handle this error, and no point in any of our callers trying to handle it, so declaring throws on loadConfiguration() would just be confusing clutter. We wrap the exception in a RuntimeException and rethrow it. Note that we don't log it -- there will be some top level reporting of uncaught exceptions, so logging it here would be repetition.
It is still valuable to have parseConfiguration() throw a checked exception, because when we are calling it from the interactive configuration editor we catch the exception and display an error message to the user.
Maybe our caller can handle the exception.
int stringToInteger(String s) throws BadNumberException { ... }
String decimalStringToHexString(String s) throws BadNumberException {
return intToHex(stringToInteger(s));
}
In this case we are not changing the meaning of the exception -- decimalStringToHexString is converting a number from a string, and one possible outcome is that the string is illegal. Our caller needs to be aware of that as a possible outcome, just as callers of stringToInteger() are, so we simply declare the exception and let our caller handle it. Our caller knows the context they are using the number in, so they can decide how to handle the exception.
A couple of rules:
Never completely ignore an exception (OK, maybe InterruptedException). If you write try { ... } catch (Exception e) {} the empty catch clause will make it hard to spot why your code doesn't work.
When you wrap an exception, always include the original exception as the cause.
So, this is a re-ask of another question that was closed for being opinion based. So I'm re-asking my question in a more factual manner.
So, as the title says, I'm unsure if I should try to implement recoverable error classes or just stick with trying to recover in a catch block.
Some psuedo-code to demonstrate:
// more or less what I have now
postToServer(data) {
try {
socket.write(data)
}
//Interrupted being a custom exception
catch(Interrupted ex) {
//happened twice is a common static method on all custom exceptions that returns a boolean indicating if the last thrown error is the same as this one
if(Interrupted.happenedTwice(ex)) throw ex;
else postToServer(data);
}
//another custom exception indicating that the network is unreachable
catch(NetworkDrop ex) {
if(!NetworkDrop.happenedTwice(ex) && !reconnectToServer()) throw ex;
else postToServer(data);
}
}
//What I would like to implement
interface Recoverable {
public void recover(Runnable) throws Exception;
}
class NetworkDrop extends Exception implements Recoverable {
...
public void recover(Runnable resume) {
if(!NetworkDrop.happenedTwice(this) && reconnectToServer()) resume.run();
else throw this;
}
}
class Interrupted extends Exception implements Recoverable {
...
public void recover(Runnable resume) {
if(!Interrupted.happenedTwice(this)) resume.run();
else throw this;
}
}
postToServer(data) throws Exception {
try {
socket.write(data)
}
catch(Recoverable ex) {
ex.recover(() -> postToServer(data));
}
}
As the example, I'd like to have all the recovery code in the exception (reduces duplicate code, as now say 5 different methods can just call recover instead of running the same recovery code). This would allow me to catch exceptions that can be recovered, but still throw unrecoverable ones, or throw if recovery can't be done.
I see an issue with this though:
How would I recover inside a method that is expected to return data, when the intermediate Runnable called from recovery doesn't return data?
Say hypothetically I'm reading from the server instead of writing, and get a recoverable exception (such as NetworkDrop) and successfully recover. Since execution is resumed through the Runnable on the recover method, and Runnable doesn't return anything, so how would the function that called the read get the data out of the Runnable?
So, would this system be more efficient that multiple catch's? Or is the readability and simplicity I get from only catching recoverable exceptions a double edged sword?
And if the tradeoff favors Recoverable classes, how would I address the issue of getting a return value from a recovered exception?
I'm working with spring boot and I'm dealing with a good way to handle exceptions:
I have this case where interact with a repository to get a product. But what about if there is a connection issue with the DB, I'm not going to catch that exception
Product product = productRepository.findById(productId)
.orElseThrow(() -> new NotFoundException("Could not find a product"));
try {
// Product logic
} catch(Exception e) {
throw new ProductException(String.format("Error getting product productId=%s. Exception message: %s",
productId, e.getMessage()), e);
}
I have a controller advice to catch the exception and return a nice response:
#ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler({NotFoundException.class})
public ResponseEntity<Error> handleNotFoundException(HttpServletRequest request, Exception exception) {
.....
}
I think I could do something like this:
try {
Product product = productRepository.findById(productId)
.orElseThrow(() -> new NotFoundException("Could not find a product"));
} catch(NotFoundException e) {
throw new NotFoundException(e.getMessage())
} catch(Exception e) {
throw new ProductException(String.format("Error getting product productId=%s. Exception message: %s",
productId, e.getMessage()), e);
That worked but it looks weird since I'm throwing NotFoundException twice. Any idea?
Generally speaking, there is nothing weird catching an Exception just to throw it again right after. You may for example catch it to log it somewhere and then throw it to the next handler for real handling (like in your case).
You can simply write:
catch (NotFoundException e) {
// Log if needed
throw e; // <-- no need to build a new one
}
However, for the part which comes after, catching generic Exception is usually a bad practice. There are too many sources this exception may come from, and you can't just assume that it is because of the DB not responding.
So the best would be that your function catches what it knows how to handle, and throws what it doesn't know how to handle. For example:
public void yourFunction() throws NotFoundException, ProductException {
//you don't know how to handle NotFoundException and ProductException here, hence you throw them up
try {
// your logic
} catch (SpecificExceptionYouWantToCatch e) {
//handle specific exception you know how to handle
} catch (AnotherSpecificException e) {
//handle other specific exception you know how to handle
}
//Let all the other Runtime exceptions flow up to the caller.
}
If there is an exception, something went wrong. You can't just wrap it and pretend it was a ProductException, so:
If you recognize the Exception and know how to handle it, then do it (as you're doing for NotFoundException)
However, if you didn't expect that Exception, then better let it flow. At some point it will be caught and handled, maybe, or maybe will just crash the program. But you will want to know it, while if you just wrap it into a ProductException you will probably hide to the system a bigger issue.
You can still catch it in ControllerAdvice, even you don't throw it so there is no need to try caatch that exception instead add:
#ExceptionHandler({PSQLException.class})
This is for Postgres you will have different exception for other typoes of databases then you can handle the message as well and see what is the cause of it in ControllerAdvice
In Java, we handle exceptions using try catch blocks. I know that I can write a try catch block like the one below to catch any exception thrown in a method.
try {
// do something
}
catch (Throwable t) {
}
But is there any way in Java which allows me to get a specific method called when an exception happens, instead of writing a catch-all method like the one above?
Specifically, I would like to show a user friendly message in my Swing application when an exception is thrown (which is not handled by my application logic).
Thanks.
By default, the JVM handles uncaught exceptions by printing the stack-trace to System.err stream. Java allows us to customize this behavior by providing our own routine which implements Thread.UncaughtExceptionHandler interface.
Take a look at this blog article which I wrote sometime back which explains this in detail ( http://blog.yohanliyanage.com/2010/09/know-the-jvm-1-uncaught-exception-handler/ ).
In summary, all you have to do is write your custom logic as below :
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
// Write the custom logic here
}
}
And set it using any of the three options I have described in the above link. For example, you could do the following to set the default handler for the entire JVM (so any uncaught exception thrown will be handled by this handler).
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler() );
try {
// do something
methodWithException();
}
catch (Throwable t) {
showMessage(t);
}
}//end business method
private void showMessage(Throwable t){
/* logging the stacktrace of exception
* if it's a web application, you can handle the message in an Object: es in Struts you can use ActionError
* if it's a desktop app, you can show a popup
* etc., etc.
*/
}
Show the friendly message from within the catch block.
you could wrap each method that can throw in a try catch
or use the getStackTrace()
catch (Throwable t) {
StackTraceElement[] trace = t.getStackTrace();
//trace[trace.length-1].getMethodName() should contain the method name inside the try
}
btw catching throwable in not recommended
I am new to Android mobile application development.
I would like to know, how can I handle exceptions like HttpConnection related exceptions or any other exceptions? Do I need to display an AlertDialog to the user?
Kindly provide a sample code or project source code on how can I handle HttpConnection or similar type of Exceptions.
There are 2 different kinds of exceptions in Java: Checked and Unchecked. There is a big debate over which one is better to use, both arguments are good.
Basically a Checked exception is derived from java.lang.Exception and it requires that if you don't specify your method as "throws MyCheckedException" then you must catch and handle the exception within your method.
// throw the exception
void foo() throws MyCheckedException
{
throw new MyCheckedException();
}
// or handle the exception
void foo()
{
try {
throw new MyCheckedException();
} catch (MyRuntimeException e) {
e.printStackTrace();
}
}
An Unchecked exception, derived from java.lang.RuntimeException, requires neither that you specify "throws" in your method definition nor that you handle it.
void foo()
{
throw new MyUncheckedException();
}
The advantage of Checked is that the compiler will warn you when you haven't handled an exception.
The disadvantage is that you have to declare either a try/catch block or a throws for every Checked exception, and the upper level code can get pretty cumbersome, trying to handle all the different types of Exceptions.
For this reason, if you're careful you might prefer using Unchecked Exceptions.
BTW, you can only choose your exception type when you define your own.
When encountering Exceptions from Java or a 3rd party library, you have to decide how to handle it. e.g. If a 3rd party method throws CheckedException1, then you have to either handle it, or declare the calling method as "throws CheckedException1". If you want to avoid using Checked Exceptions then you can wrap it in an Unchecked Exception and throw that.
void foo() // no throws declaration
{
try {
thirdPartyObj.thirdPartyMethod(); // this throws CheckedException1
}
catch (CheckedException1 e) {
throw new MyUncheckedException(e); // this will wrap the checked in an unchecked.
}
}
Note that you can throw the Unchecked exception without the "throws" declaration. To access the original CheckedException1 from higher up, you can use the .getCause() method of your Unchecked exception.
void caller()
{
try {
foo();
} catch (MyUncheckedException e) {
CheckedException1 ce1 = e.getCause();
ce1.printStackTrace();
}
}
... but because the exception from foo() is Unchecked, you don't have to handle it or declare "throws".
Regarding logging, there are different schools of thought on this.
Log it when the exception occurs (low - level)
Log it when it reaches the top (high - level)
Log it when you have enough information to make an appropriate action and/or a log message. (mid - level)
A good policy I've found is to install an uncaught exception handler which will take care of all uncaught (obviously unchecked) exceptions. This way anything that is missed will be logged and potentially handled before crashing the system.
public class MyExceptionHandler implements UncaughtExceptionHandler
{
#Override
public void uncaughtException(Thread thread, Throwable ex)
{
ex.printStackTrace();
}
}
// In your high-level code
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
and all for Exceptions that can be handled gracefully, catch and handle them in a module where you know enough about the situation to possibly correct the problem and try again.
How you handle exception depends on the exception. If the exception is something that you cannot recover from, and the user needs to know about then you could catch the exception and show it in an AlertDialog:
try {
// do something
} catch (SomeImportantException e) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("User friendly text explaining what went wrong.");
AlertDialog alert = builder.create();
alert.show();
}
For more info on the dialog, see creating dialogs.
Alternatively, if the exception is something that you can deal with, you can just log information about the exception and move on.
try {
// do something
} catch (SomeLessImportantException e) {
Log.d(tag, "Failed to do something: " + e.getMessage());
}
You could use the ACRA plugin that offers this functionality or BugSense to gather error reports.
Disclaimer: I am a founder at BugSense.