ygor
ygor

Reputation: 1756

How is Spring Boot aware of Heroku's DATABASE_URL config var?

Short story:

How exactly does Spring Boot parse the DATABASE_URL config var? Setting an environment property with same name on my local PC has no effect. Which classes in Spring Boot library are involved? Full text search on DATABASE_URL returns nothing.

Long story:

I have recently deployed a simple Spring Boot + JPA application to Heroku. My heroku was already configured with the Postgres add-on.

During my first deployment I only wanted to confirm, that the application builds and starts correctly. To my surprise though, the application immediately connected to the Postgres database configured in Heroku's DATABASE_URL config var:

2018-11-30T09:28:51.054688+00:00 app[web.1]: 2018-11-30 09:28:51.054  INFO 4 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL95Dialect

This leads me to the questions already posted above.

I am using Spring boot 2.1.0., a simple app created by Spring Initializr, with Web + JPA + H2 + PostgreSQL. H2 is included, because:

Upvotes: 4

Views: 3327

Answers (3)

ygor
ygor

Reputation: 1756

I will answer my own question, to amend the accepted answer with more details about environment properties set by Heroku.

Assuming, that your Heroku application contains environment variable:

  • DATABASE_URL = postgres://username:password@host:port/database

Heroku will automatically provide following environment variables (which you can use e.g. in your favorite JDBC based SQL client):

  • JDBC_DATABASE_URL = jdbc:postgresql://host:port/database?user=username&password=password&sslmode=require
  • JDBC_DATABASE_USERNAME = username
  • JDBC_DATABASE_PASSWORD = password

And additionally those, that get picked up by Spring Boot automatically (which you can use to modify your local Spring boot profile:

  • SPRING_DATASOURCE_USERNAME = same as JDBC_DATABASE_USERNAME
  • SPRING_DATASOURCE_PASSWORD = same as JDBC_DATABASE_PASSWORD
  • SPRING_DATASOURCE_URL = same as JDBC_DATABASE_URL

I observed this, by using a simple REST endpoint:

@RequestMapping("/env")
public @ResponseBody Map<String, String> env() {
    return System.getenv();
}

Be careful, not to make the same mistake as I did: DATABASE_URL starts with postgres, while JDBC prefix for Postgres is postgresql. Using SPRING_DATASOURCE_URL with prefix jdbc:postgres:// will lead to following error:

Driver org.h2.Driver claims to not accept jdbcUrl, jdbc:postgres://....

Upvotes: 1

codefinger
codefinger

Reputation: 10318

Spring is not aware of DATABASE_URL (as far as I know). But it does detect and automatically use SPRING_DATASOURCE_URL, which the Heroku Java buildpack sets at runtime.

You can read more about this env var in the Heroku docs on Connecting to Relational Databases on Heroku with Java

Upvotes: 3

Herve MULUDIKI
Herve MULUDIKI

Reputation: 69

To be able to switch easily between h2 and heroku, one could have 2 configurations files

The h2 properties files named application-h2.properties :

spring.profiles.active=h2
spring.datasource.url= # H2 URL of the database.
spring.datasource.driver-class-name=# H2 JDBC driver. Auto-detected based on the URL by default.
spring.datasource.password= # Login password of the database.
spring.datasource.username= # Login username of the database.

Activated by setting the h2 profile to on when running the spring boot app:

java -jar -Dspring.profiles.active=h2 myApplication.jar

The heroku properties files named application-heroku.properties :

spring.profiles.active=heroku
spring.datasource.url= # herokuURL of the database.
spring.datasource.driver-class-name=# herokuJDBC driver. Auto-detected based on the URL by default.
spring.datasource.password= # Login password of the database.
spring.datasource.username= # Login username of the database.

Activated by setting the heroku profile to on when running the spring boot app:

java -jar -Dspring.profiles.active=heroku myApplication.jar

Upvotes: 2

Related Questions