[rules-users] Flow variables not getting updated when fact changes in rule node

Todd Pagni todd.pagni at datacert.com
Wed Jan 27 16:39:04 EST 2010


I am seeing a problem in the latest stable build 12/27 andn 1/26 where a
flow variable does not get updates from a facts updated in a rule node
in the flow.  Both the flow variable and the fact are initially the same
object instance, but It looks like the flow variable gets a cloned
instance after the rule node.  

 

I am inserting 1 fact and running a flow with a debug node, a rule node,
a debug node, and a human task.  As you can see below the hashcode
changes for the flow variable after the rule node, but retains the user
value set earlier in the flow.  After the rule node the user should be
myuser which is set in the rule, but instead has the value bogus, which
is set in the first debug node. 

 

Is anyone else seeing similar issues in drools flow?  This is happening
when we run in JBoss 5.1.   This is a blocking issue that makes drools
flow unusable for us, so any help you can provide is appreciated.  

 

Debug:

 

15:00:31,985 INFO  [STDOUT] ******** flowApproval hashcode at fact
insert:18886777

15:00:31,985 INFO  [STDOUT] Hibernate: insert into ProcessInstanceInfo
(externalVariables, lastModificationDate, lastReadDate, processId,
processInstanceByteArray, startDate, state, OPTLOCK) values (?, ?, ?, ?,
?, ?, ?, ?)

15:00:31,985 INFO  [STDOUT] ******** first flow node, hashcode: 18886777
user: null

15:00:31,985 INFO  [STDOUT] ******** first flow node after approver set
to  bogus, hashcode: 18886777 user: bogus

15:00:32,000 INFO  [STDOUT] Hibernate: update ProcessInstanceInfo set
externalVariables=?, lastModificationDate=?, lastReadDate=?,
processId=?, processInstanceByteArray=?, startDate=?, state=?, OPTLOCK=?
where processInstanceId=? and OPTLOCK=?

15:00:32,000 INFO  [STDOUT] Hibernate: insert into
ProcessInstanceInfo_eventTypes (ProcessInstanceInfo_processInstanceId,
element) values (?, ?)

15:00:32,000 INFO  [STDOUT] Hibernate: update SessionInfo set dirty=?,
lastModificationDate=?, rulesByteArray=?, startDate=? where id=?

15:00:32,000 INFO  [STDOUT] ******** in rule node setting approver to
enduser, hashcode: 18886777 user: myuser

15:00:32,000 INFO  [STDOUT] Hibernate: select
processins0_.processInstanceId as col_0_0_ from ProcessInstanceInfo
processins0_ where ? in (select eventtypes1_.element from
ProcessInstanceInfo_eventTypes eventtypes1_ where
processins0_.processInstanceId=eventtypes1_.ProcessInstanceInfo_processI
nstanceId)

15:00:32,000 INFO  [STDOUT] Hibernate: select
processins0_.processInstanceId as processI1_149_0_,
processins0_.externalVariables as external2_149_0_,
processins0_.lastModificationDate as lastModi3_149_0_,
processins0_.lastReadDate as lastRead4_149_0_, processins0_.processId as
processId149_0_, processins0_.processInstanceByteArray as
processI6_149_0_, processins0_.startDate as startDate149_0_,
processins0_.state as state149_0_, processins0_.OPTLOCK as OPTLOCK149_0_
from ProcessInstanceInfo processins0_ where
processins0_.processInstanceId=?

15:00:32,016 INFO  [STDOUT] ******** after rule node, hashcode:15392910
user: bogus

 

Rule:

 

dialect "mvel"

 

rule "Assign Initial Approver"

ruleflow-group "approver"

no-loop

      when

            $flow : com.datacert.FlowApproval()

      then

            modify( $flow ) { setLastapprover( 'myuser' ) };

            System.out.println("******** in rule node setting approver
to enduser, hashcode: " + $flow.hashCode() + " user: " +
$flow.getLastapprover());

end

 

Flow: 

 

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

<definitions id="Definition"

             targetNamespace="http://www.jboss.org/drools"

             typeLanguage="http://www.java.com/javaTypes"

             expressionLanguage="http://www.mvel.org/2.0"

             xmlns="http://schema.omg.org/spec/BPMN/2.0"

             xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"

             xs:schemaLocation="http://schema.omg.org/spec/BPMN/2.0
BPMN20.xsd"

             xmlns:g="http://www.jboss.org/drools/flow/gpd"

             xmlns:tns="http://www.jboss.org/drools">

 

  <itemDefinition id="entityIdItem" structureRef="java.lang.Object" />

  <itemDefinition id="entityItem" structureRef="java.lang.Object" />

  <itemDefinition id="flowApprovalItem" structureRef="java.lang.Object"
/>

 

  <resource id="Actor" name="Human Actor" />

 

  <process id="com.datacert.workflow.Base" name="approval" >

 

    <!-- process variables -->

    <property id="entityId" itemSubjectRef="tns:entityIdItem"/>

    <property id="entity" itemSubjectRef="tns:entityItem"/>

    <property id="flowApproval" itemSubjectRef="tns:flowApprovalItem"/>

 

    <!-- nodes -->

    <endEvent id="_2" name="End" g:x="564" g:y="16" g:width="48"
