2011-08-19 6 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) 

이 작동합니다. 프로세스가 작성되고 첫 번째 휴먼 타스크가 예상대로 존재합니다.

내 다음 단계는 태스크 클라이언트를 통해 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가 null이기 때문에 발생합니다. 이 필드는 JpaPersistenceContextManager가 작성 될 때 초기화되고 dispose 메소드가 호출 될 때 무효화됩니다.

나는
// statefulSession.dispose(); 

안 좋은 해결책

을 주석으로 제대로 완료 작업을 할 수 있었다. 세션을 영원히 열어 둘 수는 없습니다.

문제의 핵심은 작업을 완료 할 때 이미 삭제 된 프로세스를 만드는 데 사용 된 JpaPersistenceContextManager를 사용하려고한다는 것입니다.

제 질문은, 어떻게 활성화 된 entityManager가 있는지 확인하기 위해 JpaPersistenceContextManager를 다시 인티그레이션해야합니까? Mina Task Client를 통해 전화하고 있으므로 JpaPersistenceContextManager에 직접 액세스 할 수 없다는 것을 기억하십시오.

+0

문제의 근원은 TaskHandler와 같은 프로세스에 대해 동일한 ksession을 사용하고 있다는 것입니다. 세션을 폐기하면 _nothing_이 더 이상 세션을 사용할 수 없습니다. Taskhandler가 사용할 다른 세션을 생성 할 수 있습니까? 그렇지 않으면 프로세스를 전개하고 dispose를 호출하지 않을 때 beginCommandScopedEntityManager 및 endCommandScopedEntityManager를 사용할 수도 있습니다. – Marco

답변

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); 

나는이 다른 사람에게 도움이되기를 바랍니다.