Duck Tales: The Wonders of Integration

How I implemented the Integration with Third-Party Services using Request Interceptor and Spring Retry Template

Gene Zeiniss
Sep 28, 2020 · 7 min read
Carl Barks painting of Uncle Scrooge McDuck.

Disney’s Duck Tales was a classic cartoon series in the early 1990s, at the time when I grew up. If you watched it, you probably just said “Duck Tales… woohoo!” in your head. The cartoon series told the story of Scrooge McDuck (an elderly Scottish anthropomorphic Pekin Duck known as a business magnate and the richest duck in the world) and his three grandnephews. Each episode told us about Scrooge and his companions’ various adventures, most of which frustrated the Beagle Boys’ attempts to steal Scrooge’s fortune.

Fast forward to the new season I’m making of Duck Tales. In (my) first episode we will integrate our system to Scrooge’s banking services (“Scrooge McDuck Money Bin inc”). Scrooge McDuck is willing to initiate electronic (21st century, you know) money transactions on behalf of the company I’m working for. In short, we developed a financial technology platform that provides instant credit to small businesses.

“A day without looking at me Money Bin is like a day without sunshine!” — Scrooge McDuck

Following the quote, once a day, the scheduler runs on our database and prepares the list of electronic payments that should be transferred to the client-business. The transfer is actually performed by the bank. So we send the request to Scrooge to originate the provided payment (“Payment Origination”). The status of each individual payment can be tracked by polling to “Check Payment Status” API.

Now, Scrooge McDuck vault, the Money Bin, has a thick door, which is designed to prevent villains from breaking in and diving into the McDuck fortune. This is an authorization token that is required by each API call. This token is valid for 24 hours. So far so good, right. Here’s come a catch: you can receive a new access token only after it has expired.

“I’ve got to get you to my vault. It’s the only safe place” — Scrooge McDuck

This shouldn’t be an issue if you perform a few calls a day. I mean, you can just get an access token before each communication with Scrooge’s bank. But, what if you perform hundreds of these calls? This might bump you into the threshold limit, and will quite ball up your logs.

The challenge was therefore to optimize code by eliminating any unnecessary API calls. The idea was to generate an access token on demand (on authorization error failure), using a try-catch with a retry mechanism.

Well, the odd thing to say, I’m using Spring Cloud OpenFeign for this integration. Let’s move forward, I’m going to show you my way to overcoming the challenge.

First Step — Configure Authentication Client

Scrooge McDuck uses Basic Authentication, to verify the user’s identity. This is a simple authentication scheme built into the HTTP protocol. The authentication request requires the Authorization header, which value is word Basic followed by space and a base64-encoded string username:password: Authorization: Basic base64(username:password).

To make it clear, the difference between Authentication and Authorization is:

Authentication — is the process of verifying the identity of a user. Who are you?

Authorization — is the process of verifying the user’s access. Do you have permission to perform this action?

Well, where were we? Uh, the first step is to verify the user’s (mine, actually) identity. Scrooge McDuck will provide me temporary access to his Money Bin, in the event of successful authentication. This access token is my multi-pass, and now I’ve got to present it, each time I want to perform some action with money.

Come dive into the water of implementation.

Scrooge McDuck by Carl Barks.

First, I created the “Scrooge McDuck Authentication Client” class. Its configuration includes a Bean of the Basic Auth Request Interceptor. This interceptor converts provided credentials into base64-encoded values and passes them into the Authorization header of each request. If you ask me, why to use nested configuration, I did this in order to override Feign’s defaults without the risk of some other client using them or overriding them. Another way to render this restriction is to exclude it from the component scan (@ComponentScan). Either way, you should declare the desired configuration in @FeignClient annotation (@FeignClient(name = {client-name}, url = {endpoint}, configuration = {Configuration.class}))

This is how it looks.

The Basic Authentication requests need a login form with fields below.

In other words, the request payload should be passed as URL encoded form: content-type=application/x-www-form-urlencoded.

By default, the parameters are passed as a string. Who’d have thought? Add the feignFormEncoder() Bean to the configuration class, to override the default encoder, and to submit parameters as form. Otherwise you will faced the following error:

Caused by: feign.codec.EncodeException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [application/x-www-form-urlencoded]

