2 Replies Latest reply on Mar 4, 2013 5:07 AM by jchocholacek

    Output mapping from Human Task does not work

    jchocholacek

      Hello there,

       

      I have a problem with mapping the Human Task output to process variables. My code is inspired by the https://community.jboss.org/people/bpmn2user/blog/2011/09/21/jbpm5-web-example blog post.

       

      I run it in Tomcat 6, using the Mina HT service.

       

      Here is my process definition:

      <?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://www.omg.org/spec/BPMN/20100524/MODEL"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
                   xmlns:g="http://www.jboss.org/drools/flow/gpd"
                   xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
                   xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
                   xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
                   xmlns:tns="http://www.jboss.org/drools">
      
        <itemDefinition id="_mgnlDataItem" structureRef="java.util.Map" />
      
        <itemDefinition id="_9-mgnlDataItem" structureRef="java.util.Map" />
      
        <process processType="Private" isExecutable="true" id="jch.workflow.test" name="Flow Test" tns:packageName="defaultPackage" >
      
          <extensionElements>
           <tns:import name="java.util.Map" />
          </extensionElements>
          <!-- process variables -->
          <property id="mgnlData" itemSubjectRef="_mgnlDataItem"/>
      
          <!-- nodes -->
          <startEvent id="_1" name="StartProcess" />
          <endEvent id="_6" name="End" >
              <terminateEventDefinition/>
          </endEvent>
          <scriptTask id="_7" name="Entry Script" scriptFormat="http://www.java.com/java" >
            <script>String processId = "" + kcontext.getProcessInstance().getId();
      System.out.println("ENTRY SCRIPT: " + processId);
      Map data = (Map) kcontext.getVariable("mgnlData");
      if (data==null) {
        System.out.println("Empty DATA");
      } else {
        System.out.println("DATA: " + data.toString());
      }
      </script>
          </scriptTask>
          <scriptTask id="_8" name="Exit Script" scriptFormat="http://www.java.com/java" >
            <script>String processId = "" + kcontext.getProcessInstance().getId();
      System.out.println("EXIT SCRIPT: " + processId);
      Map data = (Map) kcontext.getVariable("mgnlData");
      if (data==null) {
        System.out.println("Empty DATA");
      } else {
        System.out.println("DATA: " + data.toString());
      }
      </script>
          </scriptTask>
          <userTask id="_9" name="User Task" >
            <extensionElements>
              <tns:onEntry-script scriptFormat="http://www.java.com/java">
                <script>System.out.println("Human Task - Entry action");</script>
              </tns:onEntry-script>
              <tns:onExit-script scriptFormat="http://www.java.com/java">
                <script>System.out.println("Human Task - Exit action");</script>
              </tns:onExit-script>
            </extensionElements>
            <ioSpecification>
              <dataInput id="_9_ContentInput" name="Content" />
              <dataOutput id="_9_mgnlDataOutput" name="mgnlData" />
              <inputSet>
                <dataInputRefs>_9_ContentInput</dataInputRefs>
              </inputSet>
              <outputSet>
                <dataOutputRefs>_9_mgnlDataOutput</dataOutputRefs>
              </outputSet>
            </ioSpecification>
            <dataInputAssociation>
              <sourceRef>mgnlData</sourceRef>
              <targetRef>_9_ContentInput</targetRef>
            </dataInputAssociation>
            <dataOutputAssociation>
              <sourceRef>_9_mgnlDataOutput</sourceRef>
              <targetRef>mgnlData</targetRef>
            </dataOutputAssociation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>peter</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>
      
          <!-- connections -->
          <sequenceFlow id="_8-_6" sourceRef="_8" targetRef="_6" />
          <sequenceFlow id="_1-_7" sourceRef="_1" targetRef="_7" />
          <sequenceFlow id="_9-_8" sourceRef="_9" targetRef="_8" />
          <sequenceFlow id="_7-_9" sourceRef="_7" targetRef="_9" />
      
        </process>
      
        <bpmndi:BPMNDiagram>
          ...
        </bpmndi:BPMNDiagram>
      
      </definitions>
      

       

      This is how I start the process:

       

          public RunningProcess launch(Workflow workflow, Map<String, Object> parameters) throws WorkflowException {
              Map<String,Object> processParams = new HashMap<String,Object>();
              processParams.put(RunningProcess.DATA, parameters);
              try {
                  // start user transaction
                  UserTransaction ut = (UserTransaction) new InitialContext().lookup("java:comp/UserTransaction");
                  ut.begin();
                  // start process
                  ProcessInstance pi = this.ksession.startProcess(workflow.getId(), processParams);
                  this.ksession.fireAllRules();
                  // commit
                  ut.commit();
                  return new ProcessImpl(pi);
              } catch (Exception e) {
                  log.debug("Error starting workflow [" + workflow.getId() + "].", e);
                  throw new WorkflowException("Error starting workflow.", e);
              }
          }
      

       

      RunningProcess.DATA containg the "mgnlData" string, Workflow is my bean holding the process definition data, RunningProcess / ProcessImpl are my wrappers for the ProcessInstace. Then I call this method from:

       

      Map<String, Object> data = new HashMap<String, Object>();
      data.put("string", "string value");
      data.put("int", 42);
      process = manager.launch("test", data);
      

       

      And how I handle the Human Task:

       

       

      // prepare data
      Map<String, Object> data = new HashMap<String, Object>();
      Map<String, Object> mgnlData = new HashMap<String, Object>();
      mgnlData.put("int", 1111);
      mgnlData.put("string", "new value");
      data.put(RunningProcess.DATA, mgnlData);
      // start user transaction
      UserTransaction ut = (UserTransaction) new InitialContext().lookup("java:comp/UserTransaction");
      ut.begin();
      // start processing the task
      BlockingTaskOperationResponseHandler responseHandler = new BlockingTaskOperationResponseHandler();
      this.taskClient.start(summary.getId(), user, responseHandler);
      responseHandler.waitTillDone(1000);
      // and complete the task
      responseHandler = new BlockingTaskOperationResponseHandler();
      this.taskClient.complete(summary.getId(), user, map2contentData(data), responseHandler);
      responseHandler.waitTillDone(2000);
      // commit transaction
      ut.commit();
      

       

      The map2contentData method is based on the code from jBPM5 web example blog post:

       

          protected ContentData map2contentData(Map data) {
              ContentData contentData = null;
              if (data != null) {
                  ByteArrayOutputStream bos = new ByteArrayOutputStream();
                  ObjectOutputStream out;
                  try {
                      out = new ObjectOutputStream(bos);
                      out.writeObject(data);
                      out.close();
                      contentData = new ContentData();
                      contentData.setContent(bos.toByteArray());
                      contentData.setAccessType(AccessType.Inline);
                  } catch (IOException e) {
                      log.error("Problem saving output data.", e);
                  }
              }
              return contentData;
          }
      

       

      But it results in the empty process variable in the end (console output):

       

      ENTRY SCRIPT: 425984
      DATA: {int=42, string=string value}
      Human Task - Entry action
      
      ...
      
      Human Task - Exit action
      EXIT SCRIPT: 425984
      Empty DATA
      
      

       

      I expect sort-of PEBKAC error, but I couldn't find what did I forget...