What You'll Learn

We want to enable our application to communicate with different databases in different environments.

We may want to the use the repeatability and speed of H2 when developing and testing, but MariaDB when moving closer to the production environment.

This tutorial will only cover the support of different database connection properties, but profiles can vary the code as well. This might be useful where the functionality of H2 and MariaDB vary and the application has to do more work in one environment than the other.

Copy the H2 scripts and rename to ‘-maria' rather than ‘-h2'.
You will need to remove H2 specific code. Check the repository to see the differences, especially the date parsing functions.

Use the scripts to create a schema and to add data to Maria.
Do this manually (i.e. run them from the command line or in MySQL Workbench) as we are going to turn off database initialisation in the application properties.

The first thing we need to do is split the properties into those which are common across all environments, and those that may be specific to each environment.

Common and default properties

If there are common or default properties, then we leave those in application.properties. In our case, we want to default the profile to use H2 for both builds and for bootrun. So, we set one property. We'll see this property again later.

In application.properties

spring.profiles.active=h2

A profile that uses H2

We create a new file called application-h2.properties. This implicitly creates a profile called ‘h2'.

We put the H2 database connection properties into this file, plus some others. We'll set the

In **application-h2.properties**

server.port=8080 spring.devtools.restart.poll-interval=2s spring.devtools.restart.quiet-period=1s

turn on the console for development purposes

spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:testdb

set credentials explicitly

spring.datasource.username=sa spring.datasource.password=

make clear which data to load into h2. the value matches the suffix on the data.sql and schema.sql files

spring.datasource.platform=h2

spring.jpa.hibernate.ddl-auto=none

logging.level.uk.ac.cf.cs.cm6213.tutorialcompanion=debug

### A profile that uses MariaDB

The reason for introducing profiles is to support MariaDB.  Before we can do that, we
need to add the MariaDB driver to our dependencies in ```build.gradle```.

In **build.gradle**

```java
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:2.7.4'

We now create a new file called application-maria.properties.
This implicitly creates a profile called ‘maria'.

We put the MariaDB database connection properties into this file.

In application-maria.properties

###  MariaDB Settings
server.port=9090

spring.datasource.url=jdbc:mariadb://localhost:3306/charity_giving?useSSL=false&requireSSL=false&serverTimezone=UTC

#set credentials explicitly
spring.datasource.username=root
spring.datasource.password=comsc

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver


#make clear which data to load into maria.  
#the value matches the suffix on the data.sql and schema.sql files

spring.datasource.platform=maria

spring.jpa.hibernate.ddl-auto=none
spring.datasource.initialization-mode=never

logging.level.uk.ac.cf.cs.cm6213.tutorialcompanion=info

The database URL now points at MariaDB and takes the MariaDB credentials.

We also turn off database initialisation at app startup, and we turn down the logging level.

We also set the server port to 9090.

You can use Spring Boot profiles from the command line as well.
If you build your application (using gradle build or gradle assemble) you will get an executable JAR file in /build/libs.
Let's assume this Jar file is called app.jar.

Open a command line, and navigate to this folder.

Run the following command:

At the command line

java -jar app.jar --spring.profiles.active=h2

or

java -jar app.jar --spring.profiles.active=maria

depending on the profile that you want to run.

We can now build and run tests against H2, and can run quick demos using bootrun against H2. For external deployment (for testing, staging or production) we can run against MariaDB from the command line.

This is optional and is not included in the repository.

We would like to be able to run a Gradle task that starts the application in a specific profile.
To do this, we add some task configuration to build.gradle.

In build.gradle

tasks.bootRun.configure {
    systemProperty("spring.profiles.active", "h2")
}

tasks.register("bootRunProd") {
    group = "application"
    description = "Runs the Spring Boot application with the maria profile"
    doFirst {
        tasks.bootRun.configure {
            systemProperty("spring.profiles.active", "maria")
        }
    }
    finalizedBy("bootRun")
}

The first tasks configuration changes the default ‘bootrun' task so that it uses the ‘h2' profile.

The second tasks configuration registers a new Gradle task called ‘bootRunProd' which will call ‘bootRun', but first changes the profile to ‘maria'.

We can then run the application in different profiles by running the different tasks.

You can also use profiles to select components.

Add @Profile("h2") (at class level) to tell Spring Boot that a component should only be included when running in ‘h2' profile.

For example, you may end up with something like this:

On any Spring Bean

@Component
@Profile("h2")
public class DonationController {

This could be useful when integrating with external systems. It would be a typical pattern to implement a gateway component to an external service. The gateway simplifies the calls to the external service. Using profiles, a different implementation of the gateway could be used on certain environments.

See the Spring Boot documentation for more details.

Spring Boot provides a number of options for database initialisation.

If you want to use MariaDB for testing or for demonstration purposes, you may wish to tell Spring Boot to run a script at start-up.

See Database Initialization for more options.

For a real stretch, look at Liquibase or Flyway and think about how to manage changes to the database. To get a real feel for this, try to imagine that you put a version of your code out for use with real users who generate data in your database. Then, imagine that you are succesful world-wide and there isn't a good time to take the system down to make a database change. These are real-world problems, so good to start thinking about them now. For patterns that help in this area, look up "Continuous Delivery" especially the book by Jez Humble and Dave Farley.