Finally, I have the Authentication Response, which includes an access token and token type (Bearer). Hallelujah! The next step is to store this token in application content.

Second Step — Generate Access Token and Store in Memory

There are various ways to store value in memory. I selected to use Spring Singleton Scope Bean (the default one). Check out my “Scrooge McDuck Authentication Service”.

Scrooge’s authentication request is always the same. If a request is unable to be amended, there is no need to initiate it every time. So, I added the initiation of the request to @PostConstruct — it will be created once the container is created (and only once, since this is a singleton).

Let’s see, the main (the only one, actually, hellooooooo) method of this “Scrooge McDuck Authentication Service” is generateAccessToken() . (Don’t you “Hellooooooo” me!) The method calls the authentication client, that was mentioned above, sets the formatted access token to shared parameter accessToken (I’m on fire), and returns. So far so good?

Authentication is ready, an access token is stored in memory. The next step is to implement integration with the actual Payment Origination API.

Third Step — Configure Payment Origination Client

As I mentioned in the introduction of this post, Scrooge exposed two endpoints to us: “Originate Payment” (POST) and “Check Payment Status” (GET).

The payment manipulation requests require the access token (the pass to the Money Bin, remember?). The rationale is to retrieve the access token, whether it exists in memory, or else to create a new one, and to send it with a request as an “Authorization” header. I added a nested configuration that implements the Request Interceptor to apply it to each client’s request.

Well, in fact, the access token disappears only in case the service fails. So, as an alternative, you can generate the access token on the application start. Up to you.

Now, the existence of a token doesn’t mean the token is valid, right. Just to brush up the requirements — the token is valid for 24 hours and can’t be refreshed before. I brainstormed with my peers about current token management. The only thing that we agreed on is to create an access token on demand (on authorization failure). First up let’s catch this authorization failure.

The default error handler of the Feign throws a Feign Exception. In order to make it easier to catch an authorization mistake, I changed the thrown exception, by overriding the Error Decoder’s decode() method.

The method catches all errors. If the response’s status is 401 UNAUTHORIZED, I’m converting it to a very specific custom exception — UnauthorizedException().

The full “Scrooge McDuck Payment Client” class looks as following:

We are almost done, there’s only one thing on our way — to implement a retry mechanism.

Final Step — Implement Retry Mechanism

The easiest way to implement a retry mechanism is to surround the API execution by try and catch Unauthorized exception, to generate an access token, and to re-execute the failed operation. Actually, this is exactly what I started with:

Now, this is pretty easy and readable but inelegant. The repetitive template of “try-catch-generate token- try again” has been bugging me. So, I decided to replace it with a Spring Retry Template. I’m not just messing around, I mean it.

“You can’t be serious about this crazy idea; there’s no profit in it!” — Scrooge McDuck

Spring Retry Template

Spring Retry allows for the re-execution of operations when an Exception is thrown. In our case, we want to limit the retries to Unauthorized exceptions only (to reproduce the try/catch behavior).

Above all, I created the “Scrooge McDuck Payment Retry Policy” class which extends “Exception Classifier Retry Policy”. The constructor of this class initiates Simple Retry Policy and returns it if a caught exception is an instance of an Unauthorized exception. Otherwise, it returns “Never Retry Policy”, which terminates the execution.

In the same way, you can configure other exception policies. For example, on the “no internet connection” exception, you can add some backoff period before repeating our attempt.

The Retry Template is relevant for the whole project. So, I added the Retry Template Bean to the general Configuration class.

Each class, of course, can include a specific setup of Retry Template. Take a look at “Scrooge McDuck Retry Service”. I added a @PostConstruct annotation, to define template’s retry policy.

Retry Service class includes an execute() method, which wraps retryTemplate.execute(). The retry sense is to create an access token before re-execution, if it’s not the first attempt. The goal is achieved! =)

Next I took out the try/catch and replaced it by Scrooge McDuck Retry Service’s execute().

Done.

“Bless me bagpipes” — Scrooge McDuck

The Startup

Get smarter at building your thing. Join The Startup’s +731K followers.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +731K followers.

Gene Zeiniss

Written by

I am a wanderlust, foody, and wine lover. Well, I’m also a backend developer at FinTech company.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +731K followers.