Matchlogger update: I can add teams now!

I did quite a lot today. From working login, I went to being able to add teams through the user interface. All code changes can be seen in today’s pull request.

Tables and entity classes for countries and teams

I started with a database table for country information. I decided that this one will be (for now) managed only through Liquibase changesets, as I expect that country list will be static. For the beginning, there’s only one country (Poland), but I already have a task to add more. Each of the countries consists of name, some country codes (ISO-3166-1, FIFA, IOC) and a link to flag picture from Wikimedia Commons.

My structure for teams starts simple and is likely to grow. We’ve got a name, country and a link to team’s crest (logo). Right now I don’t store pictures, just links to them. This will likely change in future, but that requires a decision on how to store them – something that is a good topic for another post 馃檪

Vue.js attempt

I must admit that I had some issues with Vue.js. My first idea was to create a REST API returning team list, load them with Vue.js and present records in a table with Angular-like syntax. I must have overlooked that before, but it turns out that core Vue cannot trigger AJAX calls and needs to use a separate library for that. One has several options, starting with vue-resource, up to jQuery. I decided to start with jQuery, as I already was importing it for Bootstrap JS features. Turned out that fighting with what it looked like a simple „for each row print <tr> and three <td> tags” took me three hours after which I decided that for this module, I will go the known way and implement it with Thymeleaf.

With Thymeleaf, the structure of the application is different. We don’t provide a REST API but insert needed values on backend side using a Model object instead. The templating engine works fairly similar to what I wanted with Vue.js though, so while I don’t remove Vue yet, I’ll start with Thymeleaf and read more on Vue in the meantime.

Thymeleaf layout

Thymeleaf has its benefits – one of them is a fragment-based layout. I now have a structure where layout.html defines the core layout and each of pages doesn’t have to include a header, footer, core CSS and JS files all over again. Of course, as I’m a lazy developer that wants to start with something that looks decent and is responsive, I started with Bootstrap that I aim to customize when I get the functional part done.

So, how does the team list look like?

The user is able to add a new team, define a country (from a long list that includes Poland, Poland and… Poland), add a link to a crest picture and that’s it. Not much, but it is a first real functional part of the application. More to come soon.

Spring Boot: Saving OAuth2 login data in DB using PrincipalExtractor

This post is a continuation of configuring OAuth2 login in Spring Boot. If you want to know how to configure the login itself, please take a look at the previous post.

As I mentioned previously, we want to save user login data in our database to be able to connect matches data with their users. We’re going to save only some basic data – the external id of the user from the provider to distinguish the user, her full name (that I want the user to be able to replace it with the nickname in the future), avatar and e-mail address. Let’s start with the database. As we already configured Liquibase, we are able to add a migration that will create the table in the DB:

As we have only one provider now, we could as well skip the login_type column. That would mean that if we add a new provider, we’d likely need to add this column and prepare migration that adds the value for existing records, so I decided that it’s a good idea to start with it. When we now start the application, the table is created in the database:

Next step is adding User entity class and its related Repository interface we’ll be using for DB access. As I wanted to use LocalDateTime for managing dates, but JPA doesn’t work that well with it yet, I needed to add Jsr310JpaConverters class to @Entityscan in my MatchloggerApplication class.

The last part was using PrincipalExtractor to obtain the data we want, actually save them into the database and mark that they will be used as principal data. The documentation of this class is virtually non-existent, but I found this example. I added a similar section to my WebSecurityConfiguration.java with just returning the same I received to check which data I am able to obtain.

That was the set of data provided by PrincipalExtractor. It appears that everything that I wanted to get is available here, but there is one potential issue I may come up with in future – as long as I have only one authentication provider, I know that those data come from Google, but if I have several providers and they provide different data, it might be the case that I’ll need to find out the provider based on some keys’ existence. Not the best option, but seems I need to stick with it for now (if anybody knows a better option, please let me know).

My WebSecurityConfiguration class looks like this now:

After adding the PrincipalExtractor, I am able to see that on successful login I have my first user in the database.

Let’s then modify the code that returns user data to use my new configuration:

After login, this is a current message that we see:

One note to add is that Java 8 LocalDateTime doesn’t look too nice in generated JSON response. I’ll likely convert the returned value into a timestamp in the future, depending on view layer’s needs.

Capturing and comparing entire objects with Mockito and AssertJ

Let’s say we have a project in which we have the following classes:

We don’t yet have an implementation of the Runway interface (that will be created by another team), but we would like to test if our code creates a correct Plane object and passes it to the Runway. We’ll be using Mockito to mock the Runway implementation to test only the Airport class (so, write an actual unit test). I really like AssertJ so I’ll be using that one for assertions instead of usual JUnit assertions.

Let’s start with testing if plane departs correctly:

We now know that a plane departed, but we don’t yet know if that was the right plane. Let’s try comparing to the plane we expect:

The result is a failing test – not that we wouldn’t expect that.

There are two separate instances of Plane created here. While their fields are all the same, they are different objects and Mockito’s verify method checks that. Moreover, if we wanted to check only if a specific field of passed object has an expected value, we wouldn’t have an ability to check that with Mockito’s verify. There is a class called ArgumentCaptor though that can help us. Also, AssertJ has a neat method for comparing if all fields of two objects are the same:

The dish is ready to be served, enjoy.