6 Replies Latest reply on Sep 24, 2012 9:15 AM by dward

    How to send jBPM signal event with data?

    tangblack

      Refer to https://community.jboss.org/wiki/SwitchYardBPMComponent

       

      Once the ticket has been successfully opened, and the acknowledgement returned, the rest of the process will execute as defined in the BPMN process definition.  Remember that further interaction with the BPM process can be done (beyond just starting it), but is not shown in this example.  Looking ahead, one might want to define an event in the process, perhaps representing an external interaction.  This event might come in as another SOAP request.  As long as there exists a <bpm:processInstanceId> SOAP header which correlates back to the correct process instance, once can signal an event with data in that request, or possibly even abort the process instance all together.  A future article will showcase process instance signaling.

       

       

       

       

       

      switchyard.jpgbpm.png

      Now I create a SwitchYard (0.6.0) including a jBPM process componet which be started by web service and wait the signal event to finish the process(see the attached file).  I write a test program named MyProcessTest.java(you can find it in the attached file) to start a process and send signal event via SOAP.

       

      Starting a process is work correctly but I can't send signal event with data which in SOAP body. The SOAP request below is work if the data be placed in SOAP header.

      <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
      <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:bpm="urn:switchyard-component-bpm:process:1.0">
                <soap:Header>
                          <bpm:processInstanceId>1</bpm:processInstanceId> <!-- process instance ID -->
                          <bpm:processEvent>Hello World</bpm:processEvent> <!--  processEvent mapping data of signalEvent method in jBPM -->
                </soap:Header>
                <soap:Body>
                          <urn:signal
                                    xmlns:urn="urn:com.example.switchyard:bpm_signal_event:0.0.1-SNAPSHOT">
                                    <!-- optional -->
                                    <string>World</string>
                          </urn:signal>
                </soap:Body>
      </soap:Envelope>
      

       

      I checked source code in debug mode, I found in BaseBPMExchangeHandler.java

      • It checks if there is "{urn:switchyard-component-bpm:process:1.0}processEvent" in EXCHAGE scope first.
      • If getting value of proessEvent return it (for example: it will get "Hello World" from <bpm:processEvent>Hello World</bpm:processEvent>).
      • Otherwise it returns the data in SOAP body.
          /**
           * Gets the process event from the Exchange Context.
           * @param context the Exchange Context
           * @param message the Message
           * @return the process event
           */
          protected Object getProcessEvent(Context context, Message message) {
              Property property = context.getProperty(PROCESS_EVENT_VAR, EXCHANGE);
              if (property != null) {
                  Object value = property.getValue();
                  if (value != null) {
                      return value;
                  } else if (message != null) {
                      return message.getContent();
                  }
              }
              return null;
          }
      

       

      I change SOAP header like below but get null. After checking in debug mode, there is no "{urn:switchyard-component-bpm:process:1.0}processEvent" in EXCHAGE scope and returns null in getProcessEvent method.

      <soap:Header>
           <bpm:processInstanceId>1</bpm:processInstanceId>
           <bpm:processEvent/>
      </soap:Header>
      
      or
      
      <soap:Header>
           <bpm:processInstanceId>1</bpm:processInstanceId>
           <bpm:processEvent></bpm:processEvent>
      </soap:Header>
      

       

      So, is there any method to send signal event with data in SOAP body? How to send processEvent property but no value via SOAP?

       

      Thanks in advance!

       

       

       

      Update!! 2012/9/21


      In SOAPContextMapper.java in switchyard-component-soap 0.6.0, mapFrom() gets SOAP header and map to SwitchYard context.

      mapFrom() will not put anything if the value of processEvent is empty.

          /**
           * {@inheritDoc}
           */
          @Override
          public void mapFrom(SOAPBindingData source, Context context) throws Exception {
              ...
              @SuppressWarnings("unchecked")
              Iterator<SOAPHeaderElement> soapHeaders = soapMessage.getSOAPHeader().examineAllHeaderElements();
              while (soapHeaders.hasNext()) {
                  SOAPHeaderElement soapHeader = soapHeaders.next();
                  QName qname = soapHeader.getElementQName();
                  if (matches(qname)) {
                      // SOAPMessage SOAP headers -> Context EXCHANGE properties
                      final Object value;
                      switch (_soapHeadersType != null ? _soapHeadersType : VALUE) { // _soapHeadersType is VALUE in this case
                          case CONFIG:
                              value = new ConfigurationPuller().pull(soapHeader);
                              break;
                          case DOM:
                              value = soapHeader;
                              break;
                          case VALUE: // Go into this case
                              value = soapHeader.getValue(); // It is null when I sending <bpm:processEvent></bpm:processEvent>
                              break;
                          case XML:
                              value = new ConfigurationPuller().pull(soapHeader).toString();
                              break;
                          default:
                              value = null;
                      }
                      if (value != null) { // Beacause value is null, so it doesn't put processEvent into EXCHAGE scope!
                          String name = qname.toString();
                          context.setProperty(name, value, EXCHANGE).addLabels(SOAP_MESSAGE_HEADER);
                      }
                  }
              }
          }
      

       

       

      In BaseBPMExchangeHandler.java, getProcessEvent() checks if there is "{urn:switchyard-component-bpm:process:1.0}processEvent" in EXCHAGE scope as below.

      processEvent=[name={urn:switchyard-component-bpm:process:1.0}processEvent, scope=EXCHANGE, value=Hello World, labels={soap_message_header}]

       

       

      I guess that is why BaseBPMExchangeHandler.getProcessEvent can't get processEvent in EXCHAGE scope when sending signal event without value in bpm:processEvent property.