How to handle throw exceptions inside finally block in java
Asked Answered
N

1

7

In java, it is not recommended to throw exceptions inside finally section in try-chatch block due to hide the propagation of any unhandled throwable which was thrown in the try or catch block. This practice is a blocker level violation according to default sonar profile.

Sonar Error: Remove this throw statement from this finally block.

Please consider the following code snippet.

e.g.: close input stream inside the finally block, and handle possible exceptions might be occurred when closing the stream.

    public void upload(File file) {
        ChannelSftp c = (ChannelSftp) channel;
        BufferedInputStream bis = new BufferedInputStream(file.toInputStream());
        try {
            String uploadLocation = Files.simplifyPath(this.fileLocation + "/" + file.getName());
            c.put(bis, uploadLocation);
        } catch (SftpException e) {
            throw new IllegalTargetException("Error occurred while uploading " + e.getMessage());
        } finally {
            try {
                bis.close();
            } catch (IOException e) {
                throw new UnsupportedOperationException("Exception occurred while closing Input stream " + e.getMessage());
            }
        }
    }

It would be grateful if you can show the conventional way of handling these situations.

Niven answered 20/12, 2016 at 14:53 Comment(7)
as a sidenote, the more smooth solution would be the usage of try-with-ressourcesLegality
Thanks for the advice.Niven
Think about what happens when the finally-block is being executed after throwing that IllegalTargetException and another UnsupportedOperationException is thrown. Which of those would the caller get? The same is true with return-statements in finally-blocks, you'd tamper with the control flow which will lead to disaster.Houdini
The general problem here is that throwing from finally{} hides any exceptions that the main body has thrown. Use try-with-resources for this sort of thing.Evensong
Possible duplicate of How to avoid throw clause in finally blockStubstad
try-with-ressources is often relevant but in case when you want to trace the exception that prevents the stream from being closed or you have to perform a recovery processing, it hides the problem.Kiln
According to your advises, try-with-resource is the best solution for this problem.Niven
N
10

Best way to handle this problem is to use try-with-resource. But if someone want to close the connection manually and show the exception of the try or catch block without hiding, following code snippet is the solution.

public void upload(File file) throws IOException {
    ChannelSftp c = (ChannelSftp) channel;
    BufferedInputStream bis = new BufferedInputStream(file.toInputStream());
    SftpException sftpException = null;
    try {
        String uploadLocation = Files.simplifyPath(this.fileLocation + "/" + file.getName());
        c.put(bis, uploadLocation);
    } catch (SftpException e) {
        sftpException = e;
        throw new IllegalTargetException("Error occurred while uploading " + e.getMessage());
    } finally {
        if (sftpException != null) {
            try {
                bis.close();
            } catch (Throwable t) {
                sftpException.addSuppressed(t);
            }
        } else {
            bis.close();
        }
    }
}
Niven answered 20/12, 2016 at 15:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.