I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this article we’re going to be building a Profile for the user of our Reddit application – to allow them to configure user specific preferences.

The goal is simple – instead of having the user fill in the same data each time they schedule a new post, they can set it once – in the preferences of their profile. Of course the user can always tune these settings for each post – but the idea is they don’t have to.

2. The Preference Entity

Overall, most things that can now be configured in the applications are going to become globally configurable in the user profile.

First, let’s start with a Preference entity:

@Entity
public class Preference {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String email;

    private String subreddit;

    private boolean sendReplies;

    // for post re-submission
    private int noOfAttempts;
    private int timeInterval;
    private int minScoreRequired;
    private int minUpvoteRatio;
    private boolean keepIfHasComments;
    private boolean deleteAfterLastAttempt;
}

So, what can we now configure? Simply put – defaults for pretty much every setting in the application.

We’re also storing the email of the user to allow them to receive notifications about what’s happening to their posts.

Now, let’s link the preferences to the user:

@Entity
public class User {
    ...
    
    @OneToOne
    @JoinColumn(name = "preference_id")
    private Preference preference;
}

As you can see, we have a simple one-to-one relation between User and Preference.

3. Simple Profile Page

First, let’s create our simple profile page:

<form >
    <input type="hidden" name="id" />
    <input name="email" type="email"/>
    <input name="subreddit"/>
    ...
   <button onclick="editPref()" >Save Changes</button>
</form>
<script>
$(function() {
    $.get("user/preference", function (data){
        $.each(data, function(key, value) {
            $('*[name="'+key+'"]').val(value);
        });
    });
});
function editPref(){
    var data = {};
	$('form').serializeArray().map(function(x){data[x.name] = x.value;});
	$.ajax({
        url: "user/preference/"+$('input[name="id"]').val(),
        data: JSON.stringify(data),
        type: 'PUT',
        contentType:'application/json'
    }).done(function() { window.location.href = "./"; })
      .fail(function(error) { alert(error.responseText); }); 
}
</script>

Nothing fancy here – just some plain HTML and JavaScript.

Let’s also add a quick link to the new profile:

<h1>Welcome, <a href="profile" sec:authentication="principal.username">username</a></h1>

4. The API

And here the controller, for creating and editing user’s preferences:

@Controller
@RequestMapping(value = "/user/preference")
public class UserPreferenceController {

    @Autowired
    private PreferenceRepository preferenceReopsitory;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public Preference getCurrentUserPreference() {
        return getCurrentUser().getPreference();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.OK)
    public void updateUserPreference(@RequestBody Preference pref) {
        preferenceReopsitory.save(pref);
        getCurrentUser().setPreference(pref);
    }
}

Finally, we need to make sure that, when the user is created, its preferences are also inintialized:

public void loadAuthentication(String name, OAuth2AccessToken token) {
    ...
    Preference pref = new Preference();
    preferenceReopsitory.save(pref);
    user.setPreference(pref);
    userReopsitory.save(user);
    ...   
}

5. Load/Use Preferences

Now – let’s see how to use these preferences and fill them in whenever they’re required.

We’ll start with the main Post Schedule page – where we’ll load in the preferences of the user:

$(function() {
    $.get("user/preference", function (data){
        $.each(data, function(key, value) {
            $('*[name="'+key+'"]').val(value);
        });
    });
});

6. Testing and Conclusion

We’re almost done – we just need to implement some basic integration tests for the new Profile entity we just introduced.

For the most part, we’re simply going to be extending the existing base persistence test and inherit a battery of tests from that.

Finally – we can wrap up the new user profile functionality – users are now able to set up their own preferences.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS