-
1. Re: Can a POJO be Parameter Mapped?
calca Aug 1, 2011 8:14 AM (in response to garys)1 of 1 people found this helpfulHi Gary,
Yes, it is possible. I think this example can help you:
You can check that the process
contains complex variables.
Basically, you have to:
1) Declare de variable type:
<itemDefinition id="_emergencyItem" structureRef="com.wordpress.salaboy.example.model.Emergency"/>
2) Declare the variable:
<property id="emergency" itemSubjectRef="_emergencyItem"/>
3)
Declare the variable as input (or output) in the task:
<userTask id="_2" name="Ask for Emergency Information">
<ioSpecification>
<dataInput id="_2_emergencyInput" name="emergency"/>
....
....
<inputSet>
<dataInputRefs>_2_emergencyInput</dataInputRefs>
....
</inputSet>
<outputSet>
...
</outputSet>
</ioSpecification>
<dataInputAssociation>
<sourceRef>emergency</sourceRef>
<targetRef>_2_emergencyInput</targetRef>
</dataInputAssociation>
</userTask>
4) Send it as parameter in the process, or as an output of another task.
Hope it helps.
Demian
-
2. Re: Can a POJO be Parameter Mapped?
garys Aug 2, 2011 4:03 PM (in response to calca)Thanks Demian,
I'm still doing something wrong but I don't see it.
I followed the example carefully but I am still getting a null ServiceTask parameter. Before I get to the ServiceTask I have a HumanTask with the same POJO as input and output in my BPMN file. I'm using the example TestWorkItemHandler and not doing anything with the POJO. Do I need to?
In the ServiceTask I'm using ServiceTaskHandler.
In jUnit...
@Test
public void evaluateScore() throws Exception {
// given
final StatefulKnowledgeSession kSession = createKnowledgeSession(fr.getKbase());
TestWorkItemHandler testWorkItemHandler = new TestWorkItemHandler();
kSession.getWorkItemManager().registerWorkItemHandler("Human Task", testWorkItemHandler);
WorkItemManager wim = kSession.getWorkItemManager();
kSession.getWorkItemManager().registerWorkItemHandler("Service Task", new ServiceTaskHandler());
...
Map<String, Object> params = new HashMap<String, Object>();
params.put("vars", vars);
...
new Thread(new Runnable() {
public void run() {
kSession.fireUntilHalt(); // fireAllRules hangs
}
}).start();
ProcessInstance pi = kSession.startProcess("x.x.x.workflow.xxx", params);
Thread.sleep(250);
// then
assertTrue(pi.getState() == ProcessInstance.STATE_ACTIVE);
restoreSession(kSession, true);
WorkItem workItem = testWorkItemHandler.getWorkItem();
assertNotNull(workItem);
assertEquals(workItem.PENDING, workItem.getState());
...
wim.completeWorkItem(workItem.getId(), null);
After completing the HumanTask workItem it executes the ServiceTask
public XX execute(XX vars) {
if(vars == null) { //@FIXME shouldn't be null
vars = new XX();
vars.setValidScore(true);
}
if(vars.isCanScore()) { //@TODO real implementation
vars.setValidScore(true);
}
return vars;
}
In BPMN
...
<itemDefinition id="_varsItem" structureRef="x.x.x.workflow.xxx" />
...
<itemDefinition id="_11_InMessageType" structureRef=""x.x.x.workflow.xxx" />
<message id="_11_InMessage" itemRef="_11_InMessageType" />
<interface id="_11_ServiceInterface" name=""x.x.x.workflow.xxx.EvaluateScore">
<operation id="_11_ServiceOperation" name="execute">
<inMessageRef>_11_InMessage</inMessageRef>
</operation>
</interface>
...
<!-- process variables -->
<property id="vars" itemSubjectRef="_varsItem"/>
...
<serviceTask id="_11" name="Evaluate Score" operationRef="_11_ServiceOperation" implementation="Other" >
<ioSpecification>
<dataInput id="_11_varsInput" name="vars" />
<dataOutput id="_11_varsOutput" name="vars" />
<inputSet>
<dataInputRefs>_11_varsInput</dataInputRefs>
</inputSet>
<outputSet>
<dataOutputRefs>_11_varsOutput</dataOutputRefs>
</outputSet>
</ioSpecification>
<dataInputAssociation>
<sourceRef>vars</sourceRef>
<targetRef>_11_varsInput</targetRef>
</dataInputAssociation>
<dataOutputAssociation>
<sourceRef>_11_varsOutput</sourceRef>
<targetRef>vars</targetRef>
</dataOutputAssociation>
</serviceTask>
-
3. Re: Can a POJO be Parameter Mapped?
calca Aug 2, 2011 6:11 PM (in response to garys)1 of 1 people found this helpfulGary, if you use the default work item :
org.jbpm.bpmn2.handler.ServiceTaskHandler
I think the parameter has to be called "Parameter".
And then it is invoked:
...
Object parameter = workItem.getParameter("Parameter");
try {
Class<?> c = Class.forName(i);
Object instance = c.newInstance();
Class<?>[] classes = null;
Object[] params = null;
if (parameterType != null) {
classes = new Class<?>[] {
Class.forName(parameterType)
};
params = new Object[] {
parameter
};
}
Method method = c.getMethod(operation, classes);
Object result = method.invoke(instance, params);
Demian
-
4. Re: Can a POJO be Parameter Mapped?
garys Aug 2, 2011 6:59 PM (in response to calca)Thanks again for your help, this is very frustrating.
I made this change
<serviceTask id="_11" name="Evaluate Score" operationRef="_11_ServiceOperation" implementation="Other" >
<ioSpecification>
<dataInput id="_11_varsInput" name="Parameter" />
<dataOutput id="_11_varsOutput" name="Result" />
But the parameter is still null in my service task method. BPMN2-ServiceProcess and its jUnit test testServiceTask() show no other references to "Parameter" so I didn't change anything else.
Also ServiceTaskHandler doesn't provide a getter for workItem so I don't see how to debug or call
public class ServiceTaskHandler implements WorkItemHandler {
public void executeWorkItem(WorkItem workItem, WorkItemManager manager)
-
5. Re: Can a POJO be Parameter Mapped?
calca Aug 3, 2011 12:21 PM (in response to garys)Gary,
I just pulled an example:
That uses a service task with a POJO. It is the same than the example in jbpm, but with custom intput/output.
You can check it and compare.
If you still have the problem, you can make a simple project with a test that fails with your implementation and we can take a look.
Demian
-
6. Re: Can a POJO be Parameter Mapped?
garys Aug 3, 2011 2:37 PM (in response to calca)Demian,
I was doing the same as your example except my itemDefinition had a structureRef, some examples define it and some don't.
Then I copied my project and started removing tasks to make it simple. After I deleted the Human Task preceding my Service Task the parameter was correctly passed to the service method.
It looks like I have to propagate the POJO past the Human Task. What am I supposed to do? I'm using a copy of Kris TestWorkItemHandler ( it's still in jUnit).
-
7. Re: Can a POJO be Parameter Mapped?
garys Aug 3, 2011 8:59 PM (in response to calca)The reason the service task parameter worked after removing the Human Task is that the TestWorkItemHandler(s) I copied from examples completed the task with null results. Once I passed the pojo to workItemManager.completeWorkItem(...) my service task method then got the pojo. This means you have to customize your testWorkItemHandlers to complete with the result you expect.
class MyAutomaticHumanSimulatorWorkItemHandler implements WorkItemHandler {
private List<WorkItem> workItems = new ArrayList<WorkItem>();
public void executeWorkItem(WorkItem workItem, WorkItemManager workItemManager) {
workItems.add(workItem);
System.out.println("Map of Parameters = " + workItem.getParameters());
PIvars vars = (PIvars) workItem.getParameter("vars");
vars.setCanScore(true);
vars.setScore(new BigDecimal(4));
Map<String,Object>results = new HashMap();
results.put("vars", vars);
workItemManager.completeWorkItem(workItem.getId(), results);
System.out.println("Workitem completed " + workItem.getName());
}