How to set up different databases per environment in Play 2.0?
Asked Answered
S

5

23

I'd like my Play app to use different databases for test, local and production (production is Heroku) environments.

In application.conf I have:

db.default.driver=org.postgresql.Driver 

%dev.db.default.url="jdbc:postgresql://localhost/foobar" 
%test.db.default.url="jdbc:postgresql://localhost/foobar-test" 
%prod.db.default.url=${DATABASE_URL} 

This doesn't seem to work. When I run play test or play run, all DB access fails with:

 Configuration error [Missing configuration [db.default.url]] (Configuration.scala:258) 

I have a few questions about this:

  • In general, I'm a little confused about how databases are configured in Play: it looks like there's plain db, db.[DBNAME] and db. [DBNAME].url and different tutorials make different choices among those. Certain expressions that seem like they should work (e.g. db.default.url = "jdbc:..." fail with an error that a string was provided where an object was expected).

  • I've seen other people suggest that I create separate prod.conf, dev.conf and test.conf files that each include application.conf and then contain DB-specific configuration. But in that case, how do I specify what database to use when I run test from the Play console?

  • Is the %env syntax supposed to work in Play 2?

  • What's the correct way to specify an environment for play test to use?

Sogdiana answered 30/4, 2012 at 23:52 Comment(0)
H
21

In Play 2 there aren't different config environments. Instead you just set or override the config parameters in the conf/application.conf file. One way to do it is on the play command line, like:

play -Ddb.default.driver=org.postgresql.Driver -Ddb.default.url=$DATABASE_URL ~run

You can also tell Play to use a different config file:

play -Dconfig.file=conf/prod.conf ~run

For an example Procfile for Heroku, see:
https://github.com/jamesward/play2bars/blob/scala-anorm/Procfile

More details in the Play Docs:
http://www.playframework.org/documentation/2.0/Configuration

Haversine answered 1/5, 2012 at 2:31 Comment(4)
Hmm, that makes sense - so those %prod tips were for Play 1.x? Thanks for the examples. I actually have the dev/prod configuration issue worked out at this point. My remaining question is still: how do I configure Play to use a different environment when running the test suite?Sogdiana
Yes, the %prod stuff is Play 1.x only. You should be able to do the same thing when you run the tests: play -Dsetting=foo ~testHaversine
That's true, but it seems very error-prone: if I accudentally leave off the config file name, my (potentially destructive) test suite will run against my dev database. Isn't there another way to do this? The %prod approach from Play 1 seems more than sufficient, not sure why it's not available anymore.Sogdiana
You could leave application.conf essentially empty and then have dev.conf, test.conf, and prod.conf files. If values are common then you could put them in application.conf and then include application.conf in the other conf files.Haversine
P
13

At least in Play 2.1.1 it is possibly to override configuration values with environment variables, if they are set. (For details see: http://www.playframework.com/documentation/2.1.1/ProductionConfiguration)

So you can set the following in your conf/application.conf:

db.default.url="jdbc:mysql://localhost:3306/my-db-name"
db.default.url=${?DATABASE_URL_DB}

per default it will use the JDBC-URL defined unless the environment variable DATABASE_URL_DB defines a value for it. So you just set your development database in the configuration and for production or stages you define the environment variable.

But beware, this substitution does NOT WORK if you put your variable reference inside quoted strings:

db.default.url="jdbc:${?DATABASE_URL_DB}"

Instead, just unquote the section to be substituted, for example.

database_host = "localhost"
database_host = ${?ENV_DATABASE_HOST}
db.default.url="jdbc:mysql://"${?database_host}":3306/my-db-name"

In this example, localhost will be used by default if the environment variable ENV_DATABASE_HOST is not set. (For details see: https://www.playframework.com/documentation/2.5.x/ConfigFile#substitutions)

Prado answered 27/4, 2013 at 14:11 Comment(1)
That's an awesome feature!Arched
C
2

You can actually still use the Play 1.0 config value naming method, in Play 2, if you, when you load config values, check if Play.isTest, and then prefix the properties you load with 'test.'. Here's a snipped:

def configPrefix = if (play.api.Play.isTest) "test." else ""

def configStr(path: String) =
  Play.configuration.getString(configPrefix + path) getOrElse
     die(s"Config value missing: $configPrefix$path")

new RelDb(
  server = configStr("pgsql.server"),
  port = configStr("pgsql.port"),
  database = configStr("pgsql.database"),
  user = ...,
  password = ...)

And the related config snippet:

pgsql.server="192.168.0.123"
pgsql.port="5432"
pgsql.database="prod"
...

test.pgsql.server="192.168.0.123"
test.pgsql.port="5432"
test.pgsql.database="test"
...

Now you don't need to remember setting any system properties when you run your e2e test suite, and you won't accidentally connect to the prod database.

I suppose that you can optionally place the test. values in a separate file, which you would then include at the end of the main config file I think.

Cariole answered 9/1, 2013 at 1:22 Comment(0)
T
0

There is another approach which is to override Global / GlobalSettings method onLoadConfig and from there you can setup application configuration with generic config and specific environment configuration like below...

conf/application.conf --> configurations common for all environment
conf/dev/application.conf --> configurations for development environment
conf/test/application.conf --> configurations for testing environment

conf/prod/application.conf --> configurations for production environment

You can check http://bit.ly/1AiZvX5 for my sample implementation.

Hope this helps.

Troublesome answered 19/5, 2015 at 16:28 Comment(0)
H
0

Off-topic but if you follow 12-factor-app then having separate configurations named after environments is bad:

Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called “environments”) named after specific deploys, such as the development, test, and production environments in Rails. This method does not scale cleanly: as more deploys of the app are created, new environment names are necessary, such as staging or qa. As the project grows further, developers may add their own special environments like joes-staging, resulting in a combinatorial explosion of config which makes managing deploys of the app very brittle

source: http://12factor.net/config

Hauser answered 2/8, 2016 at 0:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.