g:height="48" />

    <userTask id="_4" name="Human Task" g:x="432" g:y="16" g:width="100"
g:height="48" >

      <ioSpecification>

        <dataInput id="_4_CommentInput" name="Comment" />

        <dataInput id="_4_TaskNameInput" name="TaskName" />

        <dataInput id="_4_ContentInput" name="Content" />

        <inputSet>

          <dataInputRefs>_4_CommentInput</dataInputRefs>

          <dataInputRefs>_4_TaskNameInput</dataInputRefs>

          <dataInputRefs>_4_ContentInput</dataInputRefs>

        </inputSet>

        <outputSet>

        </outputSet>

      </ioSpecification>

      <property id="_4_Comment" />

      <property id="_4_TaskName" />

      <property id="_4_Content" />

      <dataInputAssociation>

        <assignment>

          <from xs:type="tFormalExpression">workitem</from>

          <to xs:type="tFormalExpression">_4_CommentInput</to>

        </assignment>

        <sourceRef>_4_Comment</sourceRef>

        <targetRef>_4_CommentInput</targetRef>

      </dataInputAssociation>

      <dataInputAssociation>

        <assignment>

          <from xs:type="tFormalExpression">Human Task</from>

          <to xs:type="tFormalExpression">_4_TaskNameInput</to>

        </assignment>

        <sourceRef>_4_TaskName</sourceRef>

        <targetRef>_4_TaskNameInput</targetRef>

      </dataInputAssociation>

      <dataInputAssociation>

        <assignment>

          <from xs:type="tFormalExpression">#{entityId}</from>

          <to xs:type="tFormalExpression">_4_ContentInput</to>

        </assignment>

        <sourceRef>_4_Content</sourceRef>

        <targetRef>_4_ContentInput</targetRef>

      </dataInputAssociation>

      <potentialOwner resourceRef="tns:Actor" >

        <resourceAssignmentExpression>

 
<formalExpression>#{flowApproval.getLastapprover()}</formalExpression>

        </resourceAssignmentExpression>

      </potentialOwner>

    </userTask>

    <scriptTask id="_6" name="After Rule" g:x="320" g:y="16"
g:width="80" g:height="48" >

      <script>System.out.println("******** after rule node, hashcode:" +
flowApproval.hashCode() + " user: " +
flowApproval.getLastapprover());</script>

    </scriptTask>

    <startEvent id="_1" name="StartProcess" g:x="16" g:y="16"
g:width="48" g:height="48" />

    <businessRuleTask id="_3" name="Rule" g:x="208" g:y="16"
g:width="80" g:height="48" g:ruleFlowGroup="approver" />

    <scriptTask id="_7" name="Before Rule" g:x="96" g:y="16"
g:width="80" g:height="48" >

      <script>System.out.println("******** first flow node, hashcode: "
+ flowApproval.hashCode() + " user: " + flowApproval.getLastapprover());

flowApproval.setLastapprover("bogus");

System.out.println("******** first flow node after approver set to
bogus, hashcode: " + flowApproval.hashCode() + " user: " +
flowApproval.getLastapprover());</script>

    </scriptTask>

 

    <!-- connections -->

    <sequenceFlow sourceRef="_4" targetRef="_2" />

    <sequenceFlow sourceRef="_6" targetRef="_4" />

    <sequenceFlow sourceRef="_3" targetRef="_6" />

    <sequenceFlow sourceRef="_7" targetRef="_3" />

    <sequenceFlow sourceRef="_1" targetRef="_7" />

 

  </process>

 

</definitions>

 

 

 

Most Code: 

 

package com.datacert;

 

import groovy.lang.GroovyClassLoader;

 

import java.util.HashMap;

import java.util.Map;

import java.util.Properties;

 

import javax.annotation.Resource;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.persistence.EntityManagerFactory;

import javax.persistence.Persistence;

 

import org.apache.log4j.Level;

import org.drools.KnowledgeBase;

import org.drools.KnowledgeBaseConfiguration;

import org.drools.KnowledgeBaseFactory;

import org.drools.SessionConfiguration;

import org.drools.SystemEventListenerFactory;

import org.drools.base.MapGlobalResolver;

import org.drools.bpmn2.xml.BPMNSemanticModule;

import org.drools.builder.KnowledgeBuilder;

import org.drools.builder.KnowledgeBuilderConfiguration;

import org.drools.builder.KnowledgeBuilderError;

import org.drools.builder.KnowledgeBuilderErrors;

import org.drools.builder.KnowledgeBuilderFactory;

import org.drools.builder.ResourceType;

import org.drools.compiler.PackageBuilderConfiguration;

import org.drools.io.ResourceFactory;

import org.drools.logger.KnowledgeRuntimeLogger;

import org.drools.logger.KnowledgeRuntimeLoggerFactory;

