我有一个问题,我认为与这些问题类似,但我的情况略有不同。
如何使流程实例继续使用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。
答案 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);
我希望这有助于其他人。