7 Replies Latest reply on Aug 3, 2011 8:59 PM by garys

    Can a POJO be Parameter Mapped?

    garys

      All the examples I've seen map basic types. I mapped a POJO to a Service Task following the example of examples.junit

      testServiceTask() (which maps a string). When I debug the Service Task the operation method is called but the POJO parameter is null.

       

      Can a POJO be parameter and result mapped? Is there an example showing how?

       

      I did this in the XML editor of the BPMN file because the Process Editor doesn't save my changes.

        • 1. Re: Can a POJO be Parameter Mapped?
          calca

          Hi Gary,

           

          Yes, it is possible. I think this example can help you:

          https://github.com/Salaboy/Drools_jBPM5-Training-Examples/blob/master/jbpm5/04-jBPM5-PersistentEmergencyServiceProcess/

           

          You can check that the process

          https://github.com/Salaboy/Drools_jBPM5-Training-Examples/blob/master/jbpm5/04-jBPM5-PersistentEmergencyServiceProcess/src/test/resources/EmergencyServiceTracking.bpmn

          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

          1 of 1 people found this helpful
          • 2. Re: Can a POJO be Parameter Mapped?
            garys

            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

              Gary, 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

              1 of 1 people found this helpful
              • 4. Re: Can a POJO be Parameter Mapped?
                garys

                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

                  Gary,

                   

                  I just pulled an example:

                  https://github.com/calcacuervo/JBPM5-Samples/blob/master/bpmn-examples/src/test/java/com/test/Jbpm5ExamplesTest.java

                   

                  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

                    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

                      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());

                        }