Кажется, самый простой способ сделать это - использовать перехватчик CDI для перехвата исключений. Мы можем определить CDI Interceptor следующим образом:
@InterceptorBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TransactionDebugger {
}
Как только мы определили CDI Interceptor, нам нужно создать класс, который будет выполняться при использовании аннотации Interceptor. Мы определяем @AroundInvoke, чтобы наш код вызывался перед кодом в методе, который мы аннотируем. invocationContext.proceed()
вызовет метод, который мы аннотируем, и выдаст нам результат (если таковой имеется), который он вернул. Таким образом, мы можем поместить try, catch (Exception)
вокруг этого вызова, чтобы перехватить любое возникшее исключение. Затем мы можем зарегистрировать это исключение с помощью регистратора (здесь используется log4j) и повторно выбросить исключение, чтобы любой вышестоящий код также был проинформирован об этом.
Повторное генерирование исключения также позволит нам использовать CMT (Контейнерные управляемые транзакции), поскольку в конечном итоге контейнер перехватит исключение и сгенерирует транзакцию RollbackException. Однако вы также можете легко использовать UserTransactions с этим и выполнять откат вручную при обнаружении исключения вместо его повторной генерации.
@Interceptor
@TransactionDebugger
public class TransactionInterceptor {
private Logger logger = LogManager.getLogger();
@AroundInvoke
public Object runInTransaction(InvocationContext invocationContext) throws Exception {
Object result = null;
try {
result = invocationContext.proceed();
} catch (Exception e) {
logger.error("Error encountered during Transaction.", e);
throw e;
}
return result;
}
}
Затем мы должны включить наш новый перехватчик в наш beans.xml (обычно расположенный в src / META-INF), поскольку перехватчики по умолчанию не включены в CDI. Это должно быть сделано во ВСЕХ проектах, в которых используется аннотация, а не только в проекте, в котором аннотация определена. Это связано с тем, что CDI инициализирует перехватчики для каждого проекта:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
<interceptors>
<class>package.database.TransactionInterceptor</class>
</interceptors>
</beans>
Наконец, мы должны аннотировать методы, которые мы вызываем с помощью нашего нового перехватчика CDI. Здесь мы аннотируем их с помощью @Transactional, чтобы начать транзакцию, и @TransactionDebugger, чтобы перехватить любое исключение, возникающее в транзакции:
@Transactional @TransactionDebugger
public void init() {
...
}
Теперь это будет регистрировать ЛЮБУЮ ошибку, возникающую при выполнении кода init (). Гранулярность ведения журнала можно изменить, изменив try, catch с Exception на подкласс Exception в классе реализации Interceptor TransactionInterceptor.
person
rachekalmir
schedule
22.11.2013