工作流jbpm3.1.2 bug 导致数据库连接池满的问题

现象是:

 [org.hibernate.event.def.AbstractFlushingEventListener] [ERROR] - Could not synchronize database state with session

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#35000000000033432]
at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:180)

org.jbpm.persistence.JbpmPersistenceException: couldn't flush hibernate session at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:182)

-----------------------------------------------------------

找3.1.2工作流的源码,找到报错的类DbPersistenceService.close方法,如下:

  代码:

public void close() {
    if ( (session!=null)
         && (transaction==null)
         && (isRollbackOnly)
       ) {
      throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");
    }
    if (messagingSession!=null) {
      messagingSession.closeOpenIterators();
    }
    if (schedulerSession!=null) {
      schedulerSession.closeOpenIterators();
    }
    if ( (isTransactionEnabled)
         && (transaction!=null)
       ) {
      if (isRollbackOnly) {
        try {
          log.debug("rolling back hibernate transaction");
          mustSessionBeFlushed = false; // flushing updates that will be rolled back is not very clever :-)
          transaction.rollback();
        } catch (Exception e) {
          throw new JbpmPersistenceException("couldn't rollback hibernate session", e);
        }
      } else {
        try {
          log.debug("committing hibernate transaction");
          mustSessionBeFlushed = false; // commit does a flush anyway
          transaction.commit();
        } catch (Exception e) {
          try {
            // if the commit fails, we must do a rollback
            transaction.rollback();
          } catch (Exception e2) {
            // if the rollback fails, we did what we could and you're in
            // deep shit :-(
            log.error("problem rolling back after failed commit", e2);
          }
          throw new JbpmPersistenceException("couldn't commit hibernate session", e);
        }
      }
    }
   
    if (mustSessionBeFlushed) {
      try {
        log.debug("flushing hibernate session");
        session.flush();
      } catch (Exception e) {
        throw new JbpmPersistenceException("couldn't flush hibernate session", e);
      }
    }   
    if (mustSessionBeClosed) {
      try {
        log.debug("closing hibernate session");
        session.close();
      } catch (Exception e) {
        throw new JbpmPersistenceException("couldn't close hibernate session", e);
      }
    }

    if (mustConnectionBeClosed) {
      try {
        log.debug("closing jdbc connection");
        connection.close();
      } catch (Exception e) {
        throw new JbpmPersistenceException("couldn't close jdbc connection", e);
      }
    }
  }


来源:blogjava.net    作者:岁月如歌


一看真是吓一跳,程序在执行到session.flush();时候报错的话,如果mustSessionBeClosed为true根本不能执行到后面的session.close(),会导致数据库连接不释放的问题……基本确定问题所在了,就在本地试着复现一下问题(因为前面所描述的异常在开发环境无法复现,所以只能强制在flush后抛异常),果然不出意料。

因为这个是jbpm3.1.2版本,觉得应该是jbpm的bug吧,就又下载了一份jbpm3.3.0GA源码,找到DbPersistenceService.close()方法:

  代码:

public void close() {

    if ( (session!=null)
         && !isTransactionActive()
         && (isRollbackOnly())
       ) {
      throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");
    }
   
    if ( (isTransactionEnabled)
         && (transaction!=null)
       ) {

      if (! isRollbackOnly()) {
        Exception commitException = commit();
        if (commitException!=null) {
          rollback();
          closeSession();
          closeConnection();
          throw new JbpmPersistenceException("hibernate commit failed", commitException);
        }

      } else { // isRollbackOnly==true
        Exception rollbackException = rollback();
        if (rollbackException!=null) {
          closeSession();
          closeConnection();
          throw new JbpmPersistenceException("hibernate rollback failed", rollbackException);
        }
      }
    }
   
    Exception flushException = flushSession();
    if (flushException!=null) {
      // JBPM-1465 transaction has been either committed or rolled back at this point
      // on the other hand, it is possible that no transaction is underway
      // hence rolling back here is redundant and possibly dangerous
      closeSession();
      closeConnection();
      throw new JbpmPersistenceException("hibernate flush failed", flushException);
    }
    Exception closeSessionException = closeSession();
    if (closeSessionException!=null) {
      closeConnection();
      throw new JbpmPersistenceException("hibernate close session failed", closeSessionException);
    }
    Exception closeConnectionException = closeConnection();
    if (closeConnectionException!=null) {
      throw new JbpmPersistenceException("hibernate close connection failed", closeConnectionException);
    }
  }

  果然在3.3.0版本中,当flush、close等操作出现异常时候,都会调用closeSession()和closeConnection()以保证连接正常释放。照猫画虎在该方法写了关闭session和connection的方法,准备月底发布新版本试试。

  结论:

  三期工作流jbpm3.1.2存在连接不释放的bug,当然前提是程序执行数据库操作报错的情况下(如session.flush)。虽然解决了连接不释放的问题,但是这个关于这个报错的深层原因还没搞清楚。另外和相关人员确认,工作流的这些异常可以cacth掉,到目前为止除了引起连接不释放之外,没有发现其他问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值