`
lookdd1
  • 浏览: 47297 次
  • 性别: Icon_minigender_1
  • 来自: 日照
文章分类
社区版块
存档分类
最新评论

JBPM+spring 排错经历

阅读更多
10个小时!被一个问题困扰!

   问题描述:

    

     用户执行一个任务的时候,JBPM没有把任务执行的结果持久化的数据库中。即没有任何的update或insert语句产生。而我所看的实例中,(实例没有spring),同样的代码却执行了持久化工作。通过观察流程的输出,已经可以看到成功的执行到了下一个流程节点,但是因为没有持久化,所以流程的信息没有被保存。



  以下是java代码:
引用


  jbpmTemplate.execute(new JbpmCallback(){



public Object doInJbpm(JbpmContext context) throws JbpmException {

TaskInstance instance = context.getTaskInstance(tid);

System.out.println("----------------"+instance.getName());

if("ok".equals(result))

{

instance.end();


}

if("no".equals(result))

{

instance.end("部门审批驳回");

}

return null;

}


});




因为使用了spring-jbpm-module,此处使用了它提供的jbpmTemplate



我开始跟踪源代码,在instance.end初设置断点。


TaskInstance类 执行end方法:核心代码:

        if (transition==null) {

          log.debug("completion of task '"+task.getName()+"' results in taking the default transition");

          token.signal();

        } else {

          log.debug("completion of task '"+task.getName()+"' results in taking transition '"+transition+"'");

          token.signal(transition);

        }




然后进入Token类的signal方法

核心代码: node.leave(executionContext, transition);

进入Node类的leave方法:

核心代码:transition.take(executionContext);

进入Transition类的take方法:将执行环境传入方法中

核心代码:to.enter(executionContext);

再次进入Node类 这已经是下一个节点了。至此,已经完成了从一个节点进入另一个节点的过程调度。

没有发现任何的持久化代码!

究竟持久化代码在什么地方呐?

我突然想到,我使用的是JbpmTemplate类,调用它的doInJbpm方法,是一个回调方法,我于是又找到doInJbpm方法的源码:

public Object execute(final JbpmCallback callback) {

final JbpmContext context = getContext();

 

try {

// use the hibernateTemplate is present and if needed

if (hibernateTemplate != null && hasPersistenceService) {

 

// use hibernate template

return hibernateTemplate.execute(new HibernateCallback() {

/**

* @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)

*/

public Object doInHibernate(Session session) throws HibernateException, SQLException {

// inject the session in the context

context.setSession(session);

return callback.doInJbpm(context);

}

});

}

 

// plain callback invocation (no template w/ persistence)

return callback.doInJbpm(context);

 

}

catch (JbpmException ex) {

throw convertJbpmException(ex);

}

finally {

releaseContext(context);

}

 

}


可以看到,它在执行完你实现的doInJbpm方法后在finally体中有个releaseContext方法,

从名字可以看出,该方法是释放jbpm上下文信息的。

看它的源码:

只有一句:jbpmContext.close();

再往里找:核心代码:

      if (services!=null) {

        try {

          autoSave();

        } finally {

          services.close();

        }

      }




我看到了autoSave()方法。

我就开始找autoSave的源码:


    if (autoSaveProcessInstances!=null) {

      Iterator iter = autoSaveProcessInstances.iterator();

      while (iter.hasNext()) {

        ProcessInstance processInstance = (ProcessInstance) iter.next();

        save(processInstance);

        iter.remove();

      }

    }




我又执行了一次业务,发现执行到这儿的时候autoSaveProcessInstances是null,结果就没有执行下面的代码,整个执行也就结束了。

但是我在跟踪例子的时候发现它这儿的autoSaveProcessInstances也是null。

那是哪句呐?

又看了jbpmContext.close();源码:发现又有个finally块:

services.close();

继续找它的源码:

里面最核心的代码也只有一句: service.close();

service是个什么东东呐?是个接口,看它的实现:

通过断点跟踪,这儿的实现是:DbPersistenceService 这个也是我们在jbpm.cfg.xml中配置的。

看它对service.close的实现:



核心持久化代码:

Exception commitException = commit();  这是在跟踪示例的时候发现是这一句完成的持久化工作。

从感觉上,似乎是异常后完成的事务提交...

而执行这一句的必要条件是:

if (! isRollbackOnly()) {....}

而我在跟踪我的代码的时候,发现这儿的if(...)内是false。。。这个isRollbackOnly是哪儿设置的呐?什么时候设置的 呐?我突然想起我对我的那个purchaseApplyService配置了spring的事务,于是我就去掉了事务配置。执行,结果还是一样。

我再次找了这个isRollbackOnly方法   。核心代码:return txService.isRollbackOnly();

这应该是个事务配置。但是在哪儿设置的rollbackOnly呐?我找到了TxService类。然后找到它的setRollbackOnly方法,使用eclipse找调用它的地方,发现:在JbpmContext类中有方法:

 /**

   * mark this transaction for rollback only in the persistence service.

   * The {@link #close()} operation will then perform a rollback.

   */

  public void setRollbackOnly() {

    TxService txService = (services!=null ? services.getTxService() : null);

    if (txService!=null) {

      txService.setRollbackOnly();

    } else {

      throw new JbpmException("no transaction service configured");

    }

  }



于是我想,是不是我在使用springTemplate的方法时候,它给我提供的jbpmContext有问题呐?但是究竟是杂回事,我还是没有找到答案,但是找到个临时的解决办法,就是不使用jbpmContext,并且把JbpmConfiguration注入到我的PurchaseApplyFlowService类里。现在我的代码是:

JbpmContext jbpmContext=jbpmConfiguration.getCurrentJbpmContext();

if(jbpmContext==null)

{

jbpmContext=jbpmConfiguration.createJbpmContext();

}


TaskInstance ti=jbpmContext.getTaskInstance(Long.parseLong(taskId));

if("ok".equals(result))

{

ti.end();

}

if("no".equals(result))

{

ti.end("部门经理驳回");

}

jbpmContext.close();



执行,发现成功执行了持久化工作。。。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics