Announcement Announcement Module
No announcement yet.
Retry around Serviceinvoker with SimpleRetryPolicy exception classification Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Retry around Serviceinvoker with SimpleRetryPolicy exception classification

    Hi All,

    I want to retry a method annotated with ServiceActivator when some specific exceptions are thrown.
    I've tried adding a RetryInterceptor to the message listener container advice chain, however the exception propgated from the service method is wrapped in a ListenerExecutionFailedException which renders the exception classification in SimpleRetryPolicy fairly useless.

    I saw some examples where the advice is put in a poller inside a service-activator element, but that didn't work for me (got an error about trying to use a poller with a subscribable channel).

    Am I missing something?


  • #2
    In 2.2, we have introduced the ability to apply a retry advice to individual components...

    Release candidate 2 (2.2.0.RC2) is available; the release should be available shortly.


    • #3
      Thanks, I saw indeed that it changed in 2.2, but I'm still using 2.1.
      For now I'm using RetryTemplate programmatically, and will eagerly await the 2.2 release.


      • #4
        RequestHandlerRetryAdvice wraps Exception in a MessagingException?

        I've just upgraded to 2.2.1 and trying to use RequestHandlerRetryAdvice.
        I've noticed that the RetryCallback that it creates catches any exception from the invoked service and wraps it in a MessagingException, again rendering my SimpleRetryPolicy exception check useless.

        Do I need to extend RequestHandlerRetryAdvice and override the invoke method?


        • #5

          What's problem to get cause in your RetryPolicy:
          public boolean canRetry(RetryContext context) {
                  Throwable t = context.getLastThrowable().getCause();



          • #6

            context.getLastThrowable() will return a MessagingException that wraps the actual exception (any exception) thrown by the business code. This makes using the default exception classifier in SimpleRetryPolicy impossible.

            Why does the RetryCallback created by RequestHandlerRetryAdvice wraps the actual exception with a MessagingException?



            • #7

              Thanks, now I see what you mean:
              1. Actual exception is wrapped to MessagingException, because we are in the Message Flow, and it is very useful to get info which incoming Message causes a problem and to do some Dead Lettering or recovering in the error flow with failedMessage.Or analyze it in the caller of message flow, if it is single-thread.
              2. From other side I agree: there is no reason to wrap original exception on each retry. We can do it (in the framework) after retry is exhausted and in the RecoveryCallback via
              (Message<?>) context.getAttribute("message");
              I think you are free to raise an imrovement issue: and we'll think of it more deeply.

              However, you always can write your own RetryPolicy implementation.


              P.S. In additions we need Gary Russell opinion here.


              • #8
                Thanks, I've created

                I think it's an oversight. At least make it configurable...


                • #9
                  Yes, we should at least provide a retry policy that understands MessagingExceptions.

                  We may also want to allow explicitly setting the exception list directly on RequestHandlerRetryAdvice to make confguration easier (rather than having to inject a custom RetryTemplate with a custom RetryPolicy.


                  • #10
                    As a workaround I extended SimpleRetryPolicy and overriden registerThrowable with an implementation that unwraps MessagingExceptions and then delegates to super:

                    public void registerThrowable(final RetryContext context, final Throwable throwable) {
                    	Throwable actualThrowable = throwable;
                    	while (actualThrowable instanceof MessagingException) {
                    		actualThrowable = actualThrowable.getCause();
                    	super.registerThrowable(context, actualThrowable);