1 2 Previous Next 16 Replies Latest reply on Oct 15, 2007 1:28 PM by Mark Little

    Exceptionhandling and controlling the flow

    Haagen Hasle Novice

      Hi!

      When I'm coding my actions, I would sometimes like to be able to have different actions or services be set as the "next step" in my process-flow, depending on what is done in my action. For example, if a call to a remote webservice return a different result than I expected, I'd like to terminate the ordinary processflow, and return a response stating what happened.

      As far as I understand, I can terminate the flow by returning null as the message in my process-method, or by throwing an exception. However, these two options won't let me return a meaningful response (or, in fact, anything at all..) I guess I can use a contentbased router, but is that the only way?

      In the programmers guide I read about FaultTo-EPR, ReplyTo-EPR etc, but I haven't found an example that describes how to manipulate and use these. Am I supposed to (be able to) change them in my code, or is all of the flow supposed to be configured in jboss-esb.xml?

      I don't know how much sense I made in writing this, but I hope someone understand what I'm asking about and can give me a few hints and pointers in the right direction.

      Regards, Haagen

        • 1. Re: Exceptionhandling and controlling the flow
          Mark Little Master

          The action chaining concept is deliberately linear. For more complex task management you should consider using jBPM.

          In terms of different services to be invoked, you can always call services from within actions. If you need to send a message to a service as a result of an exceptional termination, then you can throw an ActionProcessingFaultException. All of this is explained in the Programmers Guide.

          • 2. Re: Exceptionhandling and controlling the flow
            Haagen Hasle Novice

             

            "mark.little@jboss.com" wrote:
            In terms of different services to be invoked, you can always call services from within actions. If you need to send a message to a service as a result of an exceptional termination, then you can throw an ActionProcessingFaultException. All of this is explained in the Programmers Guide.


            I've actually read the Programmers Guide, and I think it could have been explained just a little bit more in detail how this is done. :-) Do you know of any examples of how to call a service from within an action, and how to call a service by throwing an ActionProcessingFaultException? Is this done in any of the quickstarts?

            I've looked at the fields in the toEPR in one of my actions, and it looks to me that the addr (PortReference) of an EPR is a URI that looks something like "jms://localhost/queue/foobar". Am I supposed to set this to tell JBossESB which service to go to? (It seems somewhat "low-level" to me, I would have though I could use the names of the services instead.)


            Regards, Haagen

            • 3. Re: Exceptionhandling and controlling the flow
              Mark Little Master

               

              "haagenhasle" wrote:
              I've actually read the Programmers Guide, and I think it could have been explained just a little bit more in detail how this is done. :-)


              Want to lend a hand? ;-)

              Do you know of any examples of how to call a service from within an action,


              Use the ServiceInvoker.


              and how to call a service by throwing an ActionProcessingFaultException?


              I don't think any of the quickstarts do this but there are some unit tests that illustrate this. Check those out.


              Is this done in any of the quickstarts?

              I've looked at the fields in the toEPR in one of my actions, and it looks to me that the addr (PortReference) of an EPR is a URI that looks something like "jms://localhost/queue/foobar". Am I supposed to set this to tell JBossESB which service to go to? (It seems somewhat "low-level" to me, I would have though I could use the names of the services instead.)


              So it looks like the Programmers Guide section on EPRs and addresses doesn't cut it for you either then ;-)?

              Read the section on the ServiceInvoker. It will help you.

              • 4. Re: Exceptionhandling and controlling the flow
                Haagen Hasle Novice

                Hi!

                Thank you for helping me work this out, I appreciate it!

                You're right, the Programmers Guide doesn't quite cut it for me. I wouldn't mind contributing to it by writing some more examples, but to be able to do that I have to figure out how it all works first.. :-) I'm still struggling with this.

                I guess I can use the ServiceInvoker, I'm already familiar with it as I use it in my WebServices to call into the ESB. However I don't think the ServiceInvoker really does what I'm looking for. If I use the ServiceInvoker inside my actions, I would still have to return a response (a message) from within my process-method, won't I? I guess I should have phrased my question differently, what I want to do is to have different exit-points from my action, depending on the businesslogic I have in my Java-code. I don't want to call another action/service, but I want different actions/services to be the next step in the flow.

                Is it possible to use a contentbased router and still code in Java?

                I couldn't find any unit-tests that showed me how to use the ActionProcessingFaultException, do you know the name of the test? (I'm using JBossESB4.2MR3, but I'll upgrade if necessary.)


                Regards, Haagen

                • 5. Re: Exceptionhandling and controlling the flow
                  Mark Little Master

                   

                  "haagenhasle" wrote:
                  Hi!

                  Thank you for helping me work this out, I appreciate it!

                  You're right, the Programmers Guide doesn't quite cut it for me. I wouldn't mind contributing to it by writing some more examples, but to be able to do that I have to figure out how it all works first.. :-) I'm still struggling with this.


                  Once you're up to speed and ready to contribute, let me know. We'd be glad to accept any improvements you may have to offer.


                  I guess I can use the ServiceInvoker, I'm already familiar with it as I use it in my WebServices to call into the ESB. However I don't think the ServiceInvoker really does what I'm looking for. If I use the ServiceInvoker inside my actions, I would still have to return a response (a message) from within my process-method, won't I?


                  So now we're really getting into the optimum SOA design strategy, which is irrespective of the underlying technology. For a start, we'd always recommend that you only use request/response when strictly necessary. You can see that as Web Services have evolved, all of the specifications/standards and APIs have moved away from the original RPC-oriented architectural approach, to using one-way invocations that may be related at the higher level. JBossESB supports both one-way and request/response invocations, but one-ways (correlated where and how necessary) are the better option from a SOA perspective.

                  To answer you're specific implementation question, you'd only need to return a response from process if the service was invoked synchronously.

                  I guess I should have phrased my question differently, what I want to do is to have different exit-points from my action, depending on the businesslogic I have in my Java-code. I don't want to call another action/service, but I want different actions/services to be the next step in the flow.


                  As I said earlier then, the action pipeline within a service is deliberately linear.


                  Is it possible to use a contentbased router and still code in Java?


                  You could, but you be better off using jBPM.


                  I couldn't find any unit-tests that showed me how to use the ActionProcessingFaultException, do you know the name of the test? (I'm using JBossESB4.2MR3, but I'll upgrade if necessary.)


                  You're right, I was thinking about something else. But the concept is pretty easy: throw the exception from within your process method and you can add a specific Message (should be a Fault Message) and set up the header to make it go to the place/service you want. If you don't play with the header, then JBossESB will infer information from the original input Message that triggered the process execution.

                  • 6. Re: Exceptionhandling and controlling the flow
                    Haagen Hasle Novice

                    I think that RPC-style is necessary in my case, I'm providing a "merged view" of two external webservices, and both of them are two-ways.

                    Are there any examples of how I can code CBR in Java? I'll look more deeply into jBPM too, I've only briefly looked at it before. It might very well be what I'm looking for.

                    I've tried using the FaultException, and it kind of worked when I inserted the message I got as a parameter in the process-method into the constructor. I say "kind of worked", because that message only made it continue it's regular path to the next action. I understand that I need to create a new message, and create an EPR that I can use to set "msg.getHeader().getCall().setFaultTo(epr)". But I haven't figured out how to create this EPR. In the unittests I found the JMSEpr, but I haven't found any examples of how to use it.
                    Can you help me fill in the blanks in this code? (And, if I'm doing it wrong, please correct me..)

                    EPR epr = new JMSEpr(JMSEpr.QUEUE_TYPE, XXXX, XXXX );
                    PortReference portReference = new PortReference();
                    portReference.setAddress("jms://localhost/queue/name_of_jms_queue");
                    epr.setAddr(portReference);
                    msg.getHeader().getCall().setFaultTo(epr);
                    throw new ActionProcessingFaultException(msg, "A description");


                    Regards, Haagen


                    • 7. Re: Exceptionhandling and controlling the flow
                      Haagen Hasle Novice

                      I still haven't found any examples of how I should create an EPR, so I tried the following code instead:

                      faultTo = new EPR();
                      faultTo.copy(replyTo);
                      faultTo.getAddr().setAddress("jms://localhost/queue/where_i_want_to_go");
                      msg.getHeader().getCall().setFaultTo(faultTo);
                      throw new ActionProcessingFaultException(msg, "some text");

                      The Service (let's call it ExceptionService) I set the faultTo-address to was a simple Service that merely wrote out some text using the org.jboss.soa.esb.actions.SystemPrintln. However, what I experienced doing it this way was that I got trapped inside the ExceptionService in an infinite loop, because the EPR.copy-method actually just assign the same PortReference to the faultTo as it finds in the replyTo. So faultTo.getAddr().setAddress() changes the address in replyTo as well!

                      I have to admin that's not what I expected from a copy-method.

                      I guess what this shows me is that I'm not doing this the way it's supposed to be done..


                      • 8. Re: Exceptionhandling and controlling the flow
                        Kevin Conner Master

                        There is a JIRA issue which has just been raised to help with this. http://jira.jboss.com/jira/browse/JBESB-1161

                        We are hoping to have this is shortly.

                        I'll raise an issue over the copy method as it sounds as if it is doing shallow copies instead of deep ones.

                        • 10. Re: Exceptionhandling and controlling the flow
                          Haagen Hasle Novice

                          The funniest part is that the infinite loop just keeps going and going, it even survices a shutdown of the appserver and a redeploy of the application.. You have surely achieved reliable delivery of messages!

                          How do I stop this thing!? :-)

                          • 11. Re: Exceptionhandling and controlling the flow
                            Haagen Hasle Novice

                             

                            "Kevin.Conner@jboss.com" wrote:
                            Just raised the following JIRA <a href='http://jira.jboss.com/jira/browse/JBESB-1169'>http://jira.jboss.com/jira/browse/JBESB-1169</a>
                            There is a JIRA issue which has just been raised to help with this. http://jira.jboss.com/jira/browse/JBESB-1161


                            Great, that would help me a lot!


                            Regards, Haagen

                            • 12. Re: Exceptionhandling and controlling the flow
                              Kevin Conner Master

                               

                              "haagenhasle" wrote:
                              The funniest part is that the infinite loop just keeps going and going, it even survices a shutdown of the appserver and a redeploy of the application.. You have surely achieved reliable delivery of messages!

                              How do I stop this thing!? :-)

                              ROFL, sorry about this. If you can't delete the message from the queue then change your service to return null and let it drain the message queue.

                              • 13. Re: Exceptionhandling and controlling the flow
                                Haagen Hasle Novice

                                I read in the Programmers Guide that "if the system detects a Fault present on any Message during any stage of the Action processing, it will halt processing and send the Message".

                                I have the following code:

                                public class RaiseException extends AbstractActionPipelineProcessor {
                                
                                 protected ConfigTree _config;
                                
                                 /**
                                 *
                                 * @param config
                                 */
                                 public LagFeil(ConfigTree config) {
                                 _config = config;
                                 }
                                
                                 public Message process(Message msg) throws ActionProcessingException {
                                 try {
                                 msg.getFault().setCode(new URI("urn:action/error/myerror"));
                                 msg.getFault().setReason("I want to halt processing..");
                                 return msg;
                                 } catch (URISyntaxException e) {
                                 e.printStackTrace();
                                 return null;
                                 }
                                 }
                                }

                                This code has absolutely no effect. Am I doing anything wrong, or is this a bug in JBossESB?

                                Regards, Haagen

                                • 14. Re: Exceptionhandling and controlling the flow
                                  Kevin Conner Master

                                  The pipeline rules are as follows.

                                  If you return a message then it is used as the input for the next action or the eventual response if it is the final action in the pipeline.

                                  If you return a null then the pipeline processing terminates with the current action.

                                  If you throw an exception (ActionProcessingFaultException to include a response message) then it will return a fault at that point in the chain.

                                  Does this help?

                                  1 2 Previous Next