How to Configure Your Application for Different Environments with Play Framework

Managing application configurations for the Play Framework projects isn’t really straightforward. When you start a new project with Play, you typically have only one application.conf file with global settings. But then you need to configure the project for different environments, and you begin to create application.dev.confapplication.test.confapplication.demo.conf, and other *.conf files by copying the global settings from application.conf to those files and changing necessary options for different environments.

The described approach, however, leads to a couple of problems:

  • You repeat the same configurations in many files, which defies the Don’t Repeat Yourself principle.
  • You may forget to change an important global setting in some of the configuration files.

The second problem can be especially annoying when you want to run a quick demo, but you didn’t update the configurations for the demo environment, and the application starts working incorrectly or even can’t run due to errors.

We’re going to review a simple way to avoid such situations and to efficiently manage the configurations for your Play Framework projects.

Breaking App Configurations into Smaller Configs

Let’s have a look at a typical application.conf file you start with when developing a new project based on Play Framework:

# project_name/conf/application.conf
# ...
slick.dbs {
    default {
        profile = "slick.jdbc.PostgresProfile$"
        db {
            driver = "org.postgresql.Driver"
            url = "jdbc:postgresql://localhost:5432/first_db"
            user = "user"
            password = "password"
            connectionTimeout = 10s
       }
   }
}    

gitlab {
    url = "http://local-gitlab.com"
    users {
        root {
            email = "rootgitlab@local-gitlab.com"
            password = "password"
        }
    }
}

play.modules.enabled += "modules.UserModule"
# ...Code language: PHP (php)

To break the application.conf into separate files that will contain only specific settings, you can copy-paste the Slick configurations to conf/default/slick.conf, GitLab configs to conf/default/gitlab.conf, and so on, and then import these configurations into application.conf.

For example, the play.modules.conf file under conf/default/ will look like this:

# project_name/conf/default/play.modules.conf
# ...
play.modules.enabled += "modules.UserModule"
# ...Code language: PHP (php)

And the conf/ directory will have the following structure:

conf/
├── default/
    ├── gitlab.conf
    ├── play.modules.conf
    └── slick.conf
└── application.confCode language: JavaScript (javascript)

Your application.conf file will only need to import the concrete configurations from the default/ directory using include:

# ...
include "default/play.modules.conf"
include "default/slick.conf"
include "default/gitlab.conf"
# ...Code language: PHP (php)

Creating Development Configuration

You can set up the development environment with the same approach as we described in the previous section. First, you need to create the application.dev.conf file that will be importing configurations for the development environment.

Next, you need to create the conf/dev/ directory next to conf/default/ and save files with the development settings: dev/slick.conf and dev/gitlab.conf.

Finally, include these files into application.dev.conf:

# ...
include "application.conf"

include "dev/slick.conf"
include "dev/gitlab.conf"
# ...Code language: PHP (php)

Notice that the application.dev.conf file first imports the default application configurations from application.conf and only after that does it import the specific settings from dev/. Also note that the development configs are included last and, therefore, they overwrite the default settings.

After all the arrangements, the conf/ directory structure looks like this:

conf/
├── default/
    ├── gitlab.conf
    ├── play.modules.conf
    └── slick.conf
├── dev/
    ├── gitlab.conf
    └── slick.conf
├── application.dev.conf
└── application.confCode language: JavaScript (javascript)

Now, to run your project with a specific configuration, just pass an argument — the name of the configuration file — to the -Dconfig.resource property:

sbt "run -Dconfig.resource=application.dev.conf"Code language: JavaScript (javascript)

This modular-ish DRY approach that we described will allow you to easily manage and scale settings for development, test, production, and other environments for your Play Framework-based applications.