Output mapping from Human Task does not work
jchocholacek Mar 4, 2013 4:44 AMHello 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...