Revisiting a Custom UserConnection JPA Object in Spring Social

The more you work with Spring the more you learn what can be leveraged from the framework, like not having to write a UserConnection object when Spring Social ConnectionData is already available.

We're focusing on Spring Social in NixMash Spring at the moment, with one of the features being a persistent Social User object containing basic data like the user's Profile Image Url, Display Name, and so on. With that data readily available we can do things like display a Provider's User Profile image in the Navigation Bar.

We're using Spring Social ConnectionData to display that image with a Model Attribute we're calling currentUserConnection which in Thymeleaf looks like this.

ConnectionData is persisted in a table called UserConnection. It is populated by the Spring Social ProviderSignInAttempt class via a JdbcConnectionRepository on User Sign Up with providerSignInUtils.doPostSignUp(userId, request). Here we see the doPostSignUp() call in the /signup{POST} method of the UserController.

All that is to say that we have a persisted object Spring calls ConnectionData, representing the UserConnection table. Our question then, and subject of this post, is, Do we need our own UserConnection JPA Model/Service/Repository logic?

Let's take a quick look at the Spring Social UserConnection table schema.

If we were to create our own UserConnection Model it would look like this.

And our UserConnection Repository like this.

Using ConnectionData

Like I said, we could go with the UserConnection JPA approach to the UserConnection table, but we'll leverage as much of the Spring framework as possible and stick with ConnectionData. What we'll do is obtain the ConnectionData object from the Spring Social Connection<?> Interface, save it to Session when the User Signs Up or Signs In, and make it readily accessible to the client in a Controller Advice Model Attribute we'll call CurrentUserConnection.

Here the user is signing in from an Oauth Service Provider. With access to the Connection<?> Interface established on sign-in with information provided by the Provider, we'll create a ConnectionData object and pass it to our Session Saving SignInUtils.setUserConnection() method.

Saving the ConnectionData object to Session…

..and making it available to our client as a Model Attribute in our Spring Controller Advice class.

Let's look at another example of using our currentUserConnection, i.e., ConnectionData object on the client. At the bottom of each NixMash Spring page is a brief summary of the current user. Here we'll display the user's Social Provider if it exists.

The currentUserConnection Thymeleaf source can be re-purposed for any provider and as a result is very efficient.

Before I sign off, you might wander if I'll be keeping the UserConnection Model/Service/Repository logic after moving to a pure ConnectionData approach. That's an Affirmative, for now anyway. The code is fully functional if I want to use it, and Hibernate creates the UserConnection table on startup in H2 Memory mode so I don't have to mess with a .sql startup script. The main reason is because the Spring ConnectionData object doesn't have a UserId property (or Rank). With a UserConnection JPA model I can retrieve the UserId field and perform other operations on the UserConnection table if I ever wanted to do so.

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 March 29, 2016 03:48 PM EDT

More Like This Post