cancel
Showing results for 
Search instead for 
Did you mean: 

(solved) Process variables dissapearing?

bramthielemans
Champ in-the-making
Champ in-the-making
Hi

I'm currently experiencing some weird issues with dissapearing process variables in my workflow. Hopefully someone here can help me.

The workflow I created is an approval workflow used by authors and publishers for a wiki-like application (accessible via web scripts).

The general idea is that authors can introduce or modify concepts and attach one or more categories to them. Each category is linked with one or more publishers. For each category on a concept, 1 publisher has to approve the concept. If any publisher rejects the concept, it is sent back to the author so he can make the requested changes and resubmit it. For this I am using a combination of a for-each fork and pooledactors.

Here is the workflow diagram:

[img]http://img188.imageshack.us/img188/8862/processimage.th.jpg[/img]

The problem exists within the start-review node, where I start the for-each fork:

<node name="start-review">
      <action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
         <foreach>#{lexicon.selectPooledPublishers(bpm_package.children[0])}</foreach>
         <var>publishers</var>
      </action>
      <transition name="review" to="review" />
</node>

The lexicon object gives me javascript access to some of my own Java functions, such as selectPooledPublishers. This function returns an object (array actually) suitable for using in a pooledactors assignment.

The pooledactors assignment happens in the review tasknode:

<task-node name="review">
      <task name="lexwf:reviewTask">
         <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
            <pooledactors>#{publishers}</pooledactors>
         </assignment>
      </task>
      <transition name="reject" to="handle-remarks" />
      <transition name="approve" to="end-review" />
</task-node>

I think that's all you need to know, the rest of the workflow does some mailing and approving/rejecting concepts and is working as desired.

Point is, at some point in the workflow the process variables seem to have been dissapeared. More precisely in this scenario:

author         publisher
=================================
1. new/modify concept
               2. reject
3. modify concept
               4. reject
5. modify concept

(note that creating or modifying a concept automatically starts or continues the workflow)

In workflow transitions it would look like this: START -> start-review (1) -> START-REVIEW -> review -> REVIEW -> reject (2) -> HANDLE-REMARKS -> request-review (3) -> START-REVIEW -> review -> REVIEW -> reject (4) -> HANDLE-REMARKS -> request-review (5) -> START-REVIEW

(uppercase = nodes, lowercase = transitions)

When performing steps 3 and 5 the workflow transitions from the handle-remarks task to the start-review node. A mail is also sent during this transition, which completes succesfully for both steps 3 and 5. For step 3 there is no problem at all. For step 5 I get this error:

