调用statefulSession.dispose后,完成任务失败

时间:2011-08-19 10:58:42

标签: jbpm

我有一个问题,我认为与这些问题类似,但我的情况略有不同。

如何使流程实例继续使用jBPM5?
http://community.jboss.org/message/600654

人工任务API,如何在工作流程中前进? http://community.jboss.org/message/614986#614986

这是我的问题。我使用以下方法创建了一个流程:

Environment env = KnowledgeBaseFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory);
InitialContext ctx = new InitialContext();
UserTransaction transactionManager = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
env.set(EnvironmentName.TRANSACTION_MANAGER, transactionManager);

StatefulKnowledgeSession knowledgeSession = JPAKnowledgeService.newStatefulKnowledgeSession(knowledgeBase, null, env);
WorkItemHandler handler = new CommandBasedWSHumanTaskHandler(knowledgeSession);
knowledgeSession.getWorkItemManager().registerWorkItemHandler("Human Task", handler);

statefulSession.startProcess(processDefinitionId, processVariables);

statefulSession.dispose(); (Remember this line)

这很好用。创建该过程,并按预期存在第一个人工任务。

我的下一步是使用Mina Task Client,通过任务客户端分配和完成任务。分配工作完美,但在完成任务时我得到以下异常。

SEVERE: Could not commit session
java.lang.NullPointerException
    at org.drools.persistence.jpa.JpaPersistenceContextManager.beginCommandScopedEntityManager(JpaPersistenceContextManager.java:67)
    at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:287)
    at org.drools.command.impl.CommandBasedStatefulKnowledgeSession$1.completeWorkItem(CommandBasedStatefulKnowledgeSession.java:149)
    at org.jbpm.process.workitem.wsht.CommandBasedWSHumanTaskHandler$GetResultContentResponseHandler.execute(CommandBasedWSHumanTaskHandler.java:295)
    at org.jbpm.task.service.TaskClientHandler.messageReceived(TaskClientHandler.java:153)
    at org.jbpm.task.service.mina.MinaTaskClientHandler.messageReceived(MinaTaskClientHandler.java:47)
    at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:713)

这导致任务完成,但未创建下一个任务。

抛出此异常是因为org.drools.persistence.jpa.JpaPersistenceContextManager.appScopedEntityManager为null。创建JpaPersistenceContextManager时会初始化此字段,并在调用dispose方法时将其置为空。

我能够通过评论

正确完成任务
// statefulSession.dispose();

不是一个好的解决方案。我不能永远保持会议开放。

问题的关键在于,在完成任务时,它会尝试使用用于创建进程的JpaPersistenceContextManager,该进程已经被处理掉。

我的问题是,如何重新初始化JpaPersistenceContextManager以确保它具有活动的entityManager?请记住我正在通过Mina Task Client进行调用,因此无法直接访问JpaPersistenceContextManager。

1 个答案:

答案 0 :(得分:0)

行。我修好了。我必须编写自己的PersistenceContextManager版本。

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;


import org.drools.persistence.PersistenceContext;
import org.drools.persistence.jpa.JpaPersistenceContext;
import org.drools.runtime.Environment;
import org.drools.runtime.EnvironmentName;
import org.jbpm.persistence.JpaProcessPersistenceContext;
import org.jbpm.persistence.ProcessPersistenceContext;
import org.jbpm.persistence.ProcessPersistenceContextManager;


