1 2 Previous Next 16 Replies Latest reply on Jun 25, 2013 10:51 AM by dustin.barlow

    How to create a Switchyard SIGNAL_EVENT from a jUnit test?

    dustin.barlow

      When testing a switchyard BPMN process, I am easily able to invoke BPMN START_PROCESS type actions using the built in Switchyard unit testing capability (which is great btw!).

       

      @ServiceOperation("AsyncSignalEvent")
      private Invoker service;
      ...
      
      Object result = service.operation("startProcess").sendInOut(message).getContent();
      

       

      However, I have not been able to figure out how to setup a similar unit test for any of the BPMN SIGNAL_EVENT type actions.

       

      In searching the online Switchyard docs, I found that if I promote the Switchyard BPMN service, bind it to a SOAP interface, and add the following to the SOAP header...

       

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


      ... I was able to successfully test my BPMN SIGNAL_EVENT.

       

      How can I replicate this same thing in just a unit test?

        • 1. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
          dward

          This all has to do with correlation.  Your first invocation starts a new process.  The sequence-generated bpm:processInstanceId will get returned in the response headers so that in future invocations, the same id can be sent back in as a request header so that the same process instance is correlated with your signal event.

           

          Up until recently, this was the only correlation mechanism available.  However, in 0.8 (what you're using), you can also make use of specifying your own business key when you start a process, and just keep sending in that same business key for any future interactions with the same process instance.  Then you can ignore the processInstanceId.  The responsibility of making sure business keys is unique is on YOU now, however.

           

          To do this, send in a bpm:correlationKey request header with your start process, with any value that you want, and send that same value in with any subsequent signal event or abort process instance requests.  If you're going to do this to the same instance of jbpm across multiple junit tests, you'll want to somehow make sure that each test uses it's own correlation key.  You can probably use the java.util.UUID class for this.

          • 2. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
            dustin.barlow

            Two follow up questions:

             

            First, how do I send in the bpm:correlationKey as a request header using the Invoker service API?  I looked around the Invoker service functions and didn't see anything obvious.  If you have an example or a link to online docs, I would appreciate it.

             

            Second, as far as service scoping is concerned, I assume that in order to test a signal I first have to invoke the START_PROCESS so there is at least an existing instance and then send the signal request all WITHIN the same unit test method?

             

            David Ward wrote:

             

            ...

             

            To do this, send in a bpm:correlationKey request header with your start process, with any value that you want, and send that same value in with any subsequent signal event or abort process instance requests.  If you're going to do this to the same instance of jbpm across multiple junit tests, you'll want to somehow make sure that each test uses it's own correlation key.  You can probably use the java.util.UUID class for this.

            • 3. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
              dward

              First, how do I send in the bpm:correlationKey as a request header using the Invoker service API?  I looked around the Invoker service functions and didn't see anything obvious.  If you have an example or a link to online docs, I would appreciate it.

               

              Request headers are analagous to context propeties.  Try something like this:

               

                      Exchange e = _myInvoker.operation("myOperation").createExchange(handler);

                      Message m = e.createMessage().setContent("myContent");

                      m.getContext().setProperty("{urn:switchyard-component-bpm:bpm:1.0}correlationKey", "myUniquePerTestBizKey");

               

              Second, as far as service scoping is concerned, I assume that in order to test a signal I first have to invoke the START_PROCESS so there is at least an existing instance and then send the signal request all WITHIN the same unit test method?

               

              Yes.  In both invocations (the start process and the signal event), send in the SAME context property name+value.

              • 4. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                dward

                Well I guess technically it doesn't have to be within the same unit test method, unless that unit test bootstraps the whole runtime up+down each time.  The important part is that a process instance was already started - and exists - with the same correlation key that you're gonna send in again when you signal event.

                • 5. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                  dustin.barlow

                  I'm honestly not sure if the unit test bootstraps the whole run-time up and down each time a test method is invoked since I'm using the injected service.

                   

                   

                  package com.example.switchyard;
                    
                  import org.junit.Test;
                  import org.junit.runner.RunWith;
                  import org.switchyard.component.test.mixins.cdi.CDIMixIn;
                  import org.switchyard.test.Invoker;
                  import org.switchyard.test.ServiceOperation;
                  import org.switchyard.test.SwitchYardRunner;
                  import org.switchyard.test.SwitchYardTestCaseConfig;
                  
                  @RunWith(SwitchYardRunner.class)
                  @SwitchYardTestCaseConfig(mixins = CDIMixIn.class, config = SwitchYardTestCaseConfig.SWITCHYARD_XML)
                  public class AsyncSignalEventTest {
                  
                  
                            @ServiceOperation("AsyncSignalEvent")
                            private Invoker service;
                  
                  
                            @Test
                            public void testStartProcess() throws Exception {
                                      ProcessInfo message = new ProcessInfo();
                                      message.setGuid("SOMEGUID1234");
                                      message.setJobId("JobID999");
                                      message.setJobName("Some Job Name");
                                      message.setUserId("bob@bob.com");
                                      RequestAck result = service.operation("startProcess").sendInOut(message)
                                                          .getContent(RequestAck.class);
                  
                                      // validate the results
                                         Assert.assertTrue(result.getStatus())
                            }
                    
                            @Test
                            public void testUpdateTask() throws Exception {
                  
                                      TaskInfo message = new TaskInfo();
                                      message.setGuid("SOMEGUID1234");
                                      message.setWorkItemId(1);
                                      RequestAck result = service.operation("updateTask").sendInOut(message)
                                                          .getContent(RequestAck.class);
                  
                                      // validate the results
                                         Assert.assertTrue(result.getStatus())
                            }
                   }
                  
                  

                   

                  Am I correct that the Invoker service injected into the unit test survives the entire lifecycle of the class instance?  In other words, the Switchyard runtime is bootstrapped when an instance of the AsyncSignalEventTest class is created and then torn down when the class goes out of scope?

                  • 6. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                    dward

                    Depends on the lifecycle rules of @RunWith, which honestly I'm forgetting right now.  However...

                     

                    Put this line in each of your @Test methods to find out:

                     

                    System.out.println("**** service invoker: " + System.identityHashCode(service) + " ****");

                     

                    If it's the same in both test methods, it was only injected once per test class.

                    • 7. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                      dustin.barlow

                      Looks like it is a different instance per unit test method invoked:

                       

                      **** testStartProcess:  service invoker: 1465804433 ****
                      **** testUpdateTask: service invoker: 1956433926 ****
                      

                       

                      So I'll have to do both the START_PROCESS and SIGNAL_EVENT service calls within the same method in order to ensure a BPMN process instance exists.

                      • 8. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                        edevera

                        Apparently the feature David is referring to will be released as part of 1.0 if I have understood correctly the following ticket: https://issues.jboss.org/browse/SWITCHYARD-325

                        • 9. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                          dward

                          That is correct, Eduardo.

                          • 10. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                            dustin.barlow

                            Will there also be better support for setting the correlationId on the Invoker?

                             

                            Right now, I have to do something like this...

                             

                             

                            import org.switchyard.Exchange;
                            import org.switchyard.Message;
                            
                            ...
                            
                            TestExchangeHandler exchangeHandler = new TestExchangeHandler();
                            Exchange e = service.operation("updateTask").createExchange(exchangeHandler);
                            Message m = e.createMessage().setContent(taskInfo);
                            e.getContext().setProperty("{urn:switchyard-component-bpm:bpm:1.0}correlationKey", "2");
                            e.send(m);
                            
                            
                            // TestExchangeHandler Class
                            
                            import org.switchyard.Exchange;
                            import org.switchyard.ExchangeHandler;
                            import org.switchyard.HandlerException;
                            
                            public class TestExchangeHandler implements ExchangeHandler {
                            
                                       /* (non-Javadoc)
                                       * @see org.switchyard.ExchangeHandler#handleMessage(org.switchyard.Exchange)
                                       */
                                      @Override
                                      public void handleMessage(Exchange exchange) throws HandlerException {}
                            
                            
                                      /* (non-Javadoc)
                                       * @see org.switchyard.ExchangeHandler#handleFault(org.switchyard.Exchange)
                                       */
                                      @Override
                                      public void handleFault(Exchange exchange) {}
                            }
                            
                            

                             

                            The above code does not return the response from the service.  I did look into the Invoker code to see how it handled returned content and found that I would need to register some type of result handler callback thing.  I decided to punt at that point.

                             

                            It would be nice if I could just do something like this:

                             

                             

                            @ServiceOperation("SomeProcess")
                            private Invoker service;
                            
                            service.operation("startProcess").setProperty("{urn:switchyard-component-bpm:bpm:1.0}correlationKey", "myUniquePerTestBizKey");
                            RequestAck result = service.operation("startProcess").sendInOut(message).getContent(RequestAck.class);
                            
                            
                            • 11. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                              dward

                              This really has nothing to do with our BPM component, or corelation keys.  This has to do with desiring a fluent API to set context properties using our testcase ServiceInvoker stuff.  Agreed?

                              • 12. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                                dustin.barlow

                                I suppose you're technically correct given what I understand.  However, I don't know of anything else in SY aside from BPM that at its core needs context properties passed in from the caller in order to function propertly.  So while it isn't directly related, having a fluent/clear/clean API certainly is desirable for unit testing BPM processes. 

                                 

                                I spent a long time trying to figure out what on the surface seems to be a pretty simple concept of setting a property on a message.  The API made it difficult to intuatively understand where to set it.  Had you not given me some hints above, I don't think I would have ever figured it out just based on the documentation or the API JavaDocs.

                                 

                                I can certainly post the request in another forum topic or as a feature enhancement request in Jira if that would be more helpful.  I suspect this will be a very common use case for others as well.

                                • 13. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                                  dward

                                  I suppose you're technically correct given what I understand.  However, I don't know of anything else in SY aside from BPM that at its core needs context properties passed in from the caller in order to function propertly

                                   

                                  Both the BPM and Rules components can be stateful.  I don't know of any other SwitchYard comopnents that are like that, at least off the top of my head.

                                   

                                  Had you not given me some hints above, I don't think I would have ever figured it out just based on the documentation or the API JavaDocs.

                                  Documentation is due for a major revamp.  It's on my plate.

                                   

                                   

                                  I can certainly post the request in another forum topic or as a feature enhancement request in Jira if that would be more helpful.

                                   

                                  I think a feature request jira is the best place to start.  You don't have to create a new forum topic, but please do link from the jira to the anchor of the first related comment in this thread.  Thank you!!!

                                  • 14. Re: How to create a Switchyard SIGNAL_EVENT from a jUnit test?
                                    dustin.barlow

                                    It appears a ticket already exists for enhancing the ServiceInvoker https://issues.jboss.org/browse/SWITCHYARD-923.  Doesn't look like there has been any activity on it for about a year though.

                                    1 2 Previous Next