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

Spring Top – Temp

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

Lightrun – Third Party Code

We rely on other people’s code in our own work. Every day. It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.

The problem is, of course, when things fall apart in production - debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky. It’s difficult to understand what talks to what and, specifically, which part of the underlying library is at fault.

Lightrun is a new kind of debugger.

It's one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics. No hotfixes, redeployments, or restarts required.

Learn more in this quick, 5-minute Lightrun tutorial:

>> The Essential List of Spring Boot Annotations and Their Use Cases

1. Overview

Posting to Reddit is a crap shoot. One post may do great and get a whole lot of attention while another, maybe better post will get no love at all. What about keeping an eye on these posts early on and – if they're not getting enough traction – deleting them quickly and resubmitting them.

In this quick article we're continuing the Reddit case study by implementing an interesting functionality – delete and resubmit a post if it's not getting enough attention immediatly.

The simple goal is to allow the user to configure how many votes on Reddit are enough to consider the Post is getting enough traction to leave it up – inside a certain time interval.

2. More Reddit Permissions

First – we'll need to ask for additional permissions from the Reddit API – specifically we need to edit posts.

So we'll add “edit” scope to our Reddit Resource:

public OAuth2ProtectedResourceDetails reddit() {
    AuthorizationCodeResourceDetails details = 
      new AuthorizationCodeResourceDetails();
    details.setScope(Arrays.asList("identity", "read", "submit", "edit"));

3. The Entity and the Repository

Now – let's add the extra information in our Post entity:

public class Post {
    private String redditID;
    private int noOfAttempts;
    private int timeInterval;
    private int minScoreRequired;

The fields:

  • redditID: Post ID on Reddit, to be used when checking the score and when deleting the post
  • noOfAttempts: Maximum number of resubmit tries (delete Post and resubmit it)
  • timeInterval: Time interval to check if the post is getting enough traction
  • minScoreRequired: Minimum score required to consider it successful enough to leave up

Next – let's add some new operations into our PostRepository interface – in order to easily retrieve posts when we need to check check them:

public interface PostRepository extends JpaRepository<Post, Long> {

    List<Post> findBySubmissionDateBeforeAndIsSent(Date date, boolean sent);

    List<Post> findByUser(User user);

    List<Post> findByRedditIDNotNullAndNoOfAttemptsGreaterThan(int attempts);

4. A New Scheduled Task

Now – let's define a new task – the re-submit task – into the scheduler:

@Scheduled(fixedRate = 3 * 60 * 1000)
public void checkAndReSubmitPosts() {
    List<Post> submitted = 
    for (Post post : submitted) {

Each few minutes, this is simply iterating over the posts that are still in play – and, if they're not getting enough traction, it deletes them and submits them again.

And here is checkAndReSubmit() method:

private void checkAndReSubmit(Post post) {
    try {
    } catch (final Exception e) {
        logger.error("Error occurred while check post " + post.toString(), e);
private void checkAndReSubmitInternal(Post post) {
    if (didIntervalPassed(post.getSubmissionDate(), post.getTimeInterval())) {
        int score = getPostScore(post.getRedditID());
        if (score < post.getMinScoreRequired()) {
        } else {
private boolean didIntervalPassed(Date submissonDate, int postInterval) {
    long currentTime = new Date().getTime();
    long interval = currentTime - submissonDate.getTime();
    long intervalInMinutes = TimeUnit.MINUTES.convert(interval, TimeUnit.MILLISECONDS);
    return intervalInMinutes > postInterval;
private void resetPost(Post post) {
    long time = new Date().getTime();
    time += TimeUnit.MILLISECONDS.convert(post.getTimeInterval(), TimeUnit.MINUTES);
    post.setSubmissionDate(new Date(time));
    post.setSubmissionResponse("Not sent yet");;

We'll also need to keep track of the redditID when first submitting it to Reddit:

private void submitPostInternal(Post post) {
    JsonNode node = redditRestTemplate.postForObject(
      "", param, JsonNode.class);
    JsonNode errorNode = node.get("json").get("errors").get(0);
    if (errorNode == null) {
        post.setNoOfAttempts(post.getNoOfAttempts() - 1);

The logic here is also quite simple – we just save the id and decrease the number of attempts counter.

5. Get Reddit Post Score

Now – let's see how we can get the current score of the post from Reddit:

private int getPostScore(String redditId) {
    JsonNode node = redditRestTemplate.getForObject(
      "" + redditId, JsonNode.class);
    int score = node.get("data").get("children").get(0).get("data").get("score").asInt();
    return score;

Note that:

  • We need the “read” scope when retrieving the post information from Reddit
  • We add “t3_” to the reddit id to obtain full name of the post

6. Delete the Reddit Post

Next – let's see how delete Reddit post using its id:

private void deletePost(String redditId) {
    MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
    param.add("id", "t3_" + redditId);
      "", param, JsonNode.class);

7. The RedditController

Now – let's add the new info to the controller:

@RequestMapping(value = "/schedule", method = RequestMethod.POST)
public String schedule(Model model, 
  @RequestParam Map<String, String> formParams) throws ParseException {
    Post post = new Post();

8. The UI – Configure the Rules

Finally – let's modify our very simple schedule form to add resubmit the new settings:

<label class="col-sm-3">Resubmit Settings</label>

<label>Number of Attempts</label> 
<select name="attempt">
    <option value="0" selected>None</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>

<label>Time interval</label>
<select name="interval">
    <option value="0" selected >None</option>
    <option value="45">45 minutes</option>
    <option value="60">1 hour</option>
    <option value="120">2 hours</option>

<label>Min score</label>
<input type="number"value="0" name="score" required/>

9. Conclusion

We're continuing to improve what this simple app can do – we can now post to Reddit and – if the post isn't getting enough traction quickly – we can have the system delete it and re-post to give it a better chance of performing.

Spring bottom

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

REST bottom

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

REST footer banner
Comments are closed on this article!