Spring Boot Environment-specific configurations

environment, jpa, microservices, spring-boot, spring-mvc

Solution

Thanks to @Richard for the mention of `spring.profiles.active` JVM variable. Since my question was specific to the way Spring Boot does this and since there is much more to the answer, I am inclined to answer this myself and include all the details of how I arrived at the answer in the hopes that it will save others time.

First, you can indeed pick the correct profile on the `java` command line by adding `-Dspring.profiles.active=profile_name` when you are running your Spring Boot app. (this is assuming your deployment preference is an uber jar with embedded container - Tomcat in my case)

I wanted to leave MySQL datasource configurations under the default profile and put H2 in-memory datasource configuration under a test profile. However, the way Spring Boot picks the right datasource based on profile is not so obvious. Even though I had MySQL details under the default profile and I had the in-memory H2 datasource details under the test profile, it would still pick H2 as the datasource even when `spring.profiles.active` was omitted from the command line. This was contrary to my assumption that default profile will be picked, well, by default :-)

I ended up having to put H2 configuration under the default profile and then create a local profile that included the MySQL datasource configuration. Here's what I ended up with in my `application.yml`

spring:
  profiles: default 

spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:sampletest;MODE=MySQL

---
spring:
  profiles: test

spring.jpa:
    hibernate:
      ddl-auto: create-drop

---
spring:
  profiles: local

spring.datasource:
  driverClassName: com.mysql.jdbc.Driver
  url: jdbc:mysql://127.0.0.1/sampledev
  username: sample
  password: sample

spring.jpa:
  hibernate:
    dialect: org.hibernate.dialect.MySQLInnoDBDialect
    ddl-auto: update

This worked. I was able to switch between default profiles and the local profile by omitting or adding the `-Dspring.profiles.active=local` on the `java` command line. Because test profile inherits from default it is also using H2

One more nuance: I added `ddl-auto: create-drop` to the test profile which uses the in-memory DB to facilitate automatic table creation / teardown for unit tests. But for the local profile which uses MySQL I changed it to `update`. Implication being that for the local profile I have to first create the database outside of the application.

Problem

I have a spring boot application that uses the actuator, auto-configuration and JPA. I want to be able to use an in-memory DB in my test profile, a MySQL DB configuration during development and a separate production DB configuration when the app is deployed in production. Presumably from the java command line I should be able to specify the environment and the right configuration file or config block in application.properties (or .yml) will be picked up. I have not found a good post with example describing how to do this switching so I thought I'd ask if anyone has a good example. My main aim is to pre-define the `spring.datasource` and `spring.jpa` properties at build time and then at run-time switch the app config per environment "dynamically" using the java command line argument. Secondary goal would be to do the same with the `management` configurations, etc. Thank you.

Original source