Question

I am evaluating Spring 4 on Heroku and I am so far very impressed with both.

However, I am having trouble getting my Spring Boot app to run on Heroku. Everything is working fine, except Postgresql (I just get Connection Refused errors).

The problem will surely be to do with how I am setting up the DataSource but so far I've just been following a trial and error approach! I am not exactly sure how I am supposed to set-up the data source from the Heroku DATABASE_URL and I can't find any examples.

I have found spring-cloud by chance by searching on Google which looks promising but it doesn't explained anything about the DATABASE_URL. Also, it isn't even mentioned on Spring.IO so I am wondering if it is even an option for production use?

Was it helpful?

Solution

Spring Cloud is a good option. I don't know why it's not listed in spring.io - it should be, maybe it isn't quite out of incubation yet or something, but I have used it successfully. If you don't like using that I think you can probably just set the spring.datasource.url to the value Heroku gives you in its env var.

OTHER TIPS

You can use Config Vars which can be configured in the settings tab of your application at Heroku. The Config Vars will be exposed as environment variables to your application. Since Spring Boot can map environment variables to application properties you just need to set:

SPRING_DATASOURCE_URL
SPRING_DATASOURCE_USER
SPRING_DATASOURCE_PASSWORD
SPRING_DATASOURCE_DRIVER-CLASS-NAME

And they will be mapped to:

spring.datasource.url
spring.datasource.user
spring.datasource.password
spring.datasource.driver-class-name

Now all you have to do is to extract the relevant values. The complete data base configuration can be inspected at the heroku postgres management panel. Select the data base you want to connect to and you will see the values for SPRING_DATASOURCE_USER and SPRING_DATASOURCE_PASSWORD right away. The SPRING_DATASOURCE_URL has to be constructed like this:

jdbc:postgresql://<Host>:<Port>/<Database>

Where <Host>, <Port> and <Database>have to replaced by the corresponding values from the data base connection page. Last but not least the SPRING_DATASOURCE_DRIVER-CLASS-NAME has to be set to org.postgresql.Driver.

This way you can use the build in functionality of Spring Boot instead of adding environment specific configuration to your application. Note however, that Spring Boot has a specific order of reading external configuration. So you have to make sure there are no

  • Command line arguments (passed via the Procfile)
  • JNDI attributes from java:comp/env (don't know where those might be coming from in Heroku.)
  • Java System properties (can also be passed via the Procfile as -D arguments)

since those would override the OS environment variables.

One thing I would like to add after struggling with this for a while - just creating a configuration object is not sufficient with Heroku, even with the spring cloud connectors. You also have to explicitly declare the cloud profile (-Dspring.profiles.active=cloud) in your application Procfile.

Apart from DATABASE_URL, which is always there, Heroku creates 3 environment variables at Runtime. They are:

JDBC_DATABASE_URL
JDBC_DATABASE_USERNAME
JDBC_DATABASE_PASSWORD

As you may be aware, Spring Boot will automatically configure your database if it finds spring.datasource.* properties in your application.properties file. Here is an example of my application.properties

spring.datasource.url=${JDBC_DATABASE_URL}
spring.datasource.username=${JDBC_DATABASE_USERNAME}
spring.datasource.password=${JDBC_DATABASE_PASSWORD}
spring.jpa.show-sql=false
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

Hibernate / Postgres Dependencies

In my case I'm using Hibernate (bundled in spring-boot-starter-jpa with PostgreSQL, so I needed the right dependencies in my build.gradle:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile('org.postgresql:postgresql:9.4.1212')
}

If I remember right, I had the same problem and reading through the Heroku Postgres documentation I found that I needed to specify two extra connection properties for the DataSource.

I had to configure the following properties:

  • ssl=true
  • sslfactory=org.postgresql.ssl.NonValidatingFactory

Here's an example of a DataSource bean:

   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${database.driverClassName}" />
    <property name="url" value="${database.url}" />
    <property name="username" value="${database.username}" />
    <property name="password" value="${database.password}" />
    <property name="connectionProperties" value="ssl=true;sslfactory=org.postgresql.ssl.NonValidatingFactory"/>
</bean>

You of course need to add a PostgreSql library dependency.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top