Like Buttons From Scratch with Spring

If you view the NixMash Spring Posts stream you'll find shiny new Like Buttons with each post. The Like Button was built from scratch over the course of a day with Spring using a dash of Thymeleaf and Velocity, oh, and a few lines of JavaScript, but only a few.

Let's get the JavaScript out of the way. As you see, there's very little of the stuff, but it reveals the core of our Like Button logic: our Spring MVC JSON will retrieve a 1 or a -1. That's it. If the user hasn't previously liked the post a 1 is returned, if they previously liked it, their like is removed and a -1 is returned. You'll notice that the user has to be logged-in to like a post, since their userId is used to record their activity. Thymeleaf inline variables makes that easy for us.

The Spring MVC method is a single line, returning the 1 or -1 from the Service layer.

The Service method addPostLike(userId, postId) is where the action is. Let's break it down. (1) We retrieve the Post by postId and use a Java Optional to determine if the user previously liked the post. If they have (2) we send back a -1 and delete their like from the user_likes table for that post. If this is a new like (3) we'll create and save the new Like object. There's a separate likesCount field in the posts table making retrieval easier, so whether the incrementValue is 1 or -1 we add it to the existing Post likesCount value. (4)


We use Velocity to populate the individual stream posts from the post Model. Here's that.

We use Thymeleaf to populate the post HTML of the Permalink page. Here is that code, only slightly different than the Velocity we just saw.

The Tests

We're going to show two tests, first the Post Service addLikedPost() method for a pre-existing like. We also have tests for new likes but those aren't quite as interesting so we'll skip those.

There are lots of comments here to describe what's going on. Our H2 Test Data sets the scene for us with User “Keith” userId 3 having previously liked the Post with postId 3. We get the initial likesCount for that Post, then confirm the service returns a -1. That Post should also have one less likesCount. Finally we'll confirm there is no like record for that user-post combo in the user_likes table.

We'll conclude with a quick test of the Spring MVC method, using the latest cool @WithUserDetails Spring Security Annotation. We'll test a like with the same User and Post. As in our previous test, the end result should be a -1, this time in the JSON body of the MockMVC result.

Source Code Notes for this Post

All source code discussed in this post can be found in my NixMash Spring GitHub repo and viewed online here.

Posted July 22, 2016 10:21 AM EDT

More Like This Post