0

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

如何使流程实例继续使用 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 任务客户端,通过任务客户端分配和完成任务。分配工作完美,但是在完成任务时出现以下异常。

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 为空。该字段在创建 JpaPersistenceContextManager 时初始化,并在调用 dispose 方法时为空。

通过注释掉,我能够正确完成任务

// statefulSession.dispose();

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

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

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

4

1 回答 1

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 并在必要时创建一个。

然后我确保在创建我的知识会话时使用这个而不是 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);

我希望这对其他人有帮助。

于 2011-09-05T11:09:29.533 回答