import org.drools.persistence.jpa.JPAKnowledgeService;

import org.drools.process.workitem.wsht.CommandBasedWSHumanTaskHandler;

import org.drools.runtime.Environment;

import org.drools.runtime.EnvironmentName;

import org.drools.runtime.KnowledgeSessionConfiguration;

import org.drools.runtime.StatefulKnowledgeSession;

import org.drools.runtime.process.ProcessInstance;

import org.drools.runtime.process.WorkItemManager;

import org.drools.task.service.MinaTaskServer;

import org.drools.task.service.TaskService;

 

 

import com.arjuna.ats.jta.TransactionManager;

 

 

public class FlowService {

    

    private static final String  FLOW_SERVICE_URL      =
"flow.service.url";

    

    private static final String  FLOW_SERVICE_LOCATION =
"flow.service.location";

    

    private TaskService          taskService;

    

    private MinaTaskServer       server;

    

    private EntityManagerFactory taskServerEntityManagerFactory;

   

    

    public void startWorkflow() {

        Map<String, Object> parameters = new HashMap<String, Object>();

        parameters.put("entityId", 22);

        parameters.put("flowApproval", new FlowApproval());

        

        KnowledgeBase kbase = getKnowledgeBase("approval.bpmn",
"approval.drl");

        StatefulKnowledgeSession ksession = getSession(kbase);

        KnowledgeRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

        registerHumanTaskHandler(ksession);

        

        ksession.insert(parameters.get("flowApproval"));

        System.out.println("******** flowApproval hashcode at fact
insert:" + parameters.get("flowApproval").hashCode());

        

        ProcessInstance pi =
ksession.startProcess("com.datacert.workflow.Base", parameters);

        ksession.fireAllRules();

 

    }

 

   

    private ClassLoader getClassLoader() {

        GroovyClassLoader gcl = new GroovyClassLoader();

        gcl.addClasspath("c:\\temp\\");

        return gcl;

    }

    

    private Environment getEnvironment() {

        Environment env = KnowledgeBaseFactory.newEnvironment();

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

        env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);

        

        env.set(EnvironmentName.GLOBALS, new MapGlobalResolver());

        

        InitialContext ctx = null;

        try {

            ctx = new InitialContext();

        } catch (NamingException e) {

            System.err.println(e);

        }

        env.set(EnvironmentName.TRANSACTION_MANAGER,
TransactionManager.transactionManager(ctx));

        

        return env;

    }

    

    private KnowledgeBase getKnowledgeBase(String xmlFileName, String
ruleFileName) {

        KnowledgeBaseConfiguration config =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null,
getClassLoader());

        KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(config);

        kbase.addKnowledgePackages(getKnowledgeBuilder(xmlFileName,
ruleFileName).getKnowledgePackages());

        return kbase;

    }

    

    private KnowledgeBuilder getKnowledgeBuilder(String xmlFileName,
String ruleFileName) {

        Thread.currentThread().setContextClassLoader(getClassLoader());

        System.setProperty("drools.dialect.mvel.strict", "false");

        KnowledgeBuilderConfiguration conf =
KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null,

                getClassLoader());

        

        ((PackageBuilderConfiguration) conf).initSemanticModules();

        ((PackageBuilderConfiguration) conf).addSemanticModule(new
BPMNSemanticModule());

        KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder(conf);

 
kbuilder.add(ResourceFactory.newClassPathResource("approval.bpmn"),
ResourceType.DRF);

        

 
kbuilder.add(ResourceFactory.newClassPathResource("approval.drl"),
ResourceType.DRL);

        KnowledgeBuilderErrors errors = kbuilder.getErrors();

        if (errors.size() > 0) {

            for (KnowledgeBuilderError error : errors) {

                System.err.println(error);

            }

            throw new IllegalArgumentException("Could not parse
knowledge.");

        }

        return kbuilder;

    }

    

    private StatefulKnowledgeSession getSession(int sessionId,
KnowledgeBase kbase) {

        return
JPAKnowledgeService.loadStatefulKnowledgeSession(sessionId, kbase,
getSessionConfig(), getEnvironment());

    }

    

    private StatefulKnowledgeSession getSession(KnowledgeBase kbase) {

        return JPAKnowledgeService.newStatefulKnowledgeSession(kbase,
getSessionConfig(), getEnvironment());

    }

    

    private KnowledgeSessionConfiguration getSessionConfig() {

        SessionConfiguration c = new SessionConfiguration();

        c.setClassLoader(getClassLoader());

        return c;

    }

    

    private void registerHumanTaskHandler(StatefulKnowledgeSession
ksession) {

        

        CommandBasedWSHumanTaskHandler approveTask = new
CommandBasedWSHumanTaskHandler(ksession);

        

        WorkItemManager wm = ksession.getWorkItemManager();

        

        wm.registerWorkItemHandler("Human Task", approveTask);

    }

    

}

 

 

Thanks,

Todd

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20100127/7a9e4a22/attachment.html 


More information about the rules-users mailing list