Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Handle multiple exceptions in method

I'm developing a public API for people to use in their applications. I'm currently trying to figure out the best way to handle exceptions. For example, the following code snippet throws four different kinds of exceptions:

Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
s.initSign(keyChain.getPrivateKey());               //InvalidKeyException
s.update(plainText.getBytes("UTF-8"));              //UnsupportedEncodingException
byte[] signature = s.sign();                        //SignatureException
String signedData = base64Encoder.encode(signature);

My question is, how do I handle these in the best possible way?

One way I came up with was catching exceptions and throwing a custom exception:

public void signRequest(Request request) throws APISignatureException {
    try {
        ...
        Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
        s.initSign(keyChain.getPrivateKey());               //InvalidKeyException
        s.update(plainText.getBytes("UTF-8"));              //UnsupportedEncodingException
        byte[] signature = s.sign();                        //SignatureException
        String signedData = base64Encoder.encode(signature);
        ...
    }
    catch (Exception e) {
        throw new APISignatureException("Failed to create signature", e);
    }
}

Is this a good way of handling exceptions for an open API?

like image 761
anony115511 Avatar asked Dec 20 '22 10:12

anony115511


2 Answers

It's nearly a reasonable way! I'd say that if you replaced your catch with a list of specific exceptions, rather than a blanket Exception, it would be completely defensible.

It would also be quite reasonable to let all four types propagate upwards, though. It depends on what you want. If the user wants to have immediate access to the reason for failure, you might leave the types unaltered and uncaught. If you want this layer of abstraction, where the user just gets a "something went wrong with the signature" type, but can still drill down into the details, then the structure you've got is ideal.

The point is that you're not hiding anything: the original exception is still buried in the new one, and available to the caller.

like image 92
chiastic-security Avatar answered Dec 21 '22 23:12

chiastic-security


Catching general Exceptions is usually a bad idea.

You can do this instead (Java 7):

public void signRequest(Request request) throws APISignatureException {
    try {
        Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
        s.initSign(keyChain.getPrivateKey());               //InvalidKeyException
        s.update(plainText.getBytes("UTF-8"));              //UnsupportedEncodingException
        byte[] signature = s.sign();                        //SignatureException
        String signedData = base64Encoder.encode(signature);
    }
    catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException | SignatureException e) {
        throw new APISignatureException("Failed to create signature", e);
    }
}

But ask yourself what the client is going to do with this as you're forcing him to still catch your Exception.

If the client shouldn't be concerned because in general this won't go wrong, you can throw an unchecked Exception:

public void signRequest(Request request) {
    try {
        Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
        s.initSign(keyChain.getPrivateKey());               //InvalidKeyException
        s.update(plainText.getBytes("UTF-8"));              //UnsupportedEncodingException
        byte[] signature = s.sign();                        //SignatureException
        String signedData = base64Encoder.encode(signature);
    }
    catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException | SignatureException e) {
        throw new RuntimeException("Failed to create signature", e); // This doesn't need to be explicitly caught
    }
}

What I mean is, if the signing goes wrong, there's probably no need for the user to continue his application as if nothing happened by catching your own Exception. He need to change some configuration and run his application again. The RuntimeException will just propagate until a more general catcher is catching it.

like image 38
Davio Avatar answered Dec 22 '22 00:12

Davio