1 2 Previous Next 26 Replies Latest reply on Nov 6, 2012 4:40 PM by Brian Fitzpatrick

    How to implement Asychronous services in a jBPM5 process

    Jeff DeLong Master

      Asychronous services are frequently part of a business process. BPEL handles this nicely through CorrelationSets and other posssibly other mechanisms (e.g., WS-Addressing). It is not clear how to implement this using jBPM5 and SwitchYard.

       

      The first challenge is how to design the process.

       

      pqprocess1.png is an attempt to model this process using a SYTask followed by a ReceiveTask. It is not clear that the choice of ReceiveTask is correct. jBPM5 does not really support receive tasks, although it does support signaling a process through the event API.

       

      SwitchYard appears to support the signalAPI:

       

      <component name="MyService">

          <implementation.bpm xmlns="urn:switchyard-component-bpm:config:1.0" processDefinition="META-INF/MyService.bpmn" processDefinitionType="BPMN2" processId="MyService">

              <action name="start" type="START_PROCESS"/>

              <action eventType="myEvent" name="signal" type="SIGNAL_EVENT"/>

       

      So perhaps something like the following would work:

       

       

      SYProcessStarterService

           SOAP Binding

           BPM Implementation

       

      SYTaskService

           Camel Route with transformation

           Outgoing SOAPBinding

       

      SYCallbackService

           Incoming SOAP Binding

           BPM Implementation - signal

       

      Though it is not clear what would be specified in the implementation, or how SY would know which processInstance to signal?

        • 1. Re: How to implement Asychronous services in a jBPM5 process
          David Ward Master

          With regard to "which processInstance to signal", the following property is set in the context after a process is started:

           

          {urn:switchyard-component-bpm:process:1.0}processInstanceId

           

          You can then use that in subsequent calls to define which process instance will get signaled.

           

          Note: I understand that using a QName string as a context property key is probably less favorable than a java package-style key (e.g. org.switchyard.component.bpm.processInsanceId).  It was a first stab at "spacing" variable names when the BPM component was first introduced. I'd be curious what your thoughts/preferences would be on this.

          • 2. Re: How to implement Asychronous services in a jBPM5 process
            Jeff DeLong Master

            By subsequent calls I assume you mean subsequent calls to the same service? How would this be defined? My current WSDL looks like

             

              <wsdl:service name="PolicyQuoteProcessServiceService">

                    <wsdl:port binding="pps:PolicyQuoteProcessServiceBinding" name="PolicyQuoteProcessServicePort">

                        <soap:address location="http://localhost:8080/PolicyQuoteProcessServiceService/PolicyQuoteProcessServicePort"/>

                    </wsdl:port>

                    <wsdl:port binding="pps:DrivingRecordCallbackServiceBinding" name="DrivingRecordCallbackServicePort">

                        <soap:address location="http://localhost:8080/PolicyQuoteProcessServiceService/DrivingRecordCallbackServicePort"/>

                    </wsdl:port>

                </wsdl:service>

             

            and my Java interface looks like

             

            public interface PolicyQuoteProcessService {

               

                public Policy receivePolicyQuote(Policy policy);

               

                public DrivingRecordResponseType receiveDrivingRecord(DrivingRecordRequestType receiveDrivingRecordRequest);

             

            }

             

            how do I map receiveDrivingRecord to

             

                 <action eventType="myEvent" name="signal" type="SIGNAL_EVENT"/>

             

            and populate the eventData and signalRef?

             

            And how would I map the business date in the DrivingRecordRequestType (i.e. SSN) to the processInstanceId? It seems like I would need a custom correlation table and someway to access it before the processInstance is signaled.

            • 4. Re: How to implement Asychronous services in a jBPM5 process
              Jeff DeLong Master

              Adding process diagram

               

              pqprocess1.png

               

              Note that the SY diagram does not show the DrivingRecordService (I will get around to that once I figure out how to implement the callback).

              • 5. Re: How to implement Asychronous services in a jBPM5 process
                David Ward Master

                Jeff,

                 

                First, a quick response to your last question regarding correlating application data (eg: SSN) to a processInstanceId.  This is not currently supported, but is being tracked by SWITCHYARD-325.  I had been hoping that jBPM would provide this functionality for us, per JBPM-3512, but it looks like they've pushed that out to jBPM 6.x...

                 

                Now, a somewhat longer response to what you can do now for your application:

                 

                • When you start your process (actually, any interaction with a service whose implementation is bpm), the processInstanceId will be put into the Switchyard Context at Scope.EXCHANGE, and will be fed back to your client as a soap header in the soap response envelope.  So, like this:

                          <soap:Header><bpm:processInstanceId xmlns:bpm="urn:switchyard-component-bpm:process:1.0">1</bpm:processInstanceId></soap:Header>

                       This is obviously not part of your wsdl2java payload types, so you will have to access them using soap apis.

                 

                • Any other subsequent interaction that you have with your process will have to include that same soap header in your soap request envelopes so that they get correlated back to the correct process instance.  Once again, adding soap headers will require using soap apis, or direct modification of the request envelope xml.  If you have a suggestion on how you would rather see this done (some other way of correlation other than using soap headers, I would of course listen.)

                 

                • To populate the event data (the event object itself), you have two options: Another soap header, or the content of the message (the single object passed into the method marked as SIGNAL_EVENT).  The prior takes precedence, but falls back to the latter, which I'm assuming for most people is desireable:
                  1. <soap:Header><bpm:processEvent xmlns:bpm="urn:switchyard-component-bpm:process:1.0">Your event data, only possible to be a String.</bpm:processEvent></soap:Header>
                  2. @SignalEvent("signalId") public void signalEvent(MyEventData myEventData);

                 

                • When you said "signalRef" above, I think you meant the signal id.  There's a lexical discrepancy between jBPM and BPMN2.  What jBPM calls an "event type" in their API, BPMN2 calls a "signal id".  They are the same thing, and what I believe you mean by "signalRef".  If you look at #2 in the above bullet, this is passed as the value to the @SignalEvent annotation.  In switchyard xml, this would be the <action eventType="signalId"/>
                  • NOTE 1: In BPMN2, when you define a signal, it looks like this: <signal id="4" name="mysignal"/>. Unfortunately, jBPM does not recognize the signal name.  It only recognizes the signal id. Thus, I have found I have to hand-edit the generated BPMN file (created using the Eclipse BPMN2 Modeler) and change the signal id to my desired String name, vs. the number that the editor initially assigns it.
                  • NOTE 2: I have only tested SwitchYard with "Event Definitions" associated with signals, not "Message Definitions".  I honestly need to read-up more on the distinction.

                 

                I hope the above helps.  I look forward to your feedback for future enhancements!

                 

                Sincerely,

                David

                • 6. Re: How to implement Asychronous services in a jBPM5 process
                  David Ward Master

                  Hmmm... Kinda hacky, but you do have an option in getting the processInstanceId put INTO your message payload (content) object, in either direction: Write your own custom context mapper.

                   

                  So, for your <binding.soap>, specifcy your own <soap:contextMapper class="com.foo.MyCustomSOAPContextMapper"/>.  In that custom context mapper, you have full access to the Context and the SOAPMessage.  So you would be using SOAP APIs and XML manipulation at this point, but you could use this to inject/extract the processInstanceId to/from your payload data in your request/response, by moving it from/to the Context object.

                   

                  Just a server-side option so you don't have to use SOAP APIs on the client-side to manipulate the SOAP headers.

                  • 7. Re: How to implement Asychronous services in a jBPM5 process
                    Jeff DeLong Master

                    Thanks for the pointers, I will keep working on this and see if I can get it to work. In the meantime I have a couple Visual Editor quirks to note:

                     

                    1) TransformType

                     

                    I hande edited the following on the type=

                     

                      <transforms>

                        <transform:transform.smooks from="{http://www.example.org/policyQuote}policyQuote" to="java:org.acme.insurance.Policy" type="XML2JAVA" config="smooks/PolicyQuoteConfigSmooks.xml"/>

                        <transform:transform.smooks from="java:org.acme.insurance.Policy" to="{http://www.example.org/policyQuote}policyQuoteReply" config="smooks/PolicyQuoteReplyConfigSmooks.xml"/>

                        <transform:transform.jaxb from="{http://dmv.com/drivingRecord}drivingRecordResponse" to="java:dmv.com.DrivingRecordRequestType"/>

                      </transforms>

                     

                     

                    I keep adding the type="SMOOKS" to the second transform (which used a FTL transform), but it dissappears and then the XML shows an error about type missing. Type in the Transforms List show Smooks in obth cases, however one of them should say XML2JAVA.

                     

                    tranforms.png

                     

                     

                    2) Can't move serfvice and reference icons on the Component to line them up in the order I want:

                     

                    pqpservref.png

                     

                    3) Process Actions Event Type - I enter it in the Visual Editor

                     

                     

                    ProcessActions.png

                     

                     

                    but it does not show up in the xml

                     

                    <bpm:action name="receivePolicyQuote" eventType=""/>

                     

                    and XML validator complains.

                    • 8. Re: How to implement Asychronous services in a jBPM5 process
                      David Ward Master

                      I'll hafta let our tooling guys respond to that one.

                       

                      One thing I forgot to mention about the stuff above, though, is that the behavior I described is in 0.6.0.Beta2 - which just recently got released.  Especially the part about the event object being the message content.

                      • 10. Re: How to implement Asychronous services in a jBPM5 process
                        Jeff DeLong Master

                        The updated document helps, thanks.

                         

                        So above you said

                         

                        the processInstanceId will be put into the Switchyard Context at Scope.EXCHANGE, and will be fed back to your client as a soap header in the soap response envelope.  So, like this:

                                  <soap:Header><bpm:processInstanceId xmlns:bpm="urn:switchyard-component-bpm:process:1.0">1</bpm:processInstanceId></soap:Header>

                         

                        That works for some processes, e.g. the client send in a purchaseRequest and then a cancelPurchase, but many other processes the correlation id needs to be used in a subsequent invocation to an async service, which then uses the correlation id in a callback. (Never mind for now that sending correlation ids in headers may not be handled by an external service). So the id needs to be put in subsequent service calls. In my example it is the next service in the process, so I suspect I can get to Scope.Exchange. Not sure how this should work when the async service is later in the process?

                         

                        Another comment on this is that it seems like this id should use the ws-addressing correlationid (this is the standard way to do this).

                        • 11. Re: How to implement Asychronous services in a jBPM5 process
                          Brian Fitzpatrick Expert

                          Hey Jeff, I'm able to add properties to a bpm implementation just fine using the Actions table. Adding your two, I get:

                           

                                  <bpm:action name="receiveDrivingRecord" type="SIGNAL_EVENT" eventType="DrivingRecordCallbackSignalRef"/>

                                  <bpm:action name="receivePolicyQuote"/>

                           

                          In the source xml when I save the file. I can even edit them fine once they're added.

                           

                          What platform are you on? What exact steps are you doing? Can you record a screencast showing me the steps? I'm just trying to repro and not having any luck.

                           

                          --Fitz

                          • 12. Re: How to implement Asychronous services in a jBPM5 process
                            David Ward Master

                            Is this asnyc service you are talking about running in process instance 2, that needs to singal an event in process instance 1?  If that is the case, I can see how you would have to "carry around" a separate correlation id.  If that's the case, we don't have anything for that yet, and it would have to be handled by the application.

                             

                            I will read up on ws-addressing correlationid, however it might be beneficial at this point for you and I to have a phone/skype/g+hangout/etc. conversation so I fully understand what you are looking for.  Send me an email and we'll work out a day/time.  Whatever we come up with, I will echo it back as a public discussion thread so that the community can have a chance to add input.  Thanks!

                            • 13. Re: How to implement Asychronous services in a jBPM5 process
                              Brian Fitzpatrick Expert

                              Re-ordering the reference nubs on a component would be a nice feature. Can you create a feature request for that? It's something we can look at for 0.7.

                              • 14. Re: How to implement Asychronous services in a jBPM5 process
                                Jeff DeLong Master

                                The process invokes an asychronous service, meaning the response from the service back to the process will come later in time. in BPMN this is like a Send Task followed by a Receive Task. Or in a BPEL process this is a one-way Invoke followed by a Receive. But yeah let's talk on google chat..

                                1 2 Previous Next