12 Replies Latest reply on Sep 9, 2010 5:00 AM by h.wolffenbuttel

    Redelivery - config and trigger in custom action?

      Hello,

       

      I'm trying to build a prototype using JBoss ESB which will attempt to deliver messages to a Google Search Appliance.  HttpRouter (the new http-client version) is used to deliver the message payload to the GSA.

       

      This works well to deliver the message, but I need to ensure that any error responses cause the message to be redelivered at a later time (and once that's working I will want to fire off alerts and so on).  I'm not really sure how this can be achieved in JBoss ESB and I can't find anything relevant in the developer guide.

       

      As a first attempt I've created a custom action and configured it post-HttpRouter.  The custom action checks the response code and throws an ActionProcessingException if it's not 200:

       

              if (code != 200) {
                  throw new ActionProcessingException("Received non-200 response code from HttpRouter");
              }
      

       

      This is definitely throwing but doesn't seem to achieve much (at least, nothing I can observe).  How do I tell the ESB to put messages back in a queue?

       

      Cheers

      Steve

        • 1. Re: Redelivery - config and trigger in custom action?
          asankha

          This maybe helpful [http://bit.ly/azLhUs] if you are reading - say from JMS and posting to REST and want to revert and retry again on failure.

          • 2. Re: Redelivery - config and trigger in custom action?
            h.wolffenbuttel

            Hi,

             

            I have the same problem with developing a sollution which ensures delivery. The only way to ensure that an unwanted answer is followed with a redelivery is to throw an IllegalStateException as far as I know. So that means you have to extend the HttpRouter and implement the process method. I rather would implement an exception which is caught on  the pipeline and persists the message to be picked up at a later moment. The problem is that I need to be sure that no other messages are send in the meantime because i need to preserve the sequence it was send in.

             

            Here an implementation I have made for the time being:

             

            {code:java}

            @Override

              public Message process(Message message) throws ActionProcessingException {

                Message returnMessage = null;   

                boolean redeliver = false;

                returnMessage = super.process(message);

                try {

                  // body ophalen voor het antwoord

                  String returnMessageBody = returnMessage.getBody().get().toString();

                  Object bericht = ESBUtil.getBericht(returnMessageBody, true);

                  if( bericht instanceof BevestigingsBericht ){

                   ...

                  }

                  else if( bericht instanceof SynchroonAntwoordBericht ){

                    ...

                  }

                  else if( bericht instanceof AsynchroonAntwoordBericht ){

                   ...

                  }

                  else if( bericht instanceof FoutBericht ){

                   ...

                  }

                }

                catch (ClassCastException e) {

                  redeliver = true;

                }

                catch (JAXBException e) {

                  redeliver = true;

                }

                if(redeliver){

                  throw new IllegalStateException( "Redeliver message!");

                }

                return returnMessage;

              }

             

            {code}

             

            I know this is not the way and needs to be changed, but therefor I need to know how to block the message stream. I could imagine that there would be an action before the router which checkes a certain queue by using the messagestore class and persists every message until the queue is empty again. There would have to be a task listening on the queue which will try to resend the messages with intervals.

             

            Another option would be to implement a stop in the messagerouter, so it can send the messages to service which will persist the message to a queue. This way the service to send the message to an external endpoint would not be busy and can be used to resend the failed message(s).

             

            So those are my thoughts about redelivery.

             

            regards,

             

            Hans

            • 3. Re: Redelivery - config and trigger in custom action?

              Thanks for the reply Asankha... though it appears to relate to UltraESB.  There was also a link to a quite relevant JBoss SOA Platform article though: http://soa.dzone.com/articles/jms-transactions-soa-platform.

               

              I'm still working through this and have gotten a little further by using the jms-jca-provider, but I'm finding some issues with some element of the the redelivery (ServiceInvoker logs "Unresponsive EPR: JMSEpr").  I will try to nail down the issue so I can post an example config.

              • 4. Re: Redelivery - config and trigger in custom action?

                Thanks Hans... at this stage I am now able to signal the failure, using ActionProcessingFaultException instead.  From my reading of the javadoc this would seem to be the right exception for the type of fault I am representing; it also seems to have the desired effect, though I am hitting a different issue now (see my other reply to Asankha).

                 

                For what it sounds like you are doing (I had a bit of trouble understanding the code) you may want to add an action following the HttpRouter, rather than extend it.  I am using something like the following - please let me know if I've misunderstood, perhaps it has something to do with my other issue...

                 

                ...
                import org.jboss.soa.esb.http.HttpResponse;
                
                public class HttpResponseProcessor extends AbstractActionPipelineProcessor {
                 
                
                    public Message process(Message message) throws ActionProcessingException {
                        HttpResponse responseInfo = HttpResponse.getResponse(message);
                        
                        int code = responseInfo.getResponseCode();
                
                        if (code != 200) {  // Add your own error detection logic here
                            throw new ActionProcessingFaultException("Received non-200 response code from HttpRouter");
                        }
                
                        return message;
                    }
                }
                

                 

                Cheers
                Steve

                • 5. Re: Redelivery - config and trigger in custom action?
                  h.wolffenbuttel

                  Hi Steve,

                   

                  The reason I need to override the HttpRouter is because the message I'm recieving has a Soap-envelope which has to be stripped when a reply needs to be send back because it's RequestResponse. If I don't override I have two envelope's instead of one in my message. However you are correct that I can make a seperate action to process the response.

                   

                  The unresponsive EPR problem might come from the fact that you have another queue listening for the response of your message. Look at the  method "private Message post(Message message, EPRInvoker eprInvoker) throws MessageDeliverException, FaultMessageException' within the ServiceInvoker.class. There you will see that if there is no reply message returned, you will get the message "logger.info("Unresponsive EPR: " + epr+" for message: "+message.getHeader());". Unless your replymessage is a fault (when you do have a reply message), your message will be considered to be delivered succesfull.

                   

                  Regards,

                   

                  Hans

                  • 6. Re: Redelivery - config and trigger in custom action?
                    kconner

                    Thanks for the reply Asankha... though it appears to relate to UltraESB

                    Unfortunately this is not surprising as he is the CTO of the company pushing it.

                    • 7. Re: Redelivery - config and trigger in custom action?
                      kconner

                      It you are using a transactional context then the pipeline will roll the encompassing transaction back if you throw a runtime exception from the action.  Any checked exception is assumed to be an application exception which would be returned to the caller.

                       

                      By default the redelivery would happen immediately though, which I suspect is not what you want.  You would therefore need to use the jms-jca-provider and configure delayed redelivery.

                       

                      Kev

                      • 8. Re: Redelivery - config and trigger in custom action?
                        kconner

                        Or, alternatively, look at driving this through a processing enging such as jBPM or riftsaw.

                         

                        Kev

                        • 9. Re: Redelivery - config and trigger in custom action?
                          h.wolffenbuttel

                          Hi Kevin,

                           

                          Do you have an example of delayed delivery? I would like to implement a certain logic to the redelivery like incremental waiting time, but also be able to pull the message of the queue if it is causing the delivery to fail for whatever reason. Is this possible, and if so, where do I need to search for such functionality?

                           

                          Regards

                           

                          Hans

                          • 10. Re: Redelivery - config and trigger in custom action?
                            kconner

                            The functionality is specific to the JCA adapter being used so it depends on which one you are using.

                             

                            Which server and adapter are you using?

                             

                            Kev

                            • 11. Re: Redelivery - config and trigger in custom action?
                              h.wolffenbuttel

                              Hi Kevin,

                               

                              I am using the JBoss Esb Server 4.8 and the jms-jca-provider with connection-factory="XAConnectionFactory".

                               

                              Regards,

                               

                              Hans

                               

                              btw: is there an (easy) way to get messages from the deadletter-queue back on to the queue they came originally from? Maybe with a scheduler on Jboss so I have an extra way to delay the message sending.

                              • 12. Re: Redelivery - config and trigger in custom action?
                                h.wolffenbuttel

                                Hi Kevin, any idea yet?