Как правильно организовать обработку исключение в MVC в Java?
Имеется структура каталогов, разработанная на основе MVC, и имеет вид (другие каталоги исключены для наглядности и понимания сущности происходящего):
model/dao/AccountDao.class
util/AesCrypt.class
Имеется класс AesCrypt, содержащий метод encrypt(String password), который занимается шифрованием и дефишрованием пароля:
public String encrypt(String password) throws CryptException {
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(VECTOR.getBytes(StandardCharsets.UTF_8));
SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return new String(Hex.decodeHex(password.toCharArray()));
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | DecoderException e) {
LOGGER.error("Cant' create a crypt.");
throw new CryptException("Can't create a crypt.", e);
}
}
Как вы можете заметить, внутри имеется обработка возможных исключений.
В классе AccountDao имеется метод create(Account account, String password), который внутри себя занимается шифрованием пароля, переданного в данный метод, для последующего помещения зашифрованного пароля в БД. Внутри данного метода нужно будет вызвать метод шифрования пароля create(Account account, String password) того самого AesCrypt и выглядит это дело так (лишний код заменен на комментарии):
@Override
public boolean create(Account account, String password) throws DaoException {
// ... code
AesCrypt crypt = utilProvider.getAesCrypt();
try {
// ... code
String cryptPassword = crypt.encrypt(password); // тут должна быть обработка исключений
} catch (SQLException e) {
LOGGER.error("Couldn't create an account in the database: {}.", account);
throw new DaoException("Couldn't create an account in the database " + account);
}
// ... code
}
В строке String cryptPassword = crypt.encrypt(password); должна быть обработка исключений.
Вопрос - опять повторно нужно обрабатывать исключения или как правильно организовать код? Получится, что в двух разных классах будет дублирование кода, который обрабатывает исключения.
Ответы (1 шт):
В строке String cryptPassword = crypt.encrypt(password); должна быть обработка исключений.
Не обязательно, а в этом случае, скорее всего, не нужна. Обработку исключений нужно делать там, где это имеет смысл, а именно там, где клиент получивший исключение, может что-то осмысленное с ним сделать.
Примеры, когда можно что-то сделать:
- ошибка соединения с сетью - можно попробовать опять после паузы
- ошибка во входных данных предоставленных пользователем - можно и нужно попросить ввести данные заново
В вашей же ситуации, если функция create(Account account, String password) получит, скажем, NoSuchAlgorithmException, она ничего сделать не может. Это ошибка программиста и нет никакой возможности на этом уровне обработать такие исключения, вызванные ошибкой программиста. Правильное решение это сделать CryptException runtime исключением, и не обрабатывать его в этом месте вообще. В крайнем случае завернуть в DaoException, если у вас по контракту, все исключения из DAO слоя заворачиваются в DAOException.
Обработка этого исключение будет в обобщенном виде на уровне контроллера, там где он ловит все исключения, и в зависимости от типа возвращает соответствующий http status, если это web приложение.