在记录到文件之前捕获 EJBTransactionRolledbackException

Catch EJBTransactionRolledbackException before it is logged to file

我的设置:

我有一个 EJB bean(部署在 JBoss 6.4 上的 ear 中),它具有计算某些值并将其存储在数据库中的方法。该方法在新事务中启动。它看起来像这样:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void doStuff() {
    MyObject value = calculateSomeValues();

    entityManager.merge(value);
    entitiyManager.flush();
}

根据设计,刷新可能会因 ConstraintViolationException 而失败。由于这是一个新事务,异常将被包装在 EJBTransactionRolledbackException 中并作为 RuntimeException 抛出。我已经为 ejb 异常设置了日志记录,因为它有助于在整个系统中找到它们。然而,据我所知,ConstraintViolationException 会不时发生,我想在日志系统将其记录为错误之前捕获它并回滚(约束违规不被视为异常,但从数据库的角度来看是必需的看法)。目前,我的日志文件被这样的条目堵塞:

ERROR [org.jboss.as.ejb3.invocation] (default-threads - 49) JBAS014134: EJB Invocation failed on component

如何以阻止记录器打印这些错误的方式捕获异常? (注意:我仍然希望它记录所有其他 EJBTransactionRolledbackExceptions)

我没有部署 JBoss 6,所以我无法立即测试精确的异常类型是否也适用于 JBoss 6(我在 WildFly 8 上试过)。

一个可能的解决方案是在您的 EJB 中放入一个由 @AroundInvoke 注释的方法(至少如果您在此 EJB 上没有其他拦截器):

   @AroundInvoke
   public Object myConstraintViolationInterceptor(InvocationContext ctx) throws Exception
   {
      try {
          return ctx.proceed();
      }
      catch(PersistenceException e) {
          if (e.getCause() instanceof org.hibernate.exception.ConstraintViolationException) {
              //some action taken
          }
          else {
              throw e;
          }
          return null;
      }
   }

顺便说一句,如果你的ConstraintViolationException实际上是变相的乐观锁异常(即由于其他用户在此期间修改了一些数据而抛出),也许最好报告给用户。