8 Replies Latest reply on Jan 9, 2008 1:33 PM by Kevin Conner

    Throwing exceptions from actions

    Vinicius Carvalho Apprentice

      Hello there. At the programmers guide page 38 states that

      "As mentioned earlier, a Fault Message may be returned
      within an ActionProcessingFaultException
      ",
      but on at page 36

      "Callback method for failure in each element: If an Exception
      occurs then the exceptionMethod notification will be called on all
      handlers from the current (faili ng) handler back to the initial handler.
      At present time, if no exceptionMethod was specified, the only output
      will be the logged error
      "

      This led me to a very confusing idea of how to handle exceptions inside my action pipeline.

      My first attempt was:

      public Message process(Message message) throws ActionProcessingFaultException {
       XMLValidator validator = new XMLValidator("CSM.xsd");
       Source xmlInput = new StreamSource(new StringReader(String.valueOf(message.getBody().get())));
       boolean valid = validator.validate(xmlInput);
       if(!valid){
       message.getBody().add(CSMConstants.BODY_ERROR_ENTRY,validator.getErrorList());
       throw new ActionProcessingFaultException(message,"Erro de validacao do conteudo da mensagem");
       }
       return message;
       }
      


      But this, as said on page 36 of the manual, only prints an error:

      15:11:33,137 WARN [ActionProcessingPipeline] Unexpected exception caught while processing the action pipeline: header: [ To: JMSEpr [ PortReference < <wsa:Address jms://localhost/queue/ESBChannel/>, <wsa:ReferenceProperties jbossesb:java.naming.factory.initial : org.jnp.interfaces.NamingContextFactory/>, <wsa:ReferenceProperties jbossesb:java.naming.provider.url : localhost/>, <wsa:ReferenceProperties jbossesb:destination-type : queue/>, <wsa:ReferenceProperties jbossesb:specification-version : 1.1/>, <wsa:ReferenceProperties jbossesb:connection-factory : ConnectionFactory/>, <wsa:ReferenceProperties jbossesb:persistent : true/>, <wsa:ReferenceProperties jbossesb:acknowledge-mode : 1/> > ] ReplyTo: JMSEpr [ PortReference < <wsa:Address jms://localhost/ESBChannel_reply/>, <wsa:ReferenceProperties jbossesb:destination-type : queue/>, <wsa:ReferenceProperties jbossesb:specification-version : 1.1/>, <wsa:ReferenceProperties jbossesb:connection-factory : ConnectionFactory/>, <wsa:ReferenceProperties jbossesb:persistent : true/>, <wsa:ReferenceProperties jbossesb:acknowledge-mode : 1/> > ] FaultTo: JMSEpr [ PortReference < <wsa:Address jms://localhost/ESBFaultChannel/>, <wsa:ReferenceProperties jbossesb:destination-type : queue/>, <wsa:ReferenceProperties jbossesb:specification-version : 1.1/>, <wsa:ReferenceProperties jbossesb:connection-factory : ConnectionFactory/>, <wsa:ReferenceProperties jbossesb:persistent : true/>, <wsa:ReferenceProperties jbossesb:acknowledge-mode : 1/> > ] MessageID: ID:JBM-33285 RelatesTo: jms:correlationID#ID:JBM-34816 ]
      org.jboss.soa.esb.actions.ActionProcessingFaultException: Erro de validacao do conteudo da mensagem
       at com.synos.csm.business.actions.CSMValidateAction.process(CSMValidateAction.java:33)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at org.jboss.soa.esb.listeners.message.ActionProcessorMethodInfo.processMethods(ActionProcessorMethodInfo.java:102)
       at org.jboss.soa.esb.listeners.message.OverriddenActionLifecycleProcessor.process(OverriddenActionLifecycleProcessor.java:74)
       at org.jboss.soa.esb.listeners.message.ActionProcessingPipeline.process(ActionProcessingPipeline.java:316)
       at org.jboss.soa.esb.listeners.message.MessageAwareListener$1.run(MessageAwareListener.java:303)
       at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
       at java.lang.Thread.run(Thread.java:595)
      


      I was expecting it to be redirected to the FaultTo EPR. Sorry but I really did not understand the programmers guide, if the ESB will redirect to FaultTo EPR on an exception or not.
      If it does not, what should be correct way to handle this?

      Best regards


        • 1. Re: Throwing exceptions from actions
          Vinicius Carvalho Apprentice

          I'm trying to understand how to deal with exceptions, so I'm checking the source for the ActionProcessingPipeline.
          I've found that when I throw an ActionProcessingFaultException the ESB tries to send it to the faultTo endpoint.
          But, since my FaultTo is empty, the DefaultFaultTo.initialiseReply returns false, and since I'm not using implicit processing, nothing happens.

          I think if I set a defaultFaultTo to all messages in my esb instance, I shall get things working.

          How can I do that? which property descriptor?

          Regards

          • 2. Re: Throwing exceptions from actions
            Kevin Conner Master

            The processing of the fault checks for faultTo, replyTo and from in that order. The first EPR discovered will be the one used as the target for the fault response.

            This usually means that the fault will be sent back to the caller of the service unless it has been explicitly overridden before sending the request.

            Kev

            • 3. Re: Throwing exceptions from actions
              Vinicius Carvalho Apprentice

               

              "Kevin.Conner@jboss.com" wrote:

              This usually means that the fault will be sent back to the caller of the service unless it has been explicitly overridden before sending the request.
              Kev


              Thanks, but how can I set a default faultTo to all messages on my ESB, is that possible? My first action of my action pipeline do change the faultTo property. But the class ActionProcessPipeLine on the process method, defines a callDetails:Call object that has the Call from the message created from the MessageComposer of the given listener for the service. At this point, the faultTo is empty :(. I believe the problem is that this class, checks for the correct fault using the callDetails object which has an empty faultTo EPR. please have a look at this snippet [lines 339-349 of ActionProcessPipeline]

               if (ex instanceof ActionProcessingFaultException)
               {
               ActionProcessingFaultException fault = (ActionProcessingFaultException) ex;
              
               if (fault.getFaultMessage() == null)
               {
               faultTo(callDetails, Factory.createErrorMessage(Factory.PROCESSING_ERROR, message, ex));
               }
               else
               faultTo(callDetails, fault.getFaultMessage());
               }
              


              My message is handled by the inner else of the first if statement. the method faultTo does not check if my message have a faultTo EPR, but instead, it checks the callDetails.


              I'm sorry, I just believe that the current message on the pipeline should be checked as well. Since it is not, how can I force the message that will be composed by my listener to have a default faultto?

              Regards

              • 4. Re: Throwing exceptions from actions
                Vinicius Carvalho Apprentice

                Just another thing that just came up.

                In this model, if I have let's say 10 actions in a service, and the 5th action
                changes the faultTo and the 7th throws an exception, the new faultTo will not be inspected.

                also, please note that I'm really enjoying JBoss ESB, keep the good work guys :) I'm just a dumb guy with lots of questions, sorry

                • 5. Re: Throwing exceptions from actions
                  Kevin Conner Master

                  The specification of the ReplyTo/FaultTo is the responsibility of the caller and not the active service. What is it that you are trying to achieve?

                  • 6. Re: Throwing exceptions from actions
                    Vinicius Carvalho Apprentice

                     

                    "Kevin.Conner@jboss.com" wrote:
                    The specification of the ReplyTo/FaultTo is the responsibility of the caller and not the active service. What is it that you are trying to achieve?



                    Kevin, my caller is an ESB unaware client. So it can not set those values :(. What I'm giving a try at this moment (just finishing coding) is having my own MessageComposer for my JMSListener. There I'm setting the reply-to and fault-to properties.

                    I just need to have a faultto set before the message arrives at the action pipeline processing, I guess now I finally found where to put this :)

                    I've used PackageJMSMessageContents as a startpoint to code my own MessageComposer.

                    Regards

                    • 7. Re: Throwing exceptions from actions
                      Vinicius Carvalho Apprentice

                      Well, so I created my own message composer. And using the config tree, now I can set the default reply/fault EPRs:

                      <jms-listener name="inboundListener" busidref="CSMGateway" is-gateway="true" maxThreads="1">
                       <property name="composer-class" value="com.synos.csm.esb.message.CSMMessageComposer"></property>
                       <property name="default-epr">
                       <fault-to dest-type="queue" dest-name="CSMFaultChannel"/>
                       <reply-to dest-type="queue" dest-name="ESBChannel_reply"/>
                       </property>
                       </jms-listener>
                      
                       ConfigTree[] replyTo = config.getChildren(CSMConstants.COMPOSER_DEFAULT_REPLY_TO);
                       ConfigTree[] faultTo = config.getChildren(CSMConstants.COMPOSER_DEFAULT_FAULT_TO);
                       if(replyTo != null && replyTo.length > 0){
                       esbMessage.getHeader().getCall().setReplyTo(new JMSEpr(replyTo[0].getAttribute("dest-type"),replyTo[0].getAttribute("dest-name"),"ConnectionFactory"));
                       }
                       if(faultTo != null && faultTo.length > 0){
                       esbMessage.getHeader().getCall().setFaultTo(new JMSEpr(faultTo[0].getAttribute("dest-type"),faultTo[0].getAttribute("dest-name"),"ConnectionFactory"));
                       }
                      


                      now I get my FaultService to be called when an exception is thrown from the action pipeline, the only problem is that is being called twice. The
                      first time it has both faultTo and To EPRs sets, second time only To is set. I'm debugging the application, and could not find at which point does the ESB sends this second message.

                      Best regards



                      • 8. Re: Throwing exceptions from actions
                        Kevin Conner Master

                         

                        "viniciuscarvalho" wrote:
                        now I get my FaultService to be called when an exception is thrown from the action pipeline, the only problem is that is being called twice. The
                        first time it has both faultTo and To EPRs sets, second time only To is set. I'm debugging the application, and could not find at which point does the ESB sends this second message.

                        The second one is likely to be the real fault message as the ReplyTo/FaultTo entries should be cleared when the pipeline relies/faults.

                        It sounds as if you may be sending a message somewhere in your pipeline.