org.alfresco.scripts.ScriptException: Failed to execute supplied script: ReferenceError: "bpm_package" is not defined. (AlfrescoScript#1)

So the bpm_package process variable cannot be found anymore. I actually had this problem earlier, but was able to solve it by using the <expression> and <variable> tags. But I don't think I can use these when dealing with a org.alfresco.repo.workflow.jbpm.ForEachFork action.

So, does anyone have any ideas/suggestions at all? If more information is needed I'll try to post it asap.

btw, I'm using Alfresco Labs 3Stable


Thanks Smiley Happy
3 REPLIES 3

sethatrothbury
Champ in-the-making
Champ in-the-making
This all really depends on how you're using the 'scripts' inside your process definition. I really can't be more specific than to say that depending on if you use the "org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript" class in some spots and not in others, and then if you use <script/><expression/> statements… it all changes the lifecycles of your variables.

If you post your entire process definition, or even email me, I'm sure we can point out where you went wrong. There's no reason to lose the bpm_package to your workflow, unless you did something wrong somewhere.

bramthielemans
Champ in-the-making
Champ in-the-making
Ok, here it is:

<?xml version="1.0" encoding="UTF-8"?>

<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="lexwf:approval">


   <!– SWIMLANES –>
   <swimlane name="initiator" />
   
   <!– No swimlane for publisher(s). These are assigned by a for-each fork –>


   <!– WORKFLOW STEPS –>
   
   <!– The starting state –>
   <start-state name="start">
      <description>Request an approval for a business concept</description>
      <task name="lexwf:requestApprovalTask" swimlane="initiator" />
      <transition name="start-review" to="start-review">
      <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
            <script>
                  //The selectPooledPublishers function returns an object (array actually) suitable for using in a pooledactors assignment.
                  // But here the result is just used to know which publishers should receive a mail.
                  var pubs = lexicon.selectPooledPublishers(bpm_package.children[0]);
                  var toMail = new Array();
                  // …
                  // Here 'toMail' gets filled with some unique usernames, depending on the contents of 'pubs'. I removed this part of the code because it's a bit lengthy and not really interesting.
                  // …
                  var mail = actions.create("mail");
                  mail.parameters.to_many = toMail;
                  mail.parameters.subject = "Business Concept approval: " + bpm_package.children[0].properties["cm:title"];
                  mail.parameters.from = initiator.properties["cm:email"];
                  mail.parameters.template = companyhome.childByNamePath("Data Dictionary/Email Templates/lexicon/lexicon_notify_publisher.ftl");
                  mail.parameters.text = "Request for business concept approval";
                  mail.execute(bpm_package.children[0]);
            </script>
         </action>
      </transition>
   </start-state>
   
   <!– The start-review node selects the publishers needed to publish the associated business concept. Upon
   entering the node a counter that keeps track of the approval count is set to 0 to ensure that both new and
   previously rejected concepts are forced to be reviewed by 1 publisher for each domain again. –>
   <node name="start-review">
      <action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
         <foreach>#{lexicon.selectPooledPublishers(bpm_package.children[0])}</foreach>
         <var>publishers</var>
      </action>
      <event type="node-enter">
         <script>
            <variable name="approveCount" access="read,write"/>
            <expression>
               approveCount = 0;
            </expression>
         </script>
      </event>
      <transition name="review" to="review" />
   </node>

   <task-node name="review">
      <task name="lexwf:reviewTask">
         <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
            <pooledactors>#{publishers}</pooledactors>
         </assignment>
      </task>
      <transition name="reject" to="handle-remarks">
         <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
            <script>
               <expression>
                  // rejectItem is a function that does nothing more than set a rejected aspect with some properties on a node.
                  lexicon.rejectItem(bpm_package.children[0], lexwf_comment);
               </expression>
               <variable name="bpm_package" access="read" />
               <variable name="lexwf_comment" access="read" />
            </script>
         </action>
         <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
            <script>
            <expression>
               var mail = actions.create("mail");
               mail.parameters.to = initiator.properties["cm:email"];               
               mail.parameters.subject = "RE: Business Concept approval: " + bpm_package.children[0].properties["cm:title"];
               var from = "alfresco@euroconsumers.com";
               if(bpm_package.children[0].hasAspect("lex:rejected")) {
                  from = bpm_package.children[0].properties["lex:rejectedBy"].properties["cm:email"];
               }
               mail.parameters.from = from;
               mail.parameters.template = companyhome.childByNamePath("Data Dictionary/Email Templates/lexicon/lexicon_notify_author.ftl");
               mail.parameters.text = "Request for business concept approval";
               mail.execute(bpm_package.children[0]);
            </expression>
            <variable name="initiator" access="read" />
            <variable name="bpm_package" access="read" />
            <variable name="companyhome" access="read" />
            </script>
         </action>
      </transition>
      <transition name="approve" to="end-review">
         <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
            <script>
               <expression>
                  approveCount = approveCount + 1;
                  // the publisherApproveItem function just sets some properties on a node to keep track of who approved the concept.
                  lexicon.publisherApproveItem(bpm_package.children[0], lexwf_comment);
               </expression>
               <variable name="approveCount" access="read,write" />
               <variable name="bpm_package" access="read" />
               <variable name="lexwf_comment" access="read" />
            </script>
         </action>
      </transition>
   </task-node>
   
   <join name="end-review">
      <transition to="is-approved" />
   </join>
   
   <decision name="is-approved">
      <transition name="approved" to="end">
         <condition>lexwf_approveCount > bpm_package.children[0].properties["lex:domainCategories"].length</condition>
         <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
            <runas>admin</runas>
            <script>
               <expression>
                  // The approveItem function removes and adds some aspects & properties on a node and checks in the node.
                  bpm_package.children[0] = lexicon.approveItem(bpm_package.children[0]);
               </expression>
               <variable name="bpm_package" access="read" />
               <variable name="initiator" access="read" />
            </script>
         </action>
         <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
            <script>
               var mail = actions.create("mail");
               mail.parameters.to = initiator.properties["cm:email"];
               mail.parameters.subject = "RE: Business Concept approval: " + bpm_package.children[0].properties["cm:title"];
               var from = "alfresco@euroconsumers.com";
               if (bpm_package.children[0].hasAspect("lex:published")) {
                  from = bpm_package.children[0].properties["lex:publishedBy"][bpm_package.children[0].properties["lex:publishedBy"].length - 1].properties["cm:email"];
               }
               if (bpm_package.children[0].hasAspect("lex:removed")) {
                  from = bpm_package.children[0].properties["lex:removedBy"][bpm_package.children[0].properties["lex:removedBy"].length - 1].properties["cm:email"];
               }
               mail.parameters.from = from;
               mail.parameters.template = companyhome.childByNamePath("Data Dictionary/Email Templates/lexicon/lexicon_notify_author.ftl");
               mail.parameters.text = "Request for business concept approval";
               mail.execute(bpm_package.children[0]);
            </script>
         </action>
      </transition>
      <transition name="not-approved" to="start-review" />
   </decision>

   <task-node name="handle-remarks">
      <description>Initiator (author) needs to handle the remarks</description>
      <task name="lexwf:handleRemarksTask" swimlane="initiator" />
      <transition name="request-review" to="start-review">
         <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript"> <!– Resend the mail –>
            <script>
               <expression>
                  var pubs = lexicon.selectPooledPublishers(bpm_package.children[0]);
                  var toMail = new Array();
                  // …
                  // Here 'toMail' gets filled with some unique usernames, depending on the contents of 'pubs'. I removed this part of the code because it's a bit lengthy and not really interesting.
                  // …
                  var mail = actions.create("mail");
                  mail.parameters.to_many = toMail;
                  mail.parameters.subject = "Business Concept approval: " + bpm_package.children[0].properties["cm:title"];
                  mail.parameters.from = initiator.properties["cm:email"];
                  mail.parameters.template = companyhome.childByNamePath("Data Dictionary/Email Templates/lexicon/lexicon_notify_publisher.ftl");
                  mail.parameters.text = "Request for business concept approval";
                  mail.execute(bpm_package.children[0]);
               </expression>
               <variable name="initiator" access="read" />
               <variable name="bpm_package" access="read" />
               <variable name="companyhome" access="read" />
            </script>
         </action>
      </transition>
   </task-node>
   
   <end-state name="end" />
   
   <event type="process-end" />
   

</process-definition>

I added some comments to clarify some functions that I'm calling through the lexicon object.

You'll also see that I'm using multiple <action class="…"> tags in some transitions. For some reason I sometimes get error messages when I perform all the transition's code in one action tag …

Also, I forgot to mention that ideally the workflow is started with a checked out node's workingcopy. That workingcopy is later checked in again by one of my lexicon functions. But that shouldn't be relevant because the problem only arises when doing rejecting concepts, and the checkin only happens when accepting concepts.

bramthielemans
Champ in-the-making
Champ in-the-making
I think I'm very close to the solution.

It looks like the problem is that I'm not doing a join of my for-earch fork after the reject transition. The reason why I didn't put one there was that I wanted the workflow to directly continue after a reject, without waiting for the decisions of the other publishers and I assumed a join node wasn't needed then.

I've inserted a basic join node now, and the problem seems to have dissapeared (for the moment I'm not using any scripting code except for some logging statements though). I suspect that this node will cause the workflow to pause until all publishers have made their decision, but I still need to verify that. If that is the case, I've found this class that I think should do what I want: org.alfresco.repo.workflow.jbpm.JoinEndForkedTokens.

So if I can use that class in a similar way that a for-each fork is started, that'd be great.

I'll report back later today or tomorrow.

-EDIT-

Well, I was kind of on the wrong track with JoinEndForkedTokens. Turns out just making a second join and setting a nOutOfM value was all I needed.

<join name="reject-join">
   <event type="node-enter">
      <script>
         node.nOutOfM = 1;
      </script>
   </event>
   <transition to="handle-remarks" />
</join>


Problem is solved.

Seth (and others who may have not replied), thank you for looking into this Smiley Happy