Java 1.6: Learn How To Handle Exceptions

I've done extensive research on exceptions, but I'm still lost. I would like to know what is good to do or not.

And I would also like you to give me your expert opinion on the following example:

public void myprocess(...) {
    boolean error  = false;

    try {

        // Step 1
        try {
            startProcess();
        } catch (IOException e) {
            log.error("step1", e);
            throw new MyProcessException("Step1", e);
        }

        // Step 2
        try {
            ...
        } catch (IOException e) {
            log.error("step2", e);
            throw new MyProcessException("Step2", e);
        } catch (DataAccessException e) {
            log.error("step2", e);
            throw new MyProcessException("Step2", e);       
        }

        // Step 3
        try {
            ...
        } catch (IOException e) {
            log.error("step3", e);
            throw new MyProcessException("Step3", e);
        } catch (ClassNotFoundException e) {
            log.error("step3", e);
            throw new MyProcessException("Step3", e);       
        }

        // etc.

    } catch (MyProcessException mpe) {
        error = true;       
    } finally {
        finalizeProcess(error);
        if (!error) {
            log.info("OK");
        } else {
            log.info("NOK");
        }           
    }
}

      

  • Is it possible to throw an individual exception (MyProcessException) at each step to manage a global attempt to ... catch ... finally?
  • Can every known exception be managed for every step?

Thank you for your help.


EDIT 1:

Is this good practice? log directly in the global catch getting the message and try ... catch (Exception) at the top level ....

The goal is to stop if the step fails and complete the process (error or not).

In Controller

public void callProcess() {
    try {
        myprocess(...);
    } catch (Exception e) {
        log.error("Unknown error", e);
    }   
}

In Service

public void myprocess(...) {
    boolean error  = false;

    try {

        // Step 1
        try {
            startProcess();
            log.info("ok");
        } catch (IOException e) {
            throw new MyProcessException("Step1", e);
        }

        // Step 2
        try {
            ...
        } catch (IOException e) {
            throw new MyProcessException("Step2", e);
        } catch (DataAccessException e) {
            throw new MyProcessException("Step2", e);       
        }

        // Step 3
        try {
            ...
        } catch (IOException e) {
            throw new MyProcessException("Step3", e);
        } catch (ClassNotFoundException e) {
            throw new MyProcessException("Step3", e);       
        }

        // etc.

    } catch (MyProcessException mpe) {
        error = true;       
        log.error(mpe.getMessage(), mpe);           
    } finally {
        finalizeProcess(error);
        if (!error) {
            log.info("OK");
        } else {
            log.info("NOK");
        }           
    }
}

      

Thank.


Edit 2:

Is it real bad practice to catch (exception e) at a lower level and throw a personal exception?

+3


source to share


6 answers


In the above example, it may be acceptable to throw your own custom exception.

Imagine I have some Data Access Objects (DAOs) that come in different flavors (SQL, read / write to files, etc.). I don't want each DAO to throw exceptions specific to their mechansim storage (SQL related exceptions, etc.). I want them to pick CouldNotStoreException

as the abstraction layer the client is working on. Throwing an SQL related or File related exception will expose the inner workings and the client is not interested in doing so. They just want to know if the read / write operation worked.

You can create your custom exception using the exception as a reason . This way you won't lose the original information related to your problem.



In the example above, I probably won't handle every exception at every step like you did. If processing cannot continue after the exception, I would just wrap the entire block of code in an exception handling block. This improves readability and you don't have to catch the exception and then (later) check the processing status to make sure you can continue as usual (if you don't, you are going to throw a lot of exceptions for one original problem and this is not useful ).

I would have wondered if adding multiple blocks catch {}

per exception (is there something different for each one?). Note that Java 7 allows you to handle multiple classes of exceptions in a single catch {} (I understand that you are in Java 6, but I notice this for completeness).

Finally, you might want to consider checking vs unchecked exceptions .

+2


source


There is no general rule, it depends on your needs. You can throw a personal exception and you can manage every known exception.

But note, what matters is what you want.



try{
   exec1();
   exec2(); // if exec1 fails,  it is not executed
}catch(){}

try{
   exec1();
}catch(){}

try{
   exec2(); // if exec1 fails,  it is  executed
}catch(){}

      

+2


source


The main reason for the exclusion mechanism is to shorten and group the processing code. You handle them in a typical language with no exceptions, such as C: each event has a separate processing block.

In most cases, the best option is to surround the entire method code with catch-all:

try {
 .... method code ...
} 
catch (RuntimeException e) { throw e; } 
catch (Exception e) { throw new RuntimeException(e); }

      

The only cases where this doesn't fit are where you want to insert specific handling code, or wrap a custom exception that will be handled later.

Most exceptions, especially IOExcption

in your case, are nothing more than a failure and will not be handled without registering and returning the application to a safe point where it can handle further requests.If you repeat the same handling code over and over again. this is a signal that you are doing it wrong.

One very important rule: either a descriptor or ; never do both. This is what you do in your example: both logging and refactoring. Most likely, the repeated exception will be caught in the call stack and logged again. Reading the resulting log files is a nightmare, but sadly familiar.

+1


source


int step = 0;

try
{
    step = 1;
    ...
    step = 2;
    ...
    step = 3;
    ...
}
catch (Exception1 e)
{
    log ("Exception1 at step " + step);
    throw new MyException1 ("Step: " + step, e);
}
catch (Exception2 e)
{
    log ("Exception2 at step " + step);
    throw new MyException2 ("Step: " + step, e);
}
...

      

0


source


I would say it depends on your needs ...

If step2 can execute correctly even if step1 failed, you can try / catch step1 separately.
Otherwise, I would group all the steps in one try / catch block and make sure the individual steps generate a log message when they fail. This way you don't clutter your code and still know what went wrong.

It's good to catch every known exception, so you can log what the exception is and why it did it.

0


source


Here are some links to handling patterns / anti-error handling patterns:

do:

Not

About creating your own exceptions is of course useful if you are building an API, framework, or other piece of reusable code, but in a typical application it is more controversial and I personally suggest sticking to existing exceptions.

0


source







All Articles