8 Replies Latest reply on May 27, 2013 10:52 AM by swiderski.maciej

    Problem with multiple sessions

    garethed

      Hi,

       

      I am creating one knowledge session per process.

      Each knowledge session has one workItem handler, one humanTask handler and two processEventListener listeners.

       

      The behavior I am seeing is that If I only have one process (in one session) then that can be completed fine and another process (and session) can be started etc.

      If I have more than one session and complete one of the processes then the afterProcessCompleted event is called fine, at that point the other processes cannot be completed or at least the events do not fire.

      I can see that I have a different sessionId for each session and no exceptions are being thrown.  It’s as if disposing of a session is effecting  the other sessions.

       

      How are knowledge sessions normally managed?

       

      I am creating knowledge sessions within an object and storing the object in an arraylist.

       

      Help will be most appreciated.

       

      JBPM5.4

      JBoss 7.1

       

      Cheers,

       

      Gareth.

        • 1. Re: Problem with multiple sessions
          swiderski.maciej

          could you provide code snippet that you use to manage sessions, especially:

          - how you create sessions and register all required stuff on them

          - how you dispose session

          - what is done as part of listeners

           

          do you get any errors on second process completion?

           

          Cheers

          • 2. Re: Problem with multiple sessions
            garethed

            Hello again Maciej,

             

            I have a method to start a new session:

             

             

            {code}

            public synchronized int startNewSession(WorkflowSettings wfs) throws APIException{

             

                                purgeDeadSessions();

             

                                KnowledgeBase kbase = packageService.getKnowledgeBase(wfs.getPackageName(), wfs.getPackageVersion());

             

                                StatefulKnowledgeSession ksession = null;

             

             

                                          ksession = getSession(kbase);

                                log.debug("Starting new session:" + ksession.getId());

                                wfs.setSessionId(ksession.getId());

                                WorkflowSessionTask wst = new WorkflowSessionTask(workflowSessionService, ksession, wfs);

                               // Make a copy of the user to enable updates of workflowSession table

                                final User u = new SessionUser(wfs.getUser().getId());

                                wst.startWorkFlow(true, u);

             

                                 this.workFlowSessionTasks.add(wst);

             

                                log.info("WorkflowSettings:" + wfs.toString());

                                return wst.getSessionId();

                      }

            {code}

             

             

             

            The WorkflowSessionTask is an inner class that I'm using to contain the session.

            I add the instance of this to an ArrayList.  When adding a new session I purge this list of any that are marked as completed.

             

             

            {code}

            public void startWorkFlow(boolean startProcess, final User user) {

             

             

                                // pwss is a spring service that performs CRUD on a database table using hibernate

                                this.completed = false;

                                JPAWorkingMemoryDbLogger logger = new JPAWorkingMemoryDbLogger(ksession);

                                String connectorName = "Hornet" + UUID.randomUUID().toString();

                                AsyncHornetQHTWorkItemHandler humanTaskHandler = new AsyncHornetQHTWorkItemHandler(new AsyncHornetQTaskClient(connectorName), ksession, OnErrorAction.LOG);

                                humanTaskHandler.setIpAddress(ipAddress);

                                humanTaskHandler.setOwningSessionOnly(true);

                                // The CMTDisposeCommand disposes the session synchronised with the transaction

                                final CMTDisposeCommand dc = new CMTDisposeCommand();

                                dc.setHumanTaskHandler(humanTaskHandler);

                                ksession.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

             

                                WorkflowCurrentTaskHandler currentTaskHandler = new WorkflowCurrentTaskHandler();

                                currentTaskHandler.setUser(user);

                                currentTaskHandler.setWorkflowSessionService(pwss);

                                currentTaskHandler.setSessionId(ksession.getId());

                                dc.setCurrentTaskHandler(currentTaskHandler);

                                ksession.getWorkItemManager().registerWorkItemHandler("UpdateWorkflowCurrentTask",currentTaskHandler);

             

                                // The workflow event listener uses the afterNodeTriggered event to update a database table

                                WorkflowEventListener wel = new WorkflowEventListener();

                                wel.setPatientWorkflowSessionService(pwss);

                                wel.setSessionId(ksession.getId());

                                wel.setUser(user);

                                dc.setWorkflowEventListener(wel);

                                ksession.addEventListener(wel);

             

             

             

                                ksession.addEventListener(new DefaultProcessEventListener(){

                                          @Override

                                          public void afterProcessCompleted(ProcessCompletedEvent event){

                                                    log.info("~~~~~~~~~Workflow Session:" + ksession.getId() + " Completed~~~~~~~~~");

                                                    WorkflowSession pws = null;

             

                                                    try {

                                                              pws = pwss.get(ksession.getId());

                                                              pws.setActive(false);

                                                              pwss.update(pws, user);

                                                    } catch (APIException e1) {

                                                              // TODO Auto-generated catch block

                                                              e1.printStackTrace();

                                                    }

                                                    completed = true;

                                                    workflowSettings.setCompleted(true);

                                                    if (pws.getTId() != null){

                                                              String[] nextWorkflow = pwss.getNextWorkflow(pws.getTId(), pws.getWorkflowRef());

                                                              if (nextWorkflow != null){

                                                                        WorkflowSettings settings = new WorkflowSettings();

                                                                        settings.setActive(true);

                                                                        settings.setCompleted(false);

                                                                        settings.setPackageName(nextWorkflow[0]);

                                                                        settings.setPackageVersion("LATEST");

                                                                        settings.setWorkflowName(nextWorkflow[0] + "." + nextWorkflow[1]);

                                                                        settings.setPId(pws.getPId());

                                                                        settings.setTId(pws.getTId());

                                                                        settings.setUser(user);

                                                                        HashMap<String, Object> params = new HashMap<String, Object>();

                                                                        params.put("username",user.getUsername());

                                                                        params.put("pId", pws.getPId());

                                                                        params.put("tId", pws.getTId().intValue());

                                                                        params.put("packageName", settings.getPackageName());

                                                                        params.put("packageVersion", settings.getPackageVersion());

                                                                        settings.setWorkFlowData(params);

                                                                        queueWorkflow(settings);

                                                              }

             

             

                                                    }

                                                    log.info("Disposing of " + event.getProcessInstance().getProcessName() + "!");

                                                    ksession.execute(dc);

                                          }

                                });

             

                                if (startProcess)

                                          ksession.startProcess(workflowSettings.getWorkflowName(),workflowSettings.getWorkFlowData());

                      }

            {code}

             

             

            No errors after second completion.  I think It's just completing the task but the session isn't there?

            Hopefully this helps.

            • 3. Re: Problem with multiple sessions
              garethed

              I have tidied up the code and removed any thing that I think might be causing the issue.

              The WorkflowCurrentTaskHandler is now not really doing anything as an experiment.

              also the WorkflowEventListener is just logging the node name.

               

              I'm still getting the same behavior.

               


              {code}

                          public void startWorkFlow(boolean startProcess, final User user) {

                               this.completed = false;

                                   JPAWorkingMemoryDbLogger logger = new JPAWorkingMemoryDbLogger(ksession);

                                String connectorName = "Hornet" + UUID.randomUUID().toString();

               

                                final AsyncHornetQHTWorkItemHandler humanTaskHandler = new AsyncHornetQHTWorkItemHandler(new AsyncHornetQTaskClient(connectorName), ksession, OnErrorAction.LOG);

                                humanTaskHandler.setIpAddress(ipAddress);

                                humanTaskHandler.setOwningSessionOnly(true);

                                            final CMTDisposeCommand dc = new CMTDisposeCommand();

                                            dc.setWorkitemhandler(humanTaskHandler);

               

                                            ksession.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

                                            ksession.getWorkItemManager().registerWorkItemHandler("UpdateWorkflowCurrentTask", new WorkflowCurrentTaskHandler(null, ksession.getId(), null));

                                            ksession.addEventListener(new WorkflowEventListener(null, ksession.getId(), null));

                                            ksession.addEventListener(new DefaultProcessEventListener(){

                                              @Override

                                                      public void afterProcessCompleted(ProcessCompletedEvent event){

                                                   log.info("~~~~~~~~~Workflow Session:" + ksession.getId() + " Completed~~~~~~~~~");

                                                                log.info("Disposing of " + event.getProcessInstance().getProcessName() + "!");

                                                                ksession.execute(dc);

                                                                completed = true;

                                                                workflowSettings.setCompleted(true);

                                                      }

                                            });

               

                                            if (startProcess)

                                                      ksession.startProcess(workflowSettings.getWorkflowName(),workflowSettings.getWorkFlowData());

                                  }

              {code}

               


              • 4. Re: Problem with multiple sessions
                swiderski.maciej

                Gareth, I think it would be best to get complete class(es) that are responsible for managing sessions as I can't get full picture of what you have there.

                 

                Looking at the code of startWorkflow first of all I don't see when do you create or load session. Another thing is that you use CMTDisposeCommand and you execute it on ksession - where does the ksession come from, could it be that it refers to another session? Might be better to execute it on ksession that you can get from ProcessCompletedEvent as KnowledgeRuntime.

                 

                HTH

                • 5. Re: Problem with multiple sessions
                  garethed

                  Cheers,

                   

                  Here are the main classes.  I have removed some irrelevant methods and renamed certain variables.

                  I changed to this:

                  StatefulKnowledgeSession s = (StatefulKnowledgeSession) event.getKnowledgeRuntime();

                  s.execute(dc);

                   

                  but still see the same behaviour.

                   


                  {code}

                  package com.x.api.service.impl;

                   

                   

                  import java.util.ArrayList;

                  import java.util.HashMap;

                  import java.util.Iterator;

                  import java.util.LinkedList;

                  import java.util.List;

                  import java.util.Queue;

                  import java.util.UUID;

                   

                   

                  import javax.persistence.EntityManagerFactory;

                   

                   

                  import org.apache.log4j.Logger;

                  import org.drools.KnowledgeBase;

                  import org.drools.KnowledgeBaseFactory;

                  import org.drools.event.process.DefaultProcessEventListener;

                  import org.drools.event.process.ProcessCompletedEvent;

                  import org.drools.persistence.jpa.JPAKnowledgeService;

                  import org.drools.runtime.Environment;

                  import org.drools.runtime.EnvironmentName;

                  import org.drools.runtime.StatefulKnowledgeSession;

                  import org.jbpm.process.audit.JPAWorkingMemoryDbLogger;

                  import org.jbpm.process.workitem.wsht.AsyncHornetQHTWorkItemHandler;

                  import org.jbpm.task.service.hornetq.AsyncHornetQTaskClient;

                  import org.jbpm.task.utils.OnErrorAction;

                  import org.springframework.beans.factory.InitializingBean;

                  import org.springframework.beans.factory.annotation.Autowired;

                  import org.springframework.beans.factory.annotation.Value;

                  import org.springframework.scheduling.annotation.Scheduled;

                  import org.springframework.stereotype.Service;

                   

                   

                  import com.x.api.jbpm.handler.BiometricVerificationHandler;

                  import com.x.api.jbpm.handler.WorkflowCurrentTaskHandler;

                  import com.x.api.jbpm.listener.WorkflowEventListener;

                  import com.x.api.model.WorkflowSession;

                  import com.x.api.model.WorkflowSettings;

                  import com.x.api.model.user.SessionUser;

                  import com.x.api.model.user.User;

                  import com.x.api.service.PackageService;

                  import com.x.api.service.WorkflowSessionService;

                  import com.x.api.service.WorkflowSessionService;

                  import com.x.api.util.CMTDisposeCommand;

                  import com.x.api.util.xAPIException;

                   

                   

                  public class WorkflowSessionServiceImpl implements InitializingBean, WorkflowSessionService {

                   

                   

                            private static Logger log = Logger.getLogger(WorkflowSessionServiceImpl.class);

                   

                            @Autowired

                            private PackageService packageService;

                   

                            @Autowired

                            private WorkflowSessionService WorkflowSessionService;

                   

                            private StatefulKnowledgeSession ksession = null;

                   

                            private ArrayList<WorkflowSessionTask> workFlowSessionTasks;

                   

                            private Queue<WorkflowSettings> workflowQueue = new LinkedList<WorkflowSettings>();

                   

                            @Value("${HumanTaskServiceIp}")

                            private String ipAddress;

                   

                            @Override

                            public void afterPropertiesSet() throws Exception {

                                      workFlowSessionTasks = new ArrayList<WorkflowSessionServiceImpl.WorkflowSessionTask>();

                            }

                   

                            @Override

                            public List<WorkflowSession> resumeWorkflowSessions(User user)throws xAPIException{

                                      List<WorkflowSession> workflowSessions = WorkflowSessionService.getActiveSessions();

                                      List<WorkflowSession> resumedSessions = new ArrayList<WorkflowSession>();

                   

                                      for (WorkflowSession WorkflowSession : workflowSessions) {

                                                if (!isSessionLoaded(WorkflowSession.getId())){

                                                          if (this.resumeWorkflowSession(WorkflowSession, user))

                                                                    resumedSessions.add(WorkflowSession);

                                                }

                                      }

                                      return resumedSessions;

                            }

                   

                            private boolean resumeWorkflowSession(WorkflowSession pws, User user)throws xAPIException{

                                      boolean success = false;

                                      EntityManagerFactory emf = packageService.getEntityManagerFactory();

                                      Environment env = KnowledgeBaseFactory.newEnvironment();

                                      KnowledgeBase kbase;

                                      try {

                                                kbase = packageService.getKnowledgeBase(pws.getPackageRef(), pws.getPackageVersion());

                                          env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);

                                          StatefulKnowledgeSession sks = JPAKnowledgeService.loadStatefulKnowledgeSession(pws.getId(), kbase, null, env);

                                          WorkflowSettings wfs = new WorkflowSettings();

                                          wfs.setActive(true);

                                          wfs.setCompleted(false);

                                          wfs.setId(sks.getId());

                                          wfs.setPackageName(pws.getPackageRef());

                                          wfs.setPackageVersion(pws.getPackageVersion());

                                          WorkflowSessionTask wst = new WorkflowSessionTask(WorkflowSessionService, sks, wfs);

                                          // Make a copy of the user to enable updates of workflowSession table

                                          final User u = new SessionUser(user.getId());

                                          wst.startWorkFlow(false, u);

                                          workFlowSessionTasks.add(wst);

                                          success = true;

                                      } catch (Exception e) {

                                                success = false;

                                                //throw new xAPIException("Error getting knowledge base:" + e.getLocalizedMessage());

                                      }

                                      return success;

                            }

                   

                            private boolean isSessionLoaded(int sessionId){

                   

                                      for (WorkflowSessionTask workflowSessionTask : workFlowSessionTasks) {

                                                if (workflowSessionTask.ksession.getId() == sessionId && !workflowSessionTask.completed){

                                                          return true;

                                                }

                                      }

                                      return false;

                            }

                   

                            @Override

                            public synchronized int startNewSession(WorkflowSettings wfs) throws xAPIException{

                                      purgeDeadSessions();

                   

                                      KnowledgeBase kbase = packageService.getKnowledgeBase(wfs.getPackageName(), wfs.getPackageVersion());

                   

                                      //StatefulKnowledgeSession ksession = getSession(kbase);

                                      //if (ksession == null)

                                                ksession = getSession(kbase);

                                      log.debug("Starting new session:" + ksession.getId());

                                      wfs.setSessionId(ksession.getId());

                                      WorkflowSessionTask wst = new WorkflowSessionTask(WorkflowSessionService, ksession, wfs);

                                      // Make a copy of the user to enable updates of workflowSession table

                                final User u = new SessionUser(wfs.getUser().getId());

                                      wst.startWorkFlow(true, u);

                   

                                      this.workFlowSessionTasks.add(wst);

                   

                                      log.info("WorkflowSettings:" + wfs.toString());

                                      return ksession.getId();

                            }

                   

                               private StatefulKnowledgeSession getSession(KnowledgeBase kb){

                                         Environment env = KnowledgeBaseFactory.newEnvironment();

                                   env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, packageService.getEntityManagerFactory());

                                         StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession(kb, null, env);

                                         return ksession;

                               }

                              

                               protected class WorkflowSessionTask{

                                        

                                         private StatefulKnowledgeSession ksession;

                                         private WorkflowSettings workflowSettings;

                                         private boolean completed;

                                         private WorkflowSessionService pws;

                                        

                                         public WorkflowSessionTask(WorkflowSessionService pws, StatefulKnowledgeSession session, WorkflowSettings wfs){

                                                   this.ksession = session;

                                                   this.workflowSettings = wfs;

                                                   this.pws = pws;

                                         }

                   

                   

                   

                   

                                      public void startWorkFlow(boolean startProcess, final User user) {

                                                this.completed = false;

                                                JPAWorkingMemoryDbLogger logger = new JPAWorkingMemoryDbLogger(ksession);

                                    String connectorName = "Hornet" + UUID.randomUUID().toString();

                                    final AsyncHornetQHTWorkItemHandler humanTaskHandler = new AsyncHornetQHTWorkItemHandler(new AsyncHornetQTaskClient(connectorName), ksession, OnErrorAction.LOG);

                                    //final HumanTaskHandler humanTaskHandler = new HumanTaskHandler(new AsyncHornetQTaskClient(connectorName), ksession, OnErrorAction.LOG);

                                    humanTaskHandler.setIpAddress(ipAddress);

                                    humanTaskHandler.setOwningSessionOnly(true);

                                                final CMTDisposeCommand dc = new CMTDisposeCommand();

                                                dc.setWorkitemhandler(humanTaskHandler);

                   

                                                ksession.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

                                                ksession.getWorkItemManager().registerWorkItemHandler("UpdateWorkflowCurrentTask", new WorkflowCurrentTaskHandler(null, ksession.getId(), null));

                                                ksession.addEventListener(new WorkflowEventListener(null, ksession.getId(), null));

                                                ksession.addEventListener(new DefaultProcessEventListener(){

                                                          @Override

                                                          public void afterProcessCompleted(ProcessCompletedEvent event){

                                                                    log.info("~~~~~~~~~Workflow Session:" + ksession.getId() + " Completed~~~~~~~~~");

                                                                    log.info("Disposing of " + event.getProcessInstance().getProcessName() + "!");

                                                                    StatefulKnowledgeSession s = (StatefulKnowledgeSession) event.getKnowledgeRuntime();

                                                                    s.execute(dc);

                                                                    //ksession.execute(dc);

                                                                    completed = true;

                                                                    workflowSettings.setCompleted(true);

                                                          }

                                                });

                   

                                                if (startProcess)

                                                          ksession.startProcess(workflowSettings.getWorkflowName(),workflowSettings.getWorkFlowData());

                                      }

                   

                                      public boolean getCompleted(){

                                                return this.completed;

                                      }

                   

                                      public WorkflowSettings getWorkFlowSettings(){

                                                return this.workflowSettings;

                   

                                      }

                   

                               }

                              

                               private void purgeDeadSessions(){

                                         for (Iterator<WorkflowSessionTask> iterator = workFlowSessionTasks.iterator(); iterator.hasNext();) {

                                                WorkflowSessionTask task = iterator.next();

                                                if (task.getCompleted())

                                                          iterator.remove();

                                      }

                               }

                              

                   

                   

                            @Override

                            public synchronized ArrayList<WorkflowSettings> getWorkflowSettings(){

                                         ArrayList<WorkflowSettings> sessions = new ArrayList<WorkflowSettings>();

                                         for (WorkflowSessionTask task : workFlowSessionTasks ) {

                                                sessions.add(task.getWorkFlowSettings());

                                      }

                                         return sessions;

                            }

                   

                            private boolean queueWorkflow(WorkflowSettings wfs){

                                      log.info("Queueing workflow: " + wfs.getWorkflowName());

                                      return this.workflowQueue.add(wfs);

                            }

                   

                   

                            public void dequeueAndStartWorkflows(){

                                      log.info("Polling workflowQueue");

                                      WorkflowSettings wfs = null;

                                      do{

                                                wfs = workflowQueue.poll();

                                                if (wfs != null)

                                                          try {

                                                                    this.startNewSession(wfs);

                                                          } catch (xAPIException e) {

                                                                    // TODO Auto-generated catch block

                                                                    e.printStackTrace();

                                                          }

                                      }

                                      while(wfs!=null);

                            }

                  }

                   

                  {code}

                   

                   

                   

                  CMTDisposeCommand

                   

                   

                  {code}

                  package com.x.api.util;

                   

                   

                  import javax.naming.InitialContext;

                  import javax.transaction.Synchronization;

                  import javax.transaction.TransactionManager;

                   

                   

                  import org.apache.log4j.Logger;

                  import org.drools.command.Context;

                  import org.drools.command.impl.GenericCommand;

                  import org.drools.command.impl.KnowledgeCommandContext;

                  import org.drools.runtime.StatefulKnowledgeSession;

                  import org.jbpm.process.workitem.wsht.AsyncGenericHTWorkItemHandler;

                   

                   

                  public class CMTDisposeCommand implements GenericCommand<Void> {

                   

                   

                      private static final long serialVersionUID = 1L;

                      private static Logger log = Logger.getLogger(CMTDisposeCommand.class);

                      private String tmLookupName = "java:jboss/TransactionManager";

                     

                      public CMTDisposeCommand() {   

                      }

                   

                   

                      private AsyncGenericHTWorkItemHandler workitemhandler;

                     

                      public CMTDisposeCommand(String tmLookup) {

                          this.tmLookupName = tmLookup;

                      }

                     

                      public AsyncGenericHTWorkItemHandler getWorkitemhandler() {

                                      return workitemhandler;

                            }

                   

                   

                            public void setWorkitemhandler(AsyncGenericHTWorkItemHandler workitemhandler) {

                                      this.workitemhandler = workitemhandler;

                            }

                   

                   

                            @Override

                      public Void execute(Context context) {

                         

                          final StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();

                          try {

                              TransactionManager tm = (TransactionManager) new InitialContext().lookup(tmLookupName);

                              tm.getTransaction().registerSynchronization(new Synchronization() {

                                 

                                  @Override

                                  public void beforeCompletion() {

                                      // not used here

                                     

                                  }

                                 

                                  @Override

                                  public void afterCompletion(int arg0) {

                                            if (workitemhandler != null)

                                                                              try {

                                                                                        log.info("Disposing workitemHandler for session:" + ksession.getId());

                                                                                        workitemhandler.dispose();

                                                                              } catch (Exception e) {

                                                                                        e.printStackTrace();

                                                                              }

                                      ksession.dispose();              

                                  }

                              });

                          } catch (Exception e) {

                              e.printStackTrace();

                          }         

                          return null;

                            }

                  }

                  {code}

                   

                   

                  PackageService

                   

                   

                  {code}

                  package com.x.api.service.impl;

                   

                   

                  import java.net.URI;

                  import java.sql.Timestamp;

                  import java.util.ArrayList;

                  import java.util.Date;

                  import java.util.HashMap;

                  import java.util.Hashtable;

                  import java.util.List;

                  import java.util.Set;

                   

                   

                  import javax.persistence.EntityManagerFactory;

                  import javax.persistence.Persistence;

                   

                   

                  import org.apache.commons.io.IOUtils;

                  import org.apache.http.HttpResponse;

                  import org.apache.http.HttpStatus;

                  import org.apache.http.client.HttpClient;

                  import org.apache.http.client.methods.HttpGet;

                  import org.apache.http.client.utils.URIBuilder;

                  import org.apache.http.impl.client.DefaultHttpClient;

                  import org.apache.log4j.Logger;

                  import org.drools.KnowledgeBase;

                  import org.drools.KnowledgeBaseFactory;

                  import org.drools.builder.KnowledgeBuilder;

                  import org.drools.builder.KnowledgeBuilderFactory;

                  import org.drools.builder.ResourceType;

                  import org.drools.io.ResourceFactory;

                  import org.drools.io.impl.UrlResource;

                  import org.drools.runtime.Environment;

                  import org.drools.runtime.EnvironmentName;

                  import org.json.JSONArray;

                  import org.json.JSONObject;

                  import org.springframework.beans.factory.InitializingBean;

                  import org.springframework.beans.factory.annotation.Value;

                  import org.springframework.stereotype.Service;

                   

                   

                  import com.x.api.model.JbpmPackage;

                  import com.x.api.model.JbpmWorkflow;

                  import com.x.api.service.PackageService;

                  import com.x.api.util.APIException;

                   

                   

                   

                   

                  @Service("packageService")

                  public class PackageServiceImpl implements InitializingBean, PackageService {

                            private static Logger log = Logger.getLogger(PackageService.class);

                   

                            @Value( "${DroolsGuvnorUrl}" )

                            private String url;

                   

                            private EntityManagerFactory emf = null;

                            private HashMap<String, KnowledgeBase> knowLedgeBases = new HashMap<String, KnowledgeBase>();

                   

                            private List<JbpmPackage> packageCache;

                   

                            // keys by package

                            private Hashtable<String, List<JbpmWorkflow>> workflowCache;

                   

                            @Override

                            public void afterPropertiesSet() throws Exception {

                                      // TODO load required knowledgeBases

                                      this.emf = getEntityManagerFactory();

                                      this.workflowCache = new Hashtable<String,List<JbpmWorkflow>>();

                            }

                   

                            @Override

                            public void clearCaches() {

                                      this.packageCache = null;

                                      this.workflowCache = new Hashtable<String,List<JbpmWorkflow>>();

                            }

                   

                            @Override

                            public List<JbpmPackage> getJbpmPackages() throws APIException {

                                      // caching to speed up the requests

                                      if (packageCache==null) {

                                                List<JbpmPackage> packages = new ArrayList<JbpmPackage>();

                                                String authorizationHeader = "Basic " + org.apache.cxf.common.util.Base64Utility.encode("admin:admin".getBytes());

                                                HttpClient httpclient = new DefaultHttpClient();

                                                try {

                                                          URIBuilder builder = new URIBuilder(url +"/rest/packages");

                   

                                                          URI uri = builder.build();

                                                          HttpGet httpget = new HttpGet(uri);

                                                          httpget.addHeader("Authorization", authorizationHeader);

                                                          httpget.addHeader("Accept", "application/json");

                                                          HttpResponse response = httpclient.execute(httpget);

                                                          if (response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK)

                                                                    throw new PIException("Failed to retrieve list of packages from drools REST service",response.getStatusLine().getStatusCode());

                                                          else {

                                                                    String json = IOUtils.toString(response.getEntity().getContent(),"UTF-8");

                                                                    JSONArray jsonArray = new JSONArray(json);

                                                                    for (int i=0;i<jsonArray.length();i++) {

                                                                              JSONObject jo = (JSONObject)jsonArray.get(i);

                                                                              String title = jo.getString("title");

                                                                              if (title.startsWith("x.")) {

                                                                                        JbpmPackage wp = new JbpmPackage();

                                                                                        wp.setId(title);

                                                                                        wp.setDisplayTitle(title.substring(title.indexOf("x.")+8).replace("_", " "));

                                                                                        wp.setDescription(jo.getString("description"));

                                                                                        wp.setPublishedDate(new Date(jo.getLong("published")));

                                                                                        JSONObject meta = jo.getJSONObject("metadata");

                                                                                        wp.setVersion(meta.getInt("versionNumber"));

                                                                                        wp.setArchived(meta.getBoolean("archived"));

                                                                                        wp.setCreatedDate(new Timestamp(meta.getLong("created")));

                                                                                        log.debug("WorkflowPackage: "+wp.toString());

                                                                                        packages.add(wp);

                                                                              }

                                                                    }

                                                          }

                                                }

                                                catch (Exception ue) {

                                                          throw new APIException(ue);

                                                }

                                                this.packageCache = packages;

                                      }

                                      return this.packageCache;

                            }

                   

                   

                            @Override

                            public KnowledgeBase getKnowledgeBase(String packageName, String version) throws PIException{

                   

                                      if (packageName == null)

                                                throw new PIException("Package Name must not be null.");

                   

                                      if (version == null)

                                                version = "LATEST";

                   

                                      log.debug("Package requested: " + packageName + "/" + version);

                   

                                      String key = packageName + "|" + version;

                   

                                      if (!knowLedgeBases.containsKey(key)){

                                                log.info("Package " + key + " not cached, attempting to get from repository");

                                          UrlResource resource = (UrlResource) ResourceFactory.newUrlResource(url + "/org.drools.guvnor.Guvnor/package/" + packageName + "/" + version);

                                          resource.setBasicAuthentication("enabled");

                                          resource.setUsername("guest");

                                          resource.setPassword("guest");

                                          KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();

                                          kbuilder.add(resource, ResourceType.PKG);

                                          knowLedgeBases.put(key, kbuilder.newKnowledgeBase());                

                                      }

                   

                                      log.debug(knowLedgeBases.toString());

                   

                                      return knowLedgeBases.get(key);

                            }

                   

                   

                   

                            @Override

                            public EntityManagerFactory getEntityManagerFactory(){

                                      if (emf == null){

                                                emf = Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa" );

                                                Environment env = KnowledgeBaseFactory.newEnvironment();

                                                env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );

                                      }

                                      return emf;

                            }

                   

                            @Override

                            public synchronized Set<String> getLoadedKnowledgeBases(){

                                      return knowLedgeBases.keySet();

                            }

                  }

                  {code}

                   

                  Cheers,

                   

                  Gareth.

                  • 6. Re: Problem with multiple sessions
                    swiderski.maciej

                    Gareth, looking through this code I can't directly spot anything that could explain described behavior, would it be possible to get a sample executable test for it?

                     

                    I suspect something with session store (active session list) that you have there, I see some queuing there too so without a test I won't be able to help out with this as it's bit of custom code.

                    • 7. Re: Problem with multiple sessions
                      garethed

                      Hi Maciej,

                       

                      I will try and get a runnable sample together.

                      I have simplified my code somewhat and also as a temporary measure, I'm not disposing of sessions.

                       

                      More of a problem right now is that sessions don't seem to behave correctly after loading them manually.

                       

                      I can see in the database that they are being persisted (The session_info table is being populated).

                      After loading and registering listeners, completing a task does not invoke the next task so the session is pretty useless.

                       

                      I must have be missing a bit of knowledge on session management.

                       

                      I'm loading the sessions like this:

                       

                       

                      {code}

                                               // Get cached knowledge base or load based on package name and version

                                                    kbase = packageService.getKnowledgeBase(pws.getPackageRef(), pws.getPackageVersion());

                                                    env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);

                                                    StatefulKnowledgeSession session = JPAKnowledgeService.loadStatefulKnowledgeSession(pws.getId(), kbase, null, env);

                                               session.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

                                               session.getWorkItemManager().registerWorkItemHandler("UpdateWorkflowCurrentTask", new WorkflowCurrentTaskHandler(patientWorkflowSessionService, session.getId(), user));

                                               session.addEventListener(new WorkflowEventListener(patientWorkflowSessionService, session.getId(), user));

                                               session.fireAllRules();

                      {code}

                       

                       

                       

                       

                       

                       

                      Gareth.

                      • 8. Re: Problem with multiple sessions
                        swiderski.maciej

                        Gareth, make sure to invoke connect() on human task handler before you register it on the session, that will ensure it will receive events when tasks are completed.

                         

                        would be good if you provide runnable sample, that will make investigation much simpler.

                         

                        HTH