A very surface level introductory presentation on Spring Boot for the First Year TU Delft Object Oriented Programming Project course.
What is this about / Who is this for
I was really interested in Spring Boot for some time and taught myself some basics over the last one month and a half or so. Keep that in mind alongside the fact that I am a first year student that has not taken OOPP yet. That being said, this page was created with the goal of introducing my colleagues to Spring Boot and giving out a very basic, purely backend toy application to hopefully help people get started with the course.
Why / What is Spring used for?
Spring is the most popular application development framework for enterprise Java. It is the
expressjs equivalent of Java. It can be used to create both Web Services as well as Applications. It is often also used to create
APIs which are then used by separate code bases that are possibly using a different programming language.
As an example, consider last year’s OOPP which was about creating an application that allowed you to book rooms as well as order food.
What is an API
An application programming interface (API) is a computing interface that defines interactions between multiple software intermediaries. It defines the kinds of calls or requests that can be made, how to make them, the data formats that should be used, the conventions to follow, etc. It can also provide extension mechanisms so that users can extend existing functionality in various ways and to varying degrees. An API can be entirely custom, specific to a component, or designed based on an industry-standard to ensure interoperability. Through information hiding, APIs enable modular programming, allowing users to use the interface independently of the implementation.
An API is a software intermediary that allows two applications to talk to each other. In other words, an API is the messenger that delivers your request to the provider that you’re requesting it from and then delivers the response back to you.
What is an API Endpoint
In simple terms, an API endpoint is the point of entry in a communication channel when two systems are interacting. It refers to touchpoints of the communication between an API and a server. The endpoint can be viewed as the means from which the API can access the resources they need from a server to perform their task. An API endpoint is basically a fancy word for a URL of a server or service.
As an example, for those of you who made the web game, an endpoint is each url supported by your app (say
Chocolatey: A windows package manager
Make sure to run powershell with admin privileges if you want to install packages. The Choco installation executable can be found here.
What is Spring Boot
Spring Boot provides a good platform for Java developers to develop a stand-alone and production-grade Spring Application that you can just run. You can get started with minimum configurations without the need for an entire Spring configuration setup.
For this project I will be using Java 15 which may differ from what will be used in the project
- Install Gradle (
choco install gradle)
- Make sure the output of
gradle -version(the JVM part) and
java -vpoint to the same Java version. If that is not the case try reinstalling the Java SDK (
choco install opensdk)or updating your paths.
- Make sure Intellij is using the proper Java SDK version for the project. Hit
ctrl + shift + alt + sto open the Project Structure panel in Intellij (check this one we create the project).
In case you are using a different Java version make sure to edit the
sourceCompatibility = ‘15’ attribute in
build.gradle to whatever version of Java you have installed (for example change it to
sourceCompatibility = ‘13’ if you are using Java 13).
The client will create REQUESTS to our server which will be handled by our API Layer or Controller in Spring terminology. This layer manages all our application’s endpoints and extracts data from the request before it passes it to the next layer.
The Service Layer is responsible for any business logic our application might have. As an example consider the scenario where you have a website and you want to allow users to create accounts but no two accounts should have the same username. The user will send a request to the server asking for an account creation along with his username (and credentials but that is not important here). The Controller will receive the request and destructure the username before calling the appropriate Service method and passing it the username. The Service is now responsible for checking whether the username already exists in the database or not. Note that the interaction with the database it performed in the next layer.
The Data Access layer or Repository is responsible for interacting with the database. At this point is where a typical response is generated and sent back to the user (exceptions could cause a response to be generated in any of the 3 layers). Dividing the application into layers is extremely important and has a lot of advantages.
- It boosts development speed
- It makes for cleaner code
- Different teams could be working on different layers
- It increases the application’s fault tolerance
On the far right you can see the Entity class that we will be implementing later, a Person class with an ID and a name.
There are a few different ways one can structure such an application, the one I prefer is shown above. A different way of doing this would be to have a
Person folder and inside live all the other classes which I will not be using as I believe it looks messier.
What is Gradle
What is Postman
Postman is a scalable API testing tool that quickly integrates into CI/CD pipeline. It started in 2012 as a side project by Abhinav Asthana to simplify API workflow in testing and development. API stands for Application Programming Interface which allows software applications to communicate with each other via API calls.
Spring Initializr is a web-based tool with which we can easily generate the structure of the Spring Boot Project.
Alternatively, there is a command line tool that does this for you!
choco install spring-boot-cli
spring init Copy
This command will create a project with:
- Gradle as its build system (by default this is maven)
- Java version 15
- The dependencies mentioned previously (web, jpa and postgresql driver)
- Artifact id of
- Project name of
- No package
In case you want to use this, run
spring help init for documentation.
Both of the methods listed above create a zipped folder so make sure to unzip it before continuing.
mkdir SpringPresentation | tar -xf SpringPresentation.zip -C SpringPresentation
This creates a new folder
SpringPresentation and extracts the zipped folder you just downloaded inside of it (assuming you are in the correct directory). You can also run
idea64.exe . to launch Intellij on your current directory.
Optional: If you want to have implement the entire project including a database make sure to have PostgtSQL installed (I installed it in Docker). To create the Database using docker run:
docker run --name springboottestdb -e POSTGRES_PASSWORD=password -d -p 5432:5432 postgres:alpineCopy
| docker exec -it 68627bf9417e bin/bash
68627bf9417e is your container ID. I will not be going more in depth on this as it is outside the scope of this article.
Alternatively, you can use a very popular in-memory Java database engine called H2, instructions on that will follow shortly.
Spring Web: Allows the building of RESTful applications
JPA: It makes it easier to build Spring-powered applications that use data access technologies.
- PostgreSQL driver
At this point, your empty project should look like this:
│ ├── java
│ │ └── SpringPresentation
│ │ └── SpringPresentationApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
We will start by editing the
src.main.resources.application.properties file to this:
spring.datasource.urlThe url of the database
spring.jpa.hibernate.ddl-autoSpecifies how to manipulate the database in set-up (
create-dropclears the database whenever the application is ran, used for testing purposes)
spring.jpa.show-sqlLogs any SQL commands
spring.jpa.properties.hibernate.dialectTells jpa what flavour of SQL we are using
spring.jpa.properties.hibernate.format_sqlBeautifies the SQL outputs
This configuration works with my PostgreSQL database set up but in case you want to use an H2 database instead perform the following modifications in
sa(default profile) and leave the password empty
And finally, go to the
build.gradle file and replace
runtimeOnly ‘org.postgresql:postgresql’ with
runtimeOnly ‘com.h2database:h2’ (make sure to rebuild the project after this step)
Note that everything else mentioned in this article will work the same in either a proper PSQL database and an H2 database.
We will now create the following 4 packages under
Now let’s create
src.main.java.SpringPresentation.Models.Person. Add a private field
long id; as well as
String name;. Create getters, setters an equals method, toString as well as 2 constructors:
public Person() and
public Person(String name).
So far we have created a simple Java class, now let's turn this into a Spring Entity.
public class Person add the following 2 annotations:
@Entity(name = “Person”)
@Table(name = “people”)
The first one tells Spring that the class is an Entity class and specifies its name. The name by default is the name of the class (so in our case this does not make a difference) however it is good practice to always specify the name.
The second one specifies the primary table for the annotated entity.
At this point you may notice that Intellij gives you an error when you hover over the Table name
Cannot resolve table 'people'. This is because we have yet to configure a datasource in Intellij. Press
ctrl + shift + a and search for
create data source. Select PostgreSQL. Change the User, Password and Database to what was specified in our
application.properties. Click apply and OK. At this point the error should change to
Cannot resolve table 'people', this is fine as the table does not and should not exist yet, it will be created automatically once we run the application. Note that if you are using the H2 database you can skip this step since the table will be created on runtime, the errors will still be visible. Do not worry about that; the table exists and it is working as intended.
You should see another error on the Person class:
Persistent entity 'Person' should have primary key , since we told spring that this is a Database table it must have a primary key. Add the
@Id annotation before the
private long id;.
At this point you might have noticed something weird: We have not included the
id parameter in any constructor, so how is it going to ever get a value? This is not a mistake, we want any IDs to be generated by the database, not by the user (imagine if everytime a user that wanted to create an account on a website for example had to include a unique id in his form; the user would have not way of knowing whether his id is unique or not). The conventional way of generating Database IDs is using a Sequence Generator.
We will now define our Sequence Generator and assign it to our id parameter. Add the following before the id declaration:
Let’s give Spring a few more details about our attributes. We can specify the name they will have in the Database (since they are collumns) and a few other stuff such as whether they can be updated or be nullable. Put the following 2 configurations before their respective attribute declarations.
If we now run the app and refresh the Intellij Datasource we should now see the following:
As we can see, our Database table has been created and the name errors have went away.
Next we will be creating the Repository interface. Create the file
src.main.java.SpringPresentation.Repositories.PersonRepository. Make our interface extend from
JpaRepository<Person, Long>. The first parameter is the class our Repository is going to be working with and the second one specifies the ID type of that class. This interface provides us with a some basic CRUD (Create, Read, Update, Delete) operations. Let's add an
updateNameById method that will update a person's name with a specified id.
We will not be implementing the method ourselves as the JpaRepository interface can do that for us. All we have to do is specify the query in an annotation above the method we just created.
The String we passed in the annotation is the name of this Repository which optional in our case. As we will see later it is necessary when we are dealing with multiple Repositories.
That is all we need in our Repository interface as the rest is handled by JPA.
On to our Service class. Create the file
src.main.java.SpringPresentation.Services.PersonSerivce. As you might suspect by now, we will annotate it with
Our Service class will have one attribute: The
PersonRepository we created earlier. Go ahead and create a constructor. Time to annotate it. Add
@Autowired above the constructor, this tells Spring it should use Dependency Injection. Finally, inside our constructor parameters add
@Qualifier("PersonRepository"). This ensures that the Repository named
PersonRepository is the one Injected.
We now have to implement all the methods our Controller has to be able to use. Since we have our Repository as an attribute here all of the simple methods we want are actually extremely easy to implement.
Keep in mind that our application is pretty simple. There is in fact 0 logic included in this layer. In a normal app this should end up being the most complicated layer.
Finally, let’s create the
src.main.java.SpringPresentation.Api.PersonController controller. There's a few more annotations involved here. First of all, let's add the following above the class declaration:
@RestController // Tells Spring this is a REST controller
The second annotation makes it so we will be able to access our API at
http://localhost:8080/api/v1/ instead of
http://localhost:8080/. This is again good practice as it is often the case that real life projects end up hosting numerous versions of their API at once (due to backwards compatibility not being viable).
There are 4 annotations that we are going to be using based on what type of HTTP request we want our endpoint/method to support:
All of these have a
path parameter which specifies the relative url to
http://localhost:8080/api/v1. For example
@GetMapping(path = "/example") will create a GET request handler for
But what about using data that was included in the request?
@PathVariable, @RequestBody tell Spring to extract the variable from either the Path or the Request Body respectively. In the case of
@PathVariable, the Mapping path should include the variable name enclosed in curly braces so Spring knows which one to use. This is done automatically for
There is not much to talk about here. Keep in mind that
@RequestBody will try to extract one object from the Request Body. That means that we can't for example have both id and person in our
updateNameById method. Lastly remember that this will try to fit the data it finds to one of the defined constructors and we did have a
public Person(String name) constructor.
At this point our application is basically done, time to test our endpoints using Postman!
Let's first check out what happens when we make a GET Request at
We get an empty array as expected since there are no objects in our database yet. Let’s add some! Remember that out POST mapping was at
http://localhost:8080/api/v1/insert and we used
@RequestBody to extract a Person from the request. Recall that Spring will automatically try to fit the request data into a Person constructor which means that if we send a payload containing an attribute called
name that has any value of type String, Spring will create a Person object out of it.
It works! We even get the full object returned to us as expected and we can see that it automatically got assigned an Id of 1! Let’s try our previous GET endpoint again;
This time we get an array of one element which is the person that we just added! Since we now have an entity in the database, let’s see what happens when we make another GET at
Remember that for this endpoint we used
@PathParameter to get the id. Let's see what happens when we input an id that does not exist
We get null instead of an error which is nice. Remember that this method returned an Optional. Time to test our PUT mapping. For this we again need to specify a
name, for the sake of the example let's set it to
UPDATED and see what happens.
No response since our method was null but reusing our previous Request we can see that the update did go through.
We only have delete so time to test that as well. We just need to specify a path variable here and we are good to go.
Let’s reuse our first Request to make sure nothing is left in the database.
Lastly, let’s make sure our Sequence Generator works properly by adding another entity in the database.
As we can see, this has an id of 2 which means our Sequencer is working properly.
Congratulations! You just used postman instead of writing tests, see if that gets you anywhere…
My Learning Resources
If you made it this far then I want to thank you for reading and I hope you got something out of this :)
Again, do keep in mind that all this is written by a first year student that has not taken the course yet. Do not take anything from this as 100% correct or best practice or even as something you will definitely use during the course itself. I taught myself some Spring basics mostly using the following sources (the first 2 heavily influenced the example application) so be sure to look into all of them, especially the third one. The code for this has been posted on my github for which you can find the link below. Happy coding ;)
- Website with some free courses
- Youtube Playlist
- Official Spring Documentation
- A few books I found online
Last but not least, you can find the full code for this project here.