public class MultipleUseJpaPersistenceContextManager implements ProcessPersistenceContextManager {


Environment env;
private EntityManagerFactory emf;


private EntityManager appScopedEntityManager;
protected EntityManager cmdScopedEntityManager;


private boolean internalAppScopedEntityManager;
private boolean internalCmdScopedEntityManager;


public MultipleUseJpaPersistenceContextManager(Environment env) {
    this.env = env;
    this.emf = (EntityManagerFactory) env.get(EnvironmentName.ENTITY_MANAGER_FACTORY);
}


public PersistenceContext getApplicationScopedPersistenceContext() {
    checkAppScopedEntityManager();
    return new JpaPersistenceContext(appScopedEntityManager);
}


private void checkAppScopedEntityManager() {
    if (this.appScopedEntityManager == null) {
        // Use the App scoped EntityManager if the user has provided it, and it is open.
        this.appScopedEntityManager = (EntityManager) this.env.get(EnvironmentName.APP_SCOPED_ENTITY_MANAGER);
        if (this.appScopedEntityManager != null && !this.appScopedEntityManager.isOpen()) {
            throw new RuntimeException("Provided APP_SCOPED_ENTITY_MANAGER is not open");
        }


        if (this.appScopedEntityManager == null) {
            internalAppScopedEntityManager = true;
            this.appScopedEntityManager = this.emf.createEntityManager();


            this.env.set(EnvironmentName.APP_SCOPED_ENTITY_MANAGER, this.appScopedEntityManager);
        } else {
            internalAppScopedEntityManager = false;
        }
    }
}


public PersistenceContext getCommandScopedPersistenceContext() {
    return new JpaPersistenceContext(this.cmdScopedEntityManager);
}


public void beginCommandScopedEntityManager() {
    checkAppScopedEntityManager();
    EntityManager cmdScopedEntityManager = (EntityManager) env.get(EnvironmentName.CMD_SCOPED_ENTITY_MANAGER);
    if (cmdScopedEntityManager == null
            || (this.cmdScopedEntityManager != null && !this.cmdScopedEntityManager.isOpen())) {
        internalCmdScopedEntityManager = true;
        this.cmdScopedEntityManager = this.emf.createEntityManager(); // no need to call joinTransaction as it will
                                                                      // do so if one already exists
        this.env.set(EnvironmentName.CMD_SCOPED_ENTITY_MANAGER, this.cmdScopedEntityManager);
        cmdScopedEntityManager = this.cmdScopedEntityManager;
    } else {
        internalCmdScopedEntityManager = false;
    }
    cmdScopedEntityManager.joinTransaction();
    appScopedEntityManager.joinTransaction();
}


public void endCommandScopedEntityManager() {
    if (this.internalCmdScopedEntityManager) {
        this.env.set(EnvironmentName.CMD_SCOPED_ENTITY_MANAGER, null);
    }
}


public void dispose() {
    if (this.internalAppScopedEntityManager) {
        if (this.appScopedEntityManager != null && this.appScopedEntityManager.isOpen()) {
            this.appScopedEntityManager.close();
        }
        this.internalAppScopedEntityManager = false;
        this.env.set(EnvironmentName.APP_SCOPED_ENTITY_MANAGER, null);
        this.appScopedEntityManager = null;
    }


    if (this.internalCmdScopedEntityManager) {
        if (this.cmdScopedEntityManager != null && this.cmdScopedEntityManager.isOpen()) {
            this.cmdScopedEntityManager.close();
        }
        this.internalCmdScopedEntityManager = false;
        this.env.set(EnvironmentName.CMD_SCOPED_ENTITY_MANAGER, null);
        this.cmdScopedEntityManager = null;
    }
}

@Override
public ProcessPersistenceContext getProcessPersistenceContext() {
    if (cmdScopedEntityManager == null) {
        this.emf.createEntityManager();;
    }
    return new JpaProcessPersistenceContext(cmdScopedEntityManager);
}


}

此版本检查它是否具有有效的appScopedEntityManager并在必要时创建一个。

然后我确保在创建我的knowledgeSession时使用这个而不是JBPM提供的默认值:

        Environment env = KnowledgeBaseFactory.newEnvironment();
        env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory);
        InitialContext ctx = new InitialContext();
        UserTransaction transactionManager = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
       env.set(EnvironmentName.TRANSACTION_MANAGER,
                new JtaTransactionManager(transactionManager, null, transactionManager));
        env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER,
                new MultipleUseJpaPersistenceContextManager(env));

        StatefulKnowledgeSession knowledgeSession = JPAKnowledgeService.newStatefulKnowledgeSession(knowledgeBase, null, env);

我希望这有助于其他人。