Partner – Microsoft – NPI (cat= Spring)
announcement - icon

Azure Spring Apps is a fully managed service from Microsoft (built in collaboration with VMware), focused on building and deploying Spring Boot applications on Azure Cloud without worrying about Kubernetes.

And, the Enterprise plan comes with some interesting features, such as commercial Spring runtime support, a 99.95% SLA and some deep discounts (up to 47%) when you are ready for production.

>> Learn more and deploy your first Spring Boot app to Azure.

You can also ask questions and leave feedback on the Azure Spring Apps GitHub page.

Course – LS (cat=REST)

Get started with Spring and Spring Boot, through the reference Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this quick article we’re going to continue improving our small Reddit app by rate limiting the way it has access to the live Reddit API.

The simple idea is that we want to make sure we don’t hit their API to much – otherwise Reddit will start blocking the requests. We’re going to make good use of the Guava RateLimiter to get there.

2. A Custom RedditTemplate

First, let’s create a Reddit template – a small client for the Reddit API – which will consolidate all low level communication to a single component:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RedditTemplate {

    @Autowired
    @Qualifier("redditRestTemplate")
    private OAuth2RestTemplate redditRestTemplate;

    private RateLimiter rateLimiter;

    public RedditTemplate() {
        rateLimiter = RateLimiter.create(1);
    }
    
    public JsonNode getUserInfo() {
        rateLimiter.acquire();
        return redditRestTemplate.getForObject(
          "https://oauth.reddit.com/api/v1/me", JsonNode.class);
    }
    
    public JsonNode submitPost(MultiValueMap<String, String> params) {
        rateLimiter.acquire();
        return redditRestTemplate.postForObject(
          "https://oauth.reddit.com/api/submit", params, JsonNode.class);
    }
    
    public String needsCaptcha() {
        rateLimiter.acquire();
        return redditRestTemplate.getForObject(
          "https://oauth.reddit.com/api/needs_captcha.json", String.class);
    }
    
    public String getNewCaptcha() {
        rateLimiter.acquire();
        Map<String, String> param = new HashMap<String, String>();
        param.put("api_type", "json");
        return redditRestTemplate.postForObject(
          "https://oauth.reddit.com/api/new_captcha", param, String.class, param);
    }
    
    public OAuth2AccessToken getAccessToken() {
        rateLimiter.acquire();
        return redditRestTemplate.getAccessToken();
    }
}

A few interesting things are happening here.

First – we’re using the Session scope for this bean – simply so that each user/session in our app will get its own RedditTemplate instance.

Now – the OAuth2RestTemplate already has support for keeping credentials session scoped, but we’re going beyond that here and making the actual bean instance session scoped – so that we can also rate limit each user separately.

Which leads us to the actual rate limiting logic – simply put, we’re using the Guava RateLimiter to acquire a permit before letting the request through and hitting the live API.

3. The RedditController

Next – let’s start using this new RedditTemplate in the RedditContoller – for example:

@Controller
public class RedditController {
    @Autowired
    private RedditTemplate redditTemplate;

    @Autowired
    private UserRepository userReopsitory;

    @RequestMapping("/login")
    public String redditLogin() {
        JsonNode node = redditTemplate.getUserInfo();
        
        loadAuthentication(node.get("name").asText(), 
          redditTemplate.getAccessToken());
        return "redirect:home.html";
    }
}

4. Conclusion

In this part of the Case Study we added rate limiting to the Reddit application, to make sure we’re not blocked by the live API for to much activity.

This isn’t a theoretical problem either – but actually something that I ran into a couple of times using the app.

It’s this kinds of small improvements that are eventually going to lead to a mature and usable application – so I’m excited about this particular step.

Course – LS (cat=Spring)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> THE COURSE
Course – LS (cat=REST)

Get started with Spring and Spring Boot, through the Learn Spring course :

>> CHECK OUT THE COURSE
res – REST (eBook) (cat=REST)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.