This article is a continuation of Spring Boot: REST + TDD from scratch, so, please, head there first if you haven't yet.
In this article we will add Spring Data JPA to help us on implementing a JPA based repository. Our main goal will be persisting/retrieving our users data through RESTful endpoints and, just like in the previous article, we are going to try to keep up with TDD practices.
So lets start by creating a simple test:
Add this file to $SOURCE_HOME/src/test/java/br/com/brunokrebs/
This class contains a single test that uses REST Assured fluent API to post a User, serialized as JSON, to the endpoint that we are going to create. This code, as is, will not even compile, since we have no User class yet. Lets create it now to be able to run our test.
Add this file to $SOURCE_HOME/src/main/java/br/com/brunokrebs/model/
For now, a simple POJO is enough, since we will just use it to serialize/deserialize to/into our about to be created endpoint. With this new class in place, we are now able to execute our tests. Issuing a 'mvn clean verify' will perform this task for us.
Ooops, we got a red flag in our test. Looks like our endpoint didn't respond with a status code equals to HttpStatus.OK as line #23 of our test was expecting. Well, makes sense since we haven't yet created our endpoint. Lets do it now:
Add this file to $SOURCE_HOME/src/main/java/br/com/brunokrebs/rest/
With this small class in place we shall now be able to run our test again and (hopefully) see it pass. Lets issue 'mvn clean verify' again. Great, it now passes our first test.
But wait, our REST service is just returning the user that we pass to it. Lets improve our tests to see if our endpoint has, somehow, magically persisted our user.
Take a look at @FixMethodOrder annotation. The NAME_ASCENDING configuration makes JUnit run our tests in alphabetical order.
Issuing a ‘mvn clean verify’ now proves nothing about our user being persisted or not, it just proves that we don't have an endpoint answering to GET requests on '/users/' path. So, to gain some speed and keep things simpler, lets go ahead and add Spring Data JPA to our project first and then create a method to answer to GET requests.
TDD usually expect us to create a small test first, make the simplest implementation to fulfill this test, improve the test to add new conditions, refactor our implementation and go like that forever. Even though some TDD practices are very good, this micro cycles is not veeery productive and that is why we are skipping a few cycles in this article.
To add Spring Data JPA as a dependency and persisting data through our RESTful endpoints, takes only four simple steps. First we need to add two dependencies to our pom.xml:
The first one adds JPA 2 and Hibernate to our project. Then we have to annotate our User class to get persisted and add an id to its instances.
User class now annotated to be persisted and with an id field that is auto generated.
After that, as our third step, which is a proof of how Spring incredibly smoothes things to us, is to create a repository interface that Spring Data will use to create repository implementations automatically. This implementation will have everything we need for now (like save, find by id and find all methods).
Create this interface at $SOURCE_FOLDER/src/main/java/br/com/brunokrebs/repository
And as a fourth ste… wait, WAT? Is UserRepository correct? Just an interface that extends another? Yes!! So deal with it and lets keep going. In our next article we will see more great things about it. As I was saying, the fourth and last step is to refactor our UserRest class to use the previously created UserRepository to save and list users.
$SOURCE_HOME/src/main/java/br/com/brunokrebs/rest/UserRest.java
Now, with all these four steps done, lets issue 'mvn clean verify'. Great! Both tests are passing and our user is getting persisted. This is so amazing. Well, not that amazing, H2 is an embedded database and, with this configuration, all tables get recreated on every execution. So nothing gets really persisted. Our users remain in the database just for the same time as our application is up and running. When it gets shutdown, our data is lost.
We will work on that in the next article. Actually, we will replace H2 database, which was used here just to show how easy it is to use JPA/Hibernate in our Spring Boot REST oriented application, with PostgreSQL.
Oh, just an addendum, if you would like to keep our system up and running to be able to issue request manually, just issue the following command 'mvn spring-boot:run'. The system doesn't have an graphical interface yet, but we will work on that too. And this interface will be based on our RESTful endpoints as well.
So, what do you think about Spring Boot and this architecture that we are putting together? In my opinion, it is one of the best architectures that an enterprise application, that is based on web technologies, can have. We are building our application in a solid foundation, Spring with automated test, and in a stateless approach, just like HTTP was designed to work. Leave a comment :)
My name is Bruno Krebs and you can reach me on my Twitter, my LinkedIn and my Github account. Also, feel free to add any comments here or in any of my articles.