What I would like to achieve:
Have a method to get javax.net.ssl.KeyManagerFactory;
What I tried:
Here is the code:
public final KeyManagerFactory getKeyManagerFactory() throws GeneralSecurityException, IOException {
final var keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
try (InputStream file = new FileInputStream(keyStoreLocation)) {
final var keyStore = KeyStore.getInstance(PKCS12);
keyStore.load(file, keyStorePassword.toCharArray());
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
return keyManagerFactory;
}
}
Issue:
After SonarQube scan, I am getting Refactor this method to throw at most one checked exception instead of:
Note:
It uses to have all sorts of exceptions
UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException CertificateException, IOException, NoSuchAlgorithmException FileNotFoundException
and I tried to refactor the best I could, but still left with Refactor this method to throw at most one checked exception instead of: java.security.GeneralSecurityException, java.io.IOException
Question:
How to refactor this to throw at most one checked exception without using throws Exception
which will trigger another SonarQube issue?
The SonarQube comment means that there's a chance the method will throw multiple exceptions. It means it might make it longer to handle exceptions this method can throw wherever it is being called (and possibly produce repetitive code).
To optimise this code you could handle both exceptions in the method itself and throw another exception instead.
You could possibly create a custom KeyManagerFactoryException
(or more relevant, would be an exception relating to your class name). Your code that can produce an exception should be surrounded with try-catch block and both exceptions could be handled in there.
public final KeyManagerFactory getKeyManagerFactory() throws KeyManagerFactoryException {
final var keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
try (InputStream file = new FileInputStream(keyStoreLocation)) {
final var keyStore = KeyStore.getInstance(PKCS12);
keyStore.load(file, keyStorePassword.toCharArray());
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
return keyManagerFactory;
} catch (IOException ex) {
// some logging or extra handling of the error
throw new KeyManagerFactoryException("Your exception message documenting the error", ex);
} catch (GeneralSecurityException ex) {
// some logging or extra handling of the error
throw new KeyManagerFactoryException("Your exception message documenting the error", ex);
}
}
And your custom exception class would look something like:
public class KeyManagerFactoryException extends Exception {
public KeyManagerFactoryException(String message, Throwable cause) {
super(message, cause);
}
}
As a result, your method will only be able to raise an exception of a single type.