Embed PostgreSQL into a spring boot application

Embedding a database in Spring Boot is has its own benefits, and is recommended for several reasons:

  • Simplified Development: With an embedded database, you don’t need to set up and manage a separate database server during development. It eliminates the need for manual installation, configuration, and management of the database server, making it easier and faster to get started with your application development
  • Lightweight and Portable: Embedded databases are lightweight and self-contained, meaning they are bundled with your application. This makes your application more portable, as you don’t have to worry about external dependencies or compatibility issues with different database server versions. It simplifies deployment and reduces the chances of configuration errors
  • Rapid Prototyping and Proof of Concept: When building prototypes or proof of concepts, embedded databases provide a quick and easy way to get your application up and running. They allow you to focus on the core functionality of your application without worrying about database setup and management

It’s important to note that while embedded databases offer convenience during development and testing, they may not be suitable for production environments. In production, it’s recommended to use a separate, dedicated database server that can handle larger data volumes, provide better performance, and offer more robust management features.

But what can be done if we would like a production grade ready database to be embedded and started when out spring boot application is stared, and stopped when our application is stopped?

PostgreSQL is a production ready mature SQL database engine, and, luckily it can be embedded into a java / spring boot application.

There are 3 changes needed to embed and use the embedded PostgreSQL database in our spring boot application:

  1. Add the required dependencies
<dependency>
      <groupId>ru.yandex.qatools.embed</groupId>
      <artifactId>postgresql-embedded</artifactId>
      <version>2.6</version>
</dependency>
<dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>9.1-901-1.jdbc4</version>
</dependency>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
</dependency>

2. Add configuration data

We need to add to application.properties the properties for the DataSource. The spring.datasource.embedded-directory specifies the location of the embedded postgreSQL

spring.datasource.url = jdbc:postgresql://localhost:5433/app-db
spring.datasource.username = postgres
spring.datasource.password =postgres
spring.datasource.driver-class-name = org.postgresql.Driver
spring.datasource.jdbcUrl = jdbc:postgresql://localhost:5433/app-db
spring.datasource.embedded-directory = target

After adding the properties for the DataSource, we need to create a class for returning the value of the embedded-directory:

@Component
@Primary
@ConfigurationProperties("spring.datasource")
@Data
public class EmbeddedDataSourceProperties extends DataSourceProperties { private String embeddedDirectory = "target"; }

3. Implement DataSourceConfig

We need to start the PostgreSQL database before any database operation is executed. We create a DefaultDataSourceConfig which starts the PostgreSQL, and when started, it creates the DataSource

@Configuration
public class DefaultDataSourceConfig {

    @Autowired
    private EmbeddedDataSourceProperties embeddedDataSourceProperties;

    @Bean
    @ConfigurationProperties("spring.datasource")
    @Primary
    public DataSource dataSource() throws IOException {
        URI uri = URI.create(embeddedDataSourceProperties.getUrl().substring(5));
        new EmbeddedPostgres(() -> "9.1.0-1")
                .start(EmbeddedPostgres.cachedRuntimeConfig(
                        Paths.get(embeddedDataSourceProperties.getEmbeddedDirectory())),
                        uri.getHost(), uri.getPort(), uri.getPath().substring(1),
                        embeddedDataSourceProperties.getUsername(),
                        embeddedDataSourceProperties.getPassword(),
                        Collections.emptyList());

        return DataSourceBuilder
                .create()
                .build();
    }
}

When the spring boot application is started, the platform specific PostgreSQL is downloaded to the specified location, and it is started, and the configured user/password/database is created.

Liquibase can be integrated to automatically track, manage and apply database changes


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.