2011-08-19 9 views
0

私はこれらが類似していると思う問題がありますが、私のシナリオは少し異なります。statefulSession.disposeをコールした後でタスクを完了できない

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) 

これは問題なく動作します。プロセスが作成され、最初のヒューマン・タスクが期待通りに存在します。

私の次のステップは、タスククライアントを介してタスククライアントを使用して、タスクを割り当てて完了することです。代入は完全に機能しますが、タスクを完了すると次の例外が発生します。

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メソッドが呼び出されたときにNULLになります。

私は、タスクが

// statefulSession.dispose(); 

ない良い解決策をコメントアウトすることにより、正常に完了していすることができました。セッションを永遠に開いておくことはできません。

問題を解決するには、タスクを完了するときに、すでに処分されているプロセスを作成するために使用されたJpaPersistenceContextManagerを使用しようとします。

私の質問は、JpaPersistenceContextManagerがアクティブなエンティティマネージャを持っていることを確認するために、どのように再組み込みを行うのですか? Mina Task Clientを介して電話をかけているので、JpaPersistenceContextManagerに直接アクセスできないことを覚えておいてください。

+0

問題の原因は、(私が見ているように)あなたがプロセスのために同じksessionを使用していることと、TaskHandlerです。セッションを破棄すると、_nothing_はもうセッションを使用できなくなります。 Taskhandlerが使用する別のセッションを作成することは可能でしょうか? (そうでない場合は、プロセスをデプロイし、disposeを呼び出さない場合は、beginCommandScopedEntityManagerとendCommandScopedEntityManagerの使用を検討することもできます)。 – Marco

答えて

0

OK。私はそれを修正しました。 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があることを確認し、必要に応じて作成します。

私は、この1つは私の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); 

私は、これは他の人に役立ちます願っています。

関連する問題