Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid exception shadowing?

Tags:

java

exception

When an exception occurs during the handling of an exception, only the last exception gets reported, because I can add just one exception to an Error object. How to report all exception in the final error message?

Example:

class main
{
  public static void main (String[] args)
  {
    try {
      // Database.insert ();
      throw new Exception ("insert failed");
    }
    catch (Exception ex1) {
      try {
        // Database.rollback ();
        throw new Exception ("rollback failed");
      }
      catch (Exception ex2) {
        throw new Error ("Can not roll back transaction.", ex2);
      }
    }
    finally {
      try {
        // Database.close ();
        throw new Exception ("close failed");
      }
      catch (Exception ex3) {
        throw new Error ("Can not close database.", ex3);
      }
    }
  }
}

In the example everything fails. The database insert causes ex1. The rollback causes ex2. And closing the database causes ex3. When the program gets executed only the last ex3 gets reported in the Error object. How to include also ex1 and ex2 to the Error object? The constructor of Error accepts just one exception.

like image 633
ceving Avatar asked Aug 27 '20 08:08

ceving


People also ask

How do you overcome exception handling?

The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.

What are the three types of exceptions?

There are three types of exception—the checked exception, the error and the runtime exception.

How do you catch exceptions without trying?

throws: The throws keyword is used for exception handling without try & catch block. It specifies the exceptions that a method can throw to the caller and does not handle itself. 5. finally: It is executed after the catch block.

Is it a good approach to throw an exception?

The short answer is NO. You would throw an exception if the application can't continue executing with the bad data. In your example, the logic is to display an error message on the front end and Option 2 is the cleaner method for achieving this requirement.


Video Answer


1 Answers

I suggest you to use try-with-resource-statements introduced in Java 7, in conjunction with the AutoCloseable-interface.

Sidenote: The Connection, Statement and ResultSet from java.sql all implement AutoCloseable

try (Connection c = DriverManager.getConnection(url)) {
    // do your inserts
} catch (Exception e) {
    throw new Error("Insert failed", e);
}

This will close your connection or generally the passed AutoCloseable appropriately. And will handle the shadowing of the exception by using the Throwable.addSuppressed() method.

What the equivalent looks like in previous versions can be seen on this other question


Your questions also mentiones a rollback which I haven't covered. This can be done by using the before mentioned Throwable.addSuppressed() method (as pointed out in the comments by tobias_k), though to be honest it gets quite a bit more messy, and doesn't look as nice anymore:

Exception insertException = null;
try (Connection c = DriverManager.getConnection(url)) {
    try {
        // do your inserts
    } catch (Exception e1) {
        insertException = e1;
        // do your rollback
    }
} catch (Exception e2) {
    Error error = new Error("Insert failed", insertException);
    error.addSuppressed(e2);
    throw error;
}

Just for clarification, the inner catch-block, can only be reached when the insert fails. Where as the outer catch can be reached, when any of the following throws an exception:

  • DriverManager.getConnection()
  • Your rollback
  • Connection.close()

For a small demo you can visit this link, which illustrates how the stacktrace looks like.

like image 116
Lino Avatar answered Sep 28 '22 09:09

Lino