This is the second installment of a two-part tutorial by Björn Wilmsmann, Philip Riecks, and Tom Hombergs, authors of the book Stratospheric: From Zero to Production with Spring Boot and AWS. Björn, Philip, and Tom previously wrote the blog posts Getting started with Spring Boot on AWS Part 1 and Part 2.
In Using PostgreSQL with Spring Boot on AWS — Part 1, we explored how to deploy an RDBMS on Amazon RDS. In Part 2, we walk through using the database we deployed from a Spring Boot application.
Configuring the database in the application
To connect to the PostgreSQL database instance, our sample application needs a few additional dependencies:
org.postgresql:postgresql contains the JDBC driver for connecting to the PostgreSQL database, whereas
org.springframework.boot:spring-boot-starter-data-jpa provides us with Spring Data JPA (and its dependencies), a widely used library for accessing databases from within Spring Boot applications.
Once we’ve started the service stack, our Spring Boot application will automatically connect to the PostgreSQL database using the standard
SPRING_DATASOURCE_PASSWORD parameters we set before.
Using the database for storing and retrieving todos
Now that we’ve prepared the surrounding infrastructure and our Spring Boot app is configured to use our new PostgreSQL database, we can finally put it to use in our application code.
If you’re familiar with using JPA in a Spring Boot application, you can skip this section and have a look at how to set up a local development environment for database connectivity.
The domain model of our application is structured around the
Todo entity, as shown in this diagram:
Our application follows a package-by-feature structure. This means that the feature folders
todo contain the code artifacts related to each of those features. These packages include controllers, service interfaces (and their implementations), Spring Data JPA repositories, and data model classes.
We’ll have a closer look at some of the classes from the
dev.stratospheric.todo package to examine how we use the newly created PostgreSQL database for our application.
We’ll focus on the
Todo class and how it’s used. This class is annotated with the
@Entity annotation from the
javax.persistence package (the API provided by JPA / Jakarta Persistence). This annotation marks the class as a database entity. By default, the unqualified class name (as opposed to its fully qualified name, which would include the package name) is used as the entity’s database table name:
Again, as with the entity name and the table name, the attribute names by default match the column names. Most of those attributes are annotated with one or more annotations. These annotations allow us to further specify rules and constraints that should apply to an attribute.
Primary key and object identity
id attribute is annotated with
@Id from the
javax.persistence package marking this attribute as the entity’s unique identifier (or primary key).
@GeneratedValue annotation (also from the
javax.persistence package) denotes that the attribute’s value is generated automatically. The
strategy = GenerationType.IDENTITY argument further specifies that this value is provided through an identity column in the database table.
Constraints and validation
Some columns are annotated with annotations from the package
javax.validation.constraints, such as
@Future. Such annotations allow us to define the rules—or constraints—we’d like to apply to each of the attributes and their value. For example, the todo’s title is supposed to contain a non-empty (not blank) string with 30 characters at most.
Storing and retrieving information
Now that we have defined our database entity, we can use it for storing and retrieving information. With Spring Data JPA, the abstraction for doing so is the
JpaRepository interface from the
org.springframework.data.jpa.repository package. This interface provides us with a set of methods for manipulating and retrieving data:
To use this for a specific database entity, such as our
Todo class, we must extend this interface with our own
This interface specifies a
JpaRepository that’s responsible for persisting
Todo entities with a
Long-typed ID. Moreover, we’ve added a
findAllByOwnerEmailOrderByIdAsc() method that allows us to find all
Todos whose owner has the email address given by the method’s
TodoRepository then can be injected into other classes, like our
TodoService, via Spring’s dependency injection:
Spring will automatically inject the
TodoRepository into the constructor of
TodoService. With this dependency, we now can insert a new row into the database table by calling
TodoService, in turn, is injected into the
TodoController, again using constructor injection, where it is used for creating, retrieving, updating, and deleting Todos in various controller methods. These controller methods are mapped to HTTP paths within our application that can be accessed through HTTP GET (in case of the methods annotated with
@GetMapping) and POST (for those methods annotated with
Finally, the Thymeleaf template in our application’s resources/templates folder, specifically
edit.html, make use of these controller methods to allow the user to display and edit todos.
Enabling local development
One thing is still missing in our setup: In most cases, we wouldn’t want to wait until our entire AWS infrastructure has been redeployed through our nearly continuous deployment pipeline after a code change. Instead, we want to test changes locally.
That’s where a local database instance comes into play. We can use Docker to spin one up by adding a service to the
docker-compose.yml file located in our application’s root directory:
With these lines added to the
docker-compose.yml file, we can now run
docker-compose up from the command line in our application’s root directory to start a PostgreSQL instance alongside other services already defined in our
Now, all we have to do is add these lines to a
application-dev.yml properties file in our application’s
build.gradle file already configures Gradle to use
dev as Spring Profile (by using
-Dspring.profiles.active=dev as a JVM argument), these settings will be picked up automatically when running
Find the source code with detailed instructions on how to build and run this application on GitHub.
Relational databases are an essential element of web applications, and PostgreSQL is a popular open source choice for a DBMS to run such a database on. Amazon RDS allows us to manage relational databases in the cloud, which in turn allows us to both account for non-functional requirements, such as scalability, and to provision and manage database resources in a self-service, DevOps fashion.
In this two-part tutorial, we learned about provisioning and deploying the infrastructure required for running a PostgreSQL database on Amazon RDS and had a look at how to use this database in the context of a Spring Boot application.
Using databases is but one aspect of web applications, though. In our book Stratospheric: From Zero to Production with Spring Boot and AWS, we develop an entire web application that seamlessly integrates with other common AWS services, such as Amazon Simple Queue Service (Amazon SQS), Amazon Simple Storage Service (Amazon S3), Amazon Simple Notification Service (Amazon SNS), Amazon Cognito, and Amazon Elastic Container Service (Amazon ECS) using Spring Cloud AWS. We guide readers through the steps required for getting a Spring Boot application running on AWS. This book explains how to get a Spring Boot application running on AWS. Not only do we focus on developing the application with Spring Boot, but we also take a detailed look at getting it ready for production. This includes a nearly continuous deployment pipeline, infrastructure-as-code using CloudFormation and AWS CDK, deployment patterns, and monitoring.
The content and opinions in this post are those of the third-party author and AWS is not responsible for the content or accuracy of this post.