Перехватчики Java и проверенное исключение

Я использую функцию Spring AOP. у меня класс называется

class UserService {
    public User insertUserService(User user) throws PersistenceLayerException {
        System.out.println("UserServiceImpl_Two called: insertUserService method");

        if (user.id == 1) 
            throw new PersistenceLayerException();

        return null;
    }
}

Теперь вызовы этого метода insertUserService перехватываются перехватчиком, который выполняет некоторую проверку. Этот перехватчик проверки выдает проверенное исключение с именем BusinessException. Теперь, когда выдается это исключение, Java выдает UndeclaredThrowableException, потому что BusinessExcepetion не объявлено в бросках insertUserService. Есть ли способ обойти это UndeclaredThrowableException без объявления BusinessException в предложении throws.

Причина в том, что в самом insertUserService нет ничего, что выбрасывало бы BusinessException, поэтому его появление должно быть наоборот.


person TimeToCodeTheRoad    schedule 25.06.2014    source источник


Ответы (3)


Одна из идей, если это возможно, состоит в том, чтобы сделать BusinessException подклассом RuntimeException, что в любом случае больше соответствует философии Spring.

ИЗМЕНИТЬ:

Вы также спросили, есть ли способ сделать это с проверенными исключениями. Один из подходов, который вы можете использовать, основан на переосмыслении вашего UserService контракта. «Сервисы» (в смысле сервисного компонента) обычно представляют собой концепции домена более высокого уровня, поэтому в любом случае может быть более подходящим объявить BusinessException из вашего UserService контракта. Затем, когда возникает проблема сохраняемости более низкого уровня, вы можете либо обернуть это с помощью BusinessException (если BusinessException означает что-то общее, например «вызов бизнес-службы не выполнен»), либо просто объявить как BusinessException, так и PersistenceLayerException, если вы хотите, чтобы BusinessException имел узкое значение (например, вопросы проверки и тому подобное).

В этом случае вы можете использовать UserService как Spring Security UserDetailsService, который действительно более ориентирован на сохранение. Если это так, то мысли выше могут быть неприменимы. Но в остальном считайте это вариантом.

Сказав все это, создание BusinessException как RuntimeException наиболее соответствует практике Spring и, возможно, является лучшей практикой по причинам, которые я описываю здесь.

person Community    schedule 25.06.2014
comment
Согласованный. Наличие перехватчика, который выдает проверенное исключение, вероятно, не очень хорошая идея. Вид побеждает идею прозрачности. - person NilsH; 25.06.2014
comment
@Willie: привет, я как раз читал твой блог, Вилли. Я согласен, что создание подкласса Runtime Exception - это один из способов, но есть ли способ справиться с проверенными исключениями? - person TimeToCodeTheRoad; 25.06.2014
comment
Маленький мир. :-) Если и есть, то я об этом не знаю. Но я не эксперт по АОП, так что не принимайте мое невежество в этом вопросе слишком серьезно. :-Д - person ; 25.06.2014
comment
Спасибо, Вилли. Я решил объявить оба исключения: BusinessException и Persistence Exception. Я не могу сделать Business Exception подклассом RuntimeException, потому что он используется в других местах приложения, и я не хочу менять основное исключение. - person TimeToCodeTheRoad; 25.06.2014

Один из способов, который я могу придумать (поскольку вы говорите, что BusinessException является проверенным исключением), оберните ваше исключение фактическим выбрасываемым исключением. Как показано ниже, и обработайте его соответствующим образом. В любом случае обертывание Business Exception в PersistenceException не рекомендуется (спасибо Wille за указание на это)

throw new PersistenceLayerException(new BusinessException(..));
person vinayknl    schedule 25.06.2014
comment
-1 Поскольку эта проверка происходит выше слоя сохраняемости. Поэтому ошибочно заключать его в исключение PersistenceLayerException. - person ; 25.06.2014
comment
Тогда вообще не рекомендуется создавать какие-либо BusinessException. Ответ дается исходя из предположения, что ему необходимо выполнить бизнес-валидацию на уровне постоянства. - person vinayknl; 25.06.2014
comment
Вы все равно можете сгенерировать BusinessException, а затем обработать его неким глобальным обработчиком (например, таким как @ControllerAdvice), который сообщает о недопустимом объекте. Исключение PersistenceLayerException должно указывать на проблему, возникающую на уровне сохраняемости. То, что вы описываете, на самом деле просто туннелирует запрос проверки через объявленное исключение. - person ; 25.06.2014
comment
Хм, если подумать о вашем последнем утверждении, я понимаю вашу точку зрения. Это не так, как я бы это сделал, но я уберу отрицательный голос, так как вижу вашу логику. - person ; 25.06.2014

Я не знаком с перехватчиками Spring, но полагаю, что логика, стоящая за ними, будет примерно такой же, как и в стандартной Java EE javax.interceptor.AroundInvoke:

Определяет метод-перехватчик, который вставляется в бизнес-методы... AroundInvoke методы могут генерировать любые исключения, которые разрешены предложением throws метода, в который они вставляются.

Таким образом, он говорит, что вы не должны генерировать проверенное исключение, не объявленное бизнес-методом, который вы украшаете своим перехватчиком.

На самом деле, не совмещать проверенные исключения и АОП — довольно распространенная практика. Я воспринимаю обработку исключений с помощью АОП как некую альтернативную парадигму использованию проверенных исключений.

person Honza Zidek    schedule 22.10.2015