7 Replies Latest reply on Oct 12, 2006 8:58 AM by pedrosacosta

    sessions and forks

    pedrosacosta

      I'm using a fork in my process definition, but i want to persist in the DB the sibling tokens of the fork. The problem is, the way that i'm implementing this funcionality, i've

      HibernateException Illegal attempt to associate a collection with two open sessions
      
      error. The cause of the error is the following line inside SpawningMultipleTransitions:
      JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
      


      The way i'm doing is:

      processdefinition.xml
       ...
       <start-state name="start">
       <transition name="to_fork" to="Fork"></transition>
       </start-state>
       <fork name="Fork">
       <event type="node-enter">
       <action name="spawning" class="com.link.bem.jbpm.action.SpawningMultipleTransitions"/>
       </event>
       <transition name="Path_A" to="Acidentes_A1"></transition>
       <transition name="Path_B" to="Acidentes_B1"></transition>
       <transition name="Path_C" to="Acidentes_C1"></transition>
       <transition name="Path_D" to="Acidentes_D1"></transition>
       </fork>
       ...
      



      The problem is, when i enter the fork, i've already a JbpmContext session opened. How can use the session opened before enter the SpawningMultipleTransitions inside this class, or how should i close the opened session before open a new one inside the SpawningMultipleTransitions?

      I hope i've made myself clear.

      Thanks,
      Pedro

        • 1. Re: sessions and forks
          pedrosacosta

          Here is the SpawningMultipleTransitions

          
          public class SpawningMultipleTransitions extends Node implements Parsable, ActionHandler {
          
          
           private final Logger log = Logger.getLogger(getClass().getName());
          
          
           public void execute(ExecutionContext executionContext) {
           Token token = executionContext.getToken();
          
           // Get process instance
           Long pid = (Long) executionContext.getVariable("processInstanceId");
           JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
           ProcessInstance processInstance = jbpmContext.loadProcessInstance(pid);
           //---------------------------------------------
          
           // phase one: collect all the transitionNames
           List forkedTokens = new ArrayList();
          
           // by default, the fork spawns a token for each leaving transition
           Collection transitionNames = token.getNode().getLeavingTransitionsMap().keySet();
           //-------------------------
           //----------------------------------------
          
          // phase two: create forked tokens for the collected transition names
           Iterator iter = transitionNames.iterator();
           while (iter.hasNext()) {
           String transitionName = (String) iter.next();
           forkedTokens.add(createForkedToken(token, transitionName));
           }
           //---------------------------------------
          
           // phase three: launch child tokens from the fork over the given transitions
           iter = forkedTokens.iterator();
           while( iter.hasNext() ) {
          
           ForkedToken forkedToken = (ForkedToken) iter.next();
           Token childToken = forkedToken.token;
           String leavingTransitionName = forkedToken.leavingTransitionName;
          
           ExecutionContext childExecutionContext = new ExecutionContext(childToken);
           if (leavingTransitionName!=null) {
           childToken.getNode().leave(childExecutionContext, leavingTransitionName);
           jbpmContext.save(processInstance);
           jbpmContext.save(token);
           log.info("BEM-INFO: Process instance saved with id: " + processInstance.getId());//TODO:2DEL
          
           } else {
           childToken.getNode().leave(childExecutionContext);
           }
           }
           //---------------------------------
          
           jbpmContext.close();
           }
          
           protected ForkedToken createForkedToken(Token parent, String transitionName) {
           // instantiate the new token
           Token childToken = new Token(parent, getTokenName(parent, transitionName));
          
           // create a forked token
           ForkedToken forkedToken = new ForkedToken(childToken, transitionName);
          
           return forkedToken;
           }
          
           protected String getTokenName(Token parent, String transitionName) {
           String tokenName = null;
           if ( transitionName != null ) {
           if ( ! parent.hasChild( transitionName ) ) {
           tokenName = transitionName;
           } else {
           int i = 2;
           tokenName = transitionName + Integer.toString( i );
           while ( parent.hasChild( tokenName ) ) {
           i++;
           tokenName = transitionName + Integer.toString( i );
           }
           }
           } else { // no transition name
           int size = ( parent.getChildren()!=null ? parent.getChildren().size()+1 : 1 );
           tokenName = Integer.toString(size);
           }
           return tokenName;
           }
          
           static class ForkedToken {
           Token token = null;
           String leavingTransitionName = null;
           public ForkedToken(Token token, String leavingTransitionName) {
           this.token = token;
           this.leavingTransitionName = leavingTransitionName;
           }
           }
          }
          



          Here is the method that is executed before enter SpawningMultipleTransitions


          public Map nextState(String transition, Long processInstanceId){
          
           beginSessionTransaction(); // inicializar JBPM object
           ProcessInstance processInstance = jbpmContext.loadProcessInstance(processInstanceId);
          
           Token token = processInstance.getRootToken();
           String previousNodeName = token.getNode().getName();
          
           token.signal();// It's here that enter in the
           // SpawningMultipleTransitions
          
           log.info("BEM-INFO: Node transition: PreviousNode --> ActualNode\n"
           + previousNodeName + " --> " + token.getNode().getName());//TODO:2DEL
          
           jbpmContext.save(processInstance);
           jbpmContext.save(token);
           log.info("BEM-INFO: Process instance saved with id: " + processInstance.getId());//TODO:2DEL
          
           commitAndCloseSession(); // commit and close JBPM objects
          
           return result;
           }
          


          • 2. Re: sessions and forks
            pedrosacosta

            I've another question that is:

            2 - How can i retrieve the sibling tokens of the fork persisted in the DB?

            Thanks,
            Pedro

            • 3. Re: sessions and forks
              pedrosacosta

              I think that i'm reinventing the wheel when i use SpawningMultipleTransitions class, because, jbpm when enters a fork it executes org.jbpm.graph.node.Fork class. The SpawningMultipleTransitions is based on Fork class.

              So, the only question that i must do is:
              2 - How can i retrieve the sibling tokens of the fork persisted in the DB?

              This post have the intention of inform to forget my doubts about SpawningMultipleTransitions and only concern with the question of this post.

              • 4. Re: sessions and forks
                saviola

                Look at the class Token. It has four methods for retrieving its child tokens.
                The code is your best friend. :)

                Regards,
                Saviola

                • 5. Re: sessions and forks
                  pedrosacosta

                  Hi Saviola,

                  I've already saw this methods, but, let me rephrase the question.

                  The problem is, i've the sibling tokens of the Fork, saved in the DB. The part of the workflow inside the fork may have different levels, and the sibling tokens can be pointing to different levels of the running path inside the fork.

                  I want to retrieve the sibling tokens that are saved in the DB. How can i get them?

                  
                  Token forkToken = rootToken;
                  forkToken.getActiveChildren()
                  

                  is the right method?

                  Thanks,
                  Pedro

                  • 6. Re: sessions and forks
                    saviola

                    I am sorry but I can't get the question :(
                    What do yo umean by:

                    The part of the workflow inside the fork may have different levels
                    ?
                    What are these levels?
                    If you want to retrieve all the tokens of a particular token (no matter if it is the root one or not) write your own recursive method that goes down the levels and uses one of the methods of the Token class.

                    Saviola

                    • 7. Re: sessions and forks
                      pedrosacosta

                      Thanks for the reply. I did what Saviola said and it's working.

                      For anyone that interest, i get sibling tokens from a fork using getActiveChildren() and iterate over them.