Search code examples
javaspringcxf-client

Spring - Retry request if service returns 409 HTTP Code


I have an Spring + CXF application which consumes a Transmission API: Transmission RPC running in another server.

According to Transmission docs, you need to send a token which is generated on the first request. The server then responds with a 409 http code along with a header containing the token. This token should be sent on all subsequent calls:

2.3.1. CSRF Protection Most Transmission RPC servers require a X-Transmission-Session-Id header to be sent with requests, to prevent CSRF attacks. When your request has the wrong id -- such as when you send your first request, or when the server expires the CSRF token -- the Transmission RPC server will return an HTTP 409 error with the right X-Transmission-Session-Id in its own headers. So, the correct way to handle a 409 response is to update your X-Transmission-Session-Id and to resend the previous request.

I was looking for solution either using a CXF filter or interceptor, that basically will handle the 409 response and retry the initial request adding the token header. I'm thinking that clients can persist this token and send it in future calls.

I'm not very familiar with cxf so I was wondering if this can be accomplish and how. Any hint would be helpful.

Thanks!


Solution

  • Here spring-retry can be utilized which is now an independent project and no longer part of spring-batch.

    As explained here retry callback will help make another call updated with the token header.

    Pseudo code / logic in this case would look something like below

    RetryTemplate template = new RetryTemplate();
    Foo foo = template.execute(new RetryCallback<Foo>() {
        public Foo doWithRetry(RetryContext context) {
            /* 
             * 1. Check if RetryContext contains the token via hasAttribute. If available set the header else proceed
             * 2. Call the transmission API 
             * 3.a. If API responds with 409, read the token 
             *    3.a.1. Store the token in RetryContext via setAttribute method
             *    3.a.2. Throw a custom exception so that retry kicks in
             * 3.b. If API response is non 409 handle according to business logic
             * 4. Return result
             */
        }
    });
    

    Make sure to configure the RetryTemplate with reasonable retry & backoff policies so as to avoid any resource contention / surprises.

    Let know in comments in case of any queries / roadblock.

    N.B.: RetryContext's implementation RetryContextSupport has the hasAttribute & setAttribute method inherited from Spring core AttributeAccessor