One of the most common scenarios in an Enterprise application is the Creation, Retrieval, Updating and Deletion (CRUD!) of records in some backend somewhere.
Although there are many ways to implement the backend in a system like this, I describe a simple setup here. The idea is that I want to convey how simple this can be. Once you’re happy with the overall concepts it should be a trivial exercise to swap out the backend for your preferred one. You will then be able to maintain and reuse most of the middle and front tiers of the application described.
- Part 1: Introduction & Initial Setup: Maven, Spring and JPA/Backend (Database)
- Part 2: Middle Tier: Exposing our data with a REST Service
- Part 3: Front End — Initial Implementation
- Part 4: Front End — Grid Features & CRUD (Creation, Updates and Deletion)
The links above will become active as we publish the the following part of the blog series.
Our application will use the following technologies:
- Backend: H2 for the Database (Oracle in a later, optional, chapter)
- Middle tier: Java, Spring, Hibernate
- Front end: ag-Grid, Angular 4.x
Two parts of this entry of the series have been updated as the result of a bug I found later on.
Look for the
Updated! note (like this one) - one change is in the Data Model section, while the other is in the Bootstrapping section.
The lesson here? Write more tests folks!
Our application will be a reporting tool that looks at past Olympics results. Users will be able to see historic results for the Olympic Games from 2000 to 2012 (7 games in all) and be able to see who won the most medals for a given year, who won the most often, which country is — on average — the most successful, and so on.
In order to focus on the concepts being discussed, the application is deliberately simple — we’ll implement this using a traditional 3 tier model:
Or alternatively, you can break it down as follows:
In order to follow through this series, a number of tools are required. Please see their documentation on how to download and install it for your particular Operating System.
Subsequent sections will assume these tools have been installed and are available for use.
For the Backend and Middle Tier, we’ll be making use of both Maven and Spring (covered more later in the Series). In order to get up and running quickly, we’ll make use of Spring Initializr.
Spring Initializr provides a mechanism to get a Maven setup with specified key dependencies up and running with very little effort.
First, let’s navigate to http://start.spring.io/ to get started.
Once there, ensure you fill in the fields as follows:
Artifact can be anything you like. For Spring Boot I've chosen 2.0.0 (SNAPSHOT) as this is the latest available version for Spring 5 at the time of writing - if you have a newer version available that will be fine too.
Search for dependencies field search for
jpa and finally
h2, selecting each as the auto-complete presents a match.
Alternatively you can click on the
Switch to the full version link and select the above dependencies manually.
Once done, click on
Generate Project - you'll get a dialog to download the generated bundle. Save this to your chosen project location and once downloaded unzip it to a sub-directory called
You should see the following project structures:
│ ├── java
│ │ └── com
│ │ └── aggrid
│ │ └── crudapp
│ │ └── CrudAppApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
Maven provides a standard project structure, including a default Application file (
CrudAppApplication.java) and default, starting, test file (
We have unzipped the generated project into a directory called
backend as I prefer to keep the back and front end separate. Each tier can in effect be considered an application in its own right - this is especially true as your application grows in code and complexity.
Navigate to the
backend directory; let's download the dependencies and do a quick sanity check:
You should see a long output while mvn downloads all dependencies — this might take a little time depending on your internet speed. The above command will install all dependencies, compile the code and then run tests.
As it stands the test doesn’t do anything so you should see a message letting you know that the build was successful.
Running the Application
You can launch the application in one of 2 ways:
In an IDE
If you’re using an IDE you can run
src/main/java/com/aggrid/crudapp/CrudAppApplication.java - this will launch the application.
In either case the application will launch, but not actually do much at this stage.
This section has been updated to simplify the model — there is now no join table
(it was unnecessary — not sure why I added it!).
Result classes have been updated to reflect this change.
Our database model is pretty simple — we have 4 entities here:
AthleteThe main entity - from this we can get the Results and Country associated to the Athlete
SportSports completed in - static data
CountryAll Countries that completed - static data
ResultJoins the tables above and captures each medal won, by which athlete in which sport, as well as the year, date and age of the athlete at the time of the event
This information could be modelled better, but it’s based on the data available (i.e. if we had the Athletes date of birth, we wouldn’t need the age row in
Result - it could be computed).
Converting this to our middle tier, we’ll need the following four JPA Entities:
Country are simple entities as these are primarily there as static data.
Athlete are the most interesting of these entities.
Result has a
OneToOne mapping to
Sport, and has a
ManyToOne mapping to
Athlete in turn has a
OneToOne mapping to
Country, and a
OneToMany mapping to
This reflects the ERD (entity relationship diagram) model above.
We define each of these as JPA Entities by annotating the class with
@Entity. we also let Spring know that we want the
id field to be the ID by annotating the field with
@Id and finally annotate the field with
@GeneratedValue(strategy = GenerationType.AUTO) to have Spring/H2 auto-generate IDs for us.
There is obvious code duplication here which we could refactor, but for simplicities sake we’ve left the duplication in place.
With the above configuration Hibernate will create the following physical model for us:
So far we have entities and their mapping — this is great, but to be useful we need a facility to be able to perform read/writes/deletions of data. Spring makes this easy for us by providing the
CrudRepository interface which we can extend. With very little effort we get a great deal of functionality - this is a real time saver.
Below are the 4
Repositories we'll use in this application - one for each of the entities described above:
We can take a look at the generated model for us in
H2 but opening up the
H2 Console. This is disabled by default - we need to update
/src/main/resources/application.properties to enable it:
We can then navigate to http://localhost:8080/h2-console/ and take a look at what we have.
Be sure that the JDBC URL field is set to
jdbc:h2:mem:testdb. H2 will cache any previous URLs you might have used, but the in memory H2 one we're using here will be
Test Data — Bootstrapping
This section has been updated when I discovered I was incorrectly inserting duplicate
Athlete with it.
Write tests before you write code, and write them often!
In order to get the data we have (
src/main/resources/olympicWinners.csv) into the
H2 database, we'll make use of Spring's
ApplicationListener<ContextRefreshedEvent> facility to load the test data and save it to the database.
We’ll make use of a third-party library called
Jackson to convert the CSV to Java POJOs, so add this to your Maven pom.xml file, within the
Note that we’re only using this library for local testing, so it has the
On startup the data in
src/main/resources/olympicWinners.csv will be loaded, parsed and inserted in the database, ready for us to query.
Let’s start the application and then fire up the
H2 console to test what we have. If we run the following query in the
select a.name, c.name, r.age, c.name, r.year, r.date,s.name,r.gold,r.silver,r.bronze
from athlete a, country c, athlete_result ar, result r, sport s
where a.country_id = c.id
and ar.athlete_id = a.id
and ar.result_id = r.id
and r.sport_id = s.id
Optional — Spring DevTools
Spring Boot offers a development utility called Spring DevTools. This is an optional dependency, but makes local development much easier.
Let’s add the
DevTools to our Maven pom.xml file:
With this in place if you’re running your application and find you need to make a change you can do so, rebuild the project, and refresh the browser/end point without needing to restart your entire application.
This can be a real time saver, so adding this is recommended. Please refer to the Spring Boot DevTools documentation for more details about this.
This first part of the series is by necessity a bit by the numbers. It’s worth noting however if you simply run the commands above (and created the Java classes listed) you’d be up and running with a fully fledged CRUD system — all within no more than 30 minutes, which is pretty amazing.
In order to access the CRUD features we’ve just implemented we need to provide this to the front end — we’ll start covering that in the next part of this series!