Now that the basic CRUD interface is working it would be nice if we could extend the interface to make it even more useful. What if we wanted to return a list of all the locations in a particular state or if we wanted to find all the people who are in a particular location?
These sound like queries that you would normally write in SQL with something like ‘SELECT * FROM Locations WHERE State =”PA” ‘. To do this in Spring Boot and Spring Data Repositories you can use the simple query builder to add a single line to your repository.
This will return a List of Location objects when I pass in a string that matches a state. The @Param(“state”) is used as part of the REST interface that I’m also building and allows me to specify how this particular parameter will be passed on the URL.
On my PersonRepository I have added two additional query builders.
So now I can get a list of Person objects when I pass in a location id or I can get a list of Person objects when I pass in a manager id.
The Query Builder system in Spring Data Repositories is very powerful. findBy is just one of many method names that you can use. You can add additional query keywords like AND, NOT, OR etc. If your data entity has a date field you can do something like findByDateFieldBetween(date1,date2) and the query builder will build a query to find records just between those two dates.
I highly recommend reading the Query Builder documentation.
CRUD stands for Create, Read, Update and Delete which are probably the most basic of things that you can do to a piece of data. Spring Boot gives you a very easy way to setup an interface between your application logic and your data entities that can provide this CRUD interface without making you write a ton of code with what is known as a repository.
A repository is just a set of data entities, So for our application we will need two repositories, one for the Location entity and one for the Person entity. I’ve created a new package in my application to hold these called repositories. This is the LocationRepository
and this is the PersonRepository
These are both interfaces and they extend another interface called CrudRepository which will give you all the basic CRUD operations.
Assuming that I have setup access to my repository ( which I will show later ) I can now use any of the above methods on the repository to Create, Read, Update and Delete data from the repository. deleteAll() will obviously delete all the entities in the repository and findAll() will return all the entities that you can then iterate through. count() will tell you how many entities are in the repository.
So we have created our first two code changes and you are now ready to commit them to git. My rule is to commit often as this gives you a much better granularity for figuring out when bugs are introduced to the code and then being about to revert just those small changesets.
To commit your changes select the VCS menu in IntelliJ and click on Commit.
You should see a dialog box similar to the one above which shows the two new classes you have added to your application. You can then fill in the commit message but before you actually commit these changes you should also associate them with your User Story in VSTS.
If you have installed the Visual Studio Team Services For IntelliJ IDEA Plugin then you will see an extra icon above the commit message box. Clicking on this will bring up a list of the all the active user stories in VSTS that are assigned to you.
Select the story that you are working on from the list and then click on OK and the commit message box will be updated.
You can now go ahead and commit these changes to git.
When you commit the changes you are only updating your local version of the git repository. To get the changes up to the VSTS server you will also need to push them. Normally I will push my changes up every few hours and always push at the end of the day so that I know they are safe on the server in case something were to happen my machine.
In IntelliJ go to the VCS –> Git –> Push menu option
You will see a list of all the commits that you are pushing to the server and at the top will be verification that you are pushing them from your local story branch to the server story branch. If you see ‘master’ as the local branch the you forgot to check out the story local branch before commiting and you should move the commits from the master branch to the local story branch before you continue.
Back over in VSTS you will be able to see your new code commits.
and on the Code –> Branches section in VSTS
You can see all your branches and how far ahead ( or behind ) they are with the master branch.
Now that the Location class has been created it is time to create our Person class. As the name suggests it represents a single person in the data store.
This class is very similar to the Location class so I will not go in to too much details. Just don’t forget the @Entity and @Id annotations. Make sure you have the constructors created and also your Getters and Setters.
You may notice that I have not setup any relationships between the tables. Technically I am using an SQL database so I could setup a One To Many type relationship between the Location and Person using a @OneToMany annotation but normalization of database tables is outside the scope of this blog. Instead for this simple application I’m going to keep the two tables unrelated for the time being.
Now that we have our two Entity classes created lets get them pushed to the GIT repository server…
In the Domino world the data store is part of the application container. When building your app you will invariably start by creating your forms and views to hold the basic structure of the data. For this Spring Boot based application I am going to start with the same step of building my data.
Two of the dependencies that I selected from the Spring Boot Initializer were spring-boot-starter-data-jpa and com.h2database. You can see these in your pom.xml file in the root of your project structure. The H2 Database is an in-memory or file based SQL data source. It is perfect for development work but should be replaced in a production environment. The spring-boot-starter-data-jpa dependency adds in a data persistence layer based on Hibernate.
For the application I am going to need Locations and People. I’m going to create a new package under com.qtzar called ‘model’ and then create a java class in there called Location.
First I need to annotate the class with the @Entity annotation. This will indicate to Hibernate that the class represents a data structure which will then translate to a table in my data source.
Next we add all the columns to the table. This is done by adding private fields to the class. You will also notice that the first field has been annotated with @Id. This indicates to Hibernate that the field called id is the unique key for the table.
Next we need a constructor for the class. I have created two constructors. One is an empty constructor and one takes a list of parameters that match up to all the fields in the class. This allows me to create a blank location or a fully constructed location.
Then you will need a getter and a setter for each field you added to the class. You COULD type them all out by hand but that would be painful so why not use your IDE to do the job for you. IntelliJ and Eclipse both have code generators that you can use for create getters and setters.
Another option would be to investigate Project Lombok. Then you just need to add @Getter and @Setter to the class annotations and as long as Project Lombok is setup correctly the getters and setters will be auto generated in the compiled code.
Before you start writing code you should create a branch to add the code to in your git repository. You could decide to create the branch directly in your IDE if it has Git support, or if you are using an external tool like Git Tower or SourceTree you could create the branch there. I’m going to use VSTS to create my working branch and then pull that branch down to IntelliJ IDEA just to show you an alternative method.
In the story you just dragged over to the Active column you will see a small — menu in the upper right when you hover over the story. Clicking on this will bring up a context menu with some interesting items on it like adding tasks and tests which I’ll mention much later in another posting but for now I’m interesting in the ‘New Branch…’ menu. Go ahead and click on that.
A new dialog will appear asking for your branch name. You can call it whatever you want. I like to try link the branch name to the story somehow so I’m going to call mine ‘Story667-CreateHomePage’
IntelliJ IDEA has no idea that this branch exists so we need to tell it about the branch by fetching it from the server.
Using the VCS menu, go to Git and then select ‘Fetch’. This will pull down all the changes on the server but it does not change your current branch.
We can see that it has worked by looking in the Version Control log which is available by clicking the Version Control tab in the lower toolbar of IntelliJ.
Now go to the VCS -> Git -> Branches screen and you see the new remote branch.
Click on it and select the option to ‘Checkout as a new local branch’.
Now you can start writing code.
Before we start slinging code around it would probably be a good idea to map out a few concepts and requirements. I’m going to use the VSTS work section to do this. I will create requirements for each idea that I have and then later as I’m working on my code I can link these requirements with the code commits.
If you have never worked with Agile, Scrum, Waterfall or Kanban before the idea behind it is that each indivisible piece of work is laid out in what is known as a User Story. A developer can then take that story, write the code to make that story work and fulfil the acceptance criteria without having to worry about what anybody else on the team is doing. I’m not going to go in to any details on a full Agile methodology but I do want to show you creating and using User Stories in VSTS.
In VSTS go to the Work section and make sure that you are looking at the User Stories / Board view. The screenshot above shows the basic layout and this can then be further customized for your needs. In our corporate environment we have added ‘Ready’ and ‘Accepted’ columns as well as a ‘High Priority’ swimlane as follows.
Now I can start creating my User Stories. Clicking on New Item in the New column will create a new card in the New column where you can type in a title. You can create a bunch of these in quick succession as you jot down your ideas and then come back and start fleshing them out with more details.
Now that we have our main ideas in place you can open those cards and start adding the details and acceptance criteria. You can also set priorities and story points and other info that can help with the prioritization and planning of stories but I won’t be getting in to that for this application.
If you look at the user story you can see that it is written in a very specific manner. As a [WHO] I would like [WHAT] so that I can [WHY]. Even if you are writing your own user stories you should try and use this methodology as it helps you get inside the mind of the users of the application need. The acceptance criteria is written is the form of what the user does and what the expected result is. In a large organization it will probably be the product owners and not the developers who write thee user stories.
In this case the product owner has finished writing the user story and has dropped it in to the ‘Ready’ column. This indicates to the development team that the story is ready to start work on so as the developer I can then drag that story from the ‘Ready’ column to the ‘Active’ column. This will assign the story to me and tell any other developers on the team that I am working on it.
Now I can start writing code…