Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Java, how to force an Exception to "bubble up"?

Tags:

java

exception

I have a method that throws an Exception, which calls a method which throws an Exception, etc etc. So several methods that "throw Exception" are daisy-chained. The first method that calls the submethod, puts that submethod in a try-catch block that catches any Exception that gets thrown inside that call. IN THEORY. In practice, no Exception is being caught by that try-catch block. Is there a way to remedy that?

Here is the code:

          try {
                CSVSingleton.tryToReadBothFiles(FILE1_PATH, FILE2_PATH);

                } catch (Exception e) { // THIS BLOCK NEVER GETS ENTERED BY THE PATH O EXECUTION
System.out.println("There was an exception reading from at least one of the files. Exiting.");
                    System.exit(0);
                }

here is the method from the CSVSingleton class:

public static void tryToReadBothFiles(String filePath1, String filePath2) throws Exception {

        file1 = new CSVFileForDwellTime1(filePath1);
        file2 = new CSVFileForDwellTime2(filePath2);
    }

And here is code from the CSVFileForDwellTime1 class:

public CSVFileForDwellTime1(String filePath) throws Exception {
        super(filePath);
    }

and then here is the code that actually throws an original FileNotFoundException:

public GenericCSVFile(String filePath) throws Exception{
        this.filePath = filePath;
        try {
            fileReader = new FileReader(filePath);
            csvReader = new CSVReader(
                    fileReader);
            header = getActualHeaderNames();
        } catch (FileNotFoundException e) {
            System.out.println("Could not read file with name: " + filePath);
            // e.printStackTrace();
        }
    }

My guess is that the FileNotFoundException in the last method is caught by the catch block and so doesn't "bubble up". But is there a way to force it to bubble up?

like image 928
Alexander Mills Avatar asked Jun 12 '14 22:06

Alexander Mills


2 Answers

Immediate answer:

Your thought is exactly right,

    try {
        fileReader = new FileReader(filePath);
        csvReader = new CSVReader(
                fileReader);
        header = getActualHeaderNames();
    } catch (FileNotFoundException e) {
        System.out.println("Could not read file with name: " + filePath);
        // e.printStackTrace();
    }

This suppresses the exception Either remove the try-catch block (desired unless you can actually do something with the exception)or re-throw it within the catch block.

Explanation

Generally with checked exceptions like this you have 2 options

  1. Catch the exception and do something to remedy the exception
  2. Throw the exception to the caller

What you have done here falls into the 1st category except that you have not done anything useful in the catch block (printing to console is rarely useful in this case because the exception message itself normally has enough information to see what has gone wrong)

The 2nd category is achieved either by not using a try-catch block and thus adding throws FileNotFoundException to the method signature. Alternatively explicitly throw the exception that you caught using:

catch(FileNotFoundException e)
{
    //do something
    throw e;
}

however in this case if do something isn't worthwhile you have unnecessarily caught something just to throw it on.

You can think of it like this:

Alice throws a ball to Charlie
Bob intercepts the ball
Bob then looks at the ball and then throws it to Charlie

Bonus Points

When you know the exception that could occur make sure to actually catch or throw that exception and not a parent of that exception. Take the following method signatures for example:

public String method1() throws Exception

public String method2() throws FileNotFoundException

Here method2 clearly tells the caller what could happen and can help then figure out why the exception is being called (without having to read through the code or experience the error).

Secondly other exceptions can occur and you are potentially catching the wrong exception, take the following example:

try{
    fileReader = new FileReader(filePath); //could potentially throw FileNotFoundException
    fileReader = null; //woops
    csvReader = new CSVReader(fileReader); //throws NullPointerException but the compiler will not know this 
    //....other stuff....//
}
catch(Exception e){
    // the compiler told me that a FileNotFoundException can occur so i assume that is the reason the catch has executed
    System.err.println("You have entered an invalid filename");
    //doing anything here that would fix a FileNotFoundException is pointless because that is not the exception that occured
}
like image 186
RossBille Avatar answered Oct 30 '22 13:10

RossBille


Use a throw in the catch clause.

} catch (FileNotFoundException e) {
    System.out.println("Could not read file with name: " + filePath);
    // Continue up, Mr. Exception!
    throw e;
}

Alternatively, wrap the exception as appropriate (since an IOException is checked this handy here) - this is called a Chained Exception. Then, depending on what is thrown, the throws Exception can be removed from the method signature.

throw new RuntimeException("Could not read file: " + filePath, e);
like image 39
user2864740 Avatar answered Oct 30 '22 13:10

user2864740