0

I'm working in a retry scenario (related to an http outbound gateway). The retry logic is working very well, but my logic to not retry looks like has a bug.

What I would like to do is to not retry if I get an http status error different to 404,500,503,504.

In order to test it, I have a configurable endpoint, which I can configure to response with any http status error for X times before getting a sucess.

So for example, I can configure my endpoint to get an http 400 status just the first time I hit it, and after that, when I retry, I'll get a sucessful response.

That said, what I was expecting is, when I configure my endpoint to get an http 400 status just the first time, is to never retry, but looks like that is not working.

The logic that I have for the the never retry scenario is this one:

   <int-http:outbound-gateway
            header-mapper="httpHeaderMapper"
            request-channel="some_request_channel"
            url-expression="'http://some_url"
            http-method="POST"
            expected-response-type="java.lang.String"
            charset="UTF-8"
            reply-timeout="${com.property.value.from.db.for.time.out:5000}"
            reply-channel="some_reply_channel">

            <int-http:request-handler-advice-chain>
                        <bean class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
                            <property name="recoveryCallback">
                                <bean class="org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer">
                                    <constructor-arg ref="errorChannel" />
                                </bean>
                            </property>
                            <property name="retryTemplate" ref="retryTemplate" />
                        </bean>
            </int-http:request-handler-advice-chain>

    </int-http:outbound-gateway>


    <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
        <property name="retryPolicy">
            <bean class="com.whatever.CustomRetryPolicy">
                <property name="maxAttempts" value="${com.property.value.from.db.for.retry.MaxAttemps:5}" />
            </bean>
        </property>
        <property name="backOffPolicy">
            <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
                <property name="initialInterval" value="${com.property.value.from.db.for.backoffpolicy.initialInterval:1000}" />
                <property name="multiplier" value="${com.property.value.from.db.for.backoffpolicy.initialInterval:6}" />
            </bean>
        </property>
    </bean> 

The CustomRetryPolicy is this:

public class CustomRetryPolicy extends ExceptionClassifierRetryPolicy {

    private String maxAttempts;

    @PostConstruct
    public void init() {

        final RetryPolicy defaultRetry = defaultRetryPolicy();
        this.setExceptionClassifier(new Classifier<Throwable, RetryPolicy>() {
            @Override
            public RetryPolicy classify(Throwable classifiable) {
                Throwable exceptionCause = classifiable.getCause();
                if (exceptionCause instanceof HttpStatusCodeException) {
                    int statusCode = ((HttpStatusCodeException) classifiable.getCause()).getStatusCode().value();
                    handleHttpErrorCode(statusCode);
                }
                return defaultRetry;
            }
        });
    }

    public void setMaxAttempts(String maxAttempts) {
        this.maxAttempts = maxAttempts;
    }


    private RetryPolicy handleHttpErrorCode(int statusCode) {
        RetryPolicy retryPolicy = null;
        switch(statusCode) {
        case 404 :
        case 500 :
        case 503 :
        case 504 :
            retryPolicy = defaultRetryPolicy();
            break;
        default :
            retryPolicy = neverRetry();
            break;
        }

        return retryPolicy;
    }

    private RetryPolicy neverRetry() {
        return new NeverRetryPolicy();
    }

    private RetryPolicy defaultRetryPolicy() {
        final SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
        simpleRetryPolicy.setMaxAttempts(5);
        return simpleRetryPolicy;
    }

}

According to the NeverRetryPolicy class, it should do this:

A RetryPolicy that allows the first attempt but never permits a retry. Also be used as a base class for other policies, e.g. for test purposes as a stub.

So my understanding is, the first attempt is when we hit the endpoint, we receive the http 400 error status, then never retry.

What's wrong with that?

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
Columb1a
  • 463
  • 2
  • 11
  • 25
  • Where are you calling `handleHttpErrorCode` from? And, what are you doing with the result? It looks strange to select the policy at runtime but I might be missing the bigger picture. Edit the question to add the calling code and your retry template setup. – Gary Russell May 23 '17 at 14:56
  • @GaryRussell question updated. – Columb1a May 23 '17 at 15:20

1 Answers1

3

You're always returning the default policy; looks like you need a return here...

return handleHttpErrorCode(statusCode);

By the way, it would be better to create the policies once, rather than creating a new one each time.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • You're right! , Also The code shouldn't return `defaultRetry` at the end. Instead of that, Instead of that, it should return `neverRetry()`, and with that, I can ensure that I won't retry If I get something different to `HttpStatusCodeException` – Columb1a May 23 '17 at 16:38