Posts Working With Config
Post
Cancel

Working With Config

We will first start by adding demo config to our app and reading it manually.
Add the following to your conf/application.conf (not inside, but rather under play’s blob):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: hotels_best_dishes
host: "https://example.com"
port: 80
hotels: [
  "Club Hotel Lutraky Greece",
  "Four Seasons",
  "Ritz",
  "Waldorf Astoria"
]
min-duration: 2 days
application-id: 00112233-4455-6677-8899-aabbccddeeff
ssh-directory: /home/whoever/.ssh
developer: {
  name: alice,
  age: 20
}

We will read values from the config and convert each one to an appropriate built-in type.
We will also convert the developer value to a custom Person class.

In the project tool window (CMD+1), right click on app and select New -> Scala Class and create a case class called com.example.playground.configuration.Person.
Add a name and an age to it. e.g:

1
case class Person(name: String, age: Int)

Go to app/controllers/HomeController.scala and inject an instance of a Configuration object to this class by adding config: Configuration as a constructor parameter.
The order of the constructor parameters does not matter - Guice will create a new instance for each of the class parameters using Eligible Constructors, @ImplementedBy or @ProvidedBy.

Side note: 99% of the time, “injecting a dependency” is just a fancy way of saying “passing it as an argument using the consructor”.
Your classes will usually be either service classes (that provide behaviour) or value classes (that represent information. such classes are represented in scala with case class).
As a rule of thumb, while you can create value objects anywhere, you want to inject your services, so that you will be able to inject another service, possibly a mock, when testing or running locally.
With object oriented programming, an object also contains its behaviors. Although you will not have a clear separation, you want to inject the object’s services.

Change the index method so that it will read the config values to the appropriate types.
Then print them to the sbt console and describe the config in the response.
Try to do this without copy-paste.

The method should be similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.net.URL
import java.nio.file.Paths
import java.util.UUID
import scala.concurrent.duration.FiniteDuration
import com.example.playground.configuration.Person

// class definition here

def index() = Action { implicit request: Request[AnyContent] =>
  val name = config.get[String]("name")
  val host = config.get[URL]("host")
  val port = config.get[Int]("port")
  val hotels = config.underlying.getStringList("hotels") // notice that getting a Person list here will be more complex
  val minDuration = config.get[FiniteDuration]("min-duration")
  val applicationId = UUID.fromString(config.get[String]("application-id"))
  val sshDirectory = Paths.get(config.get[String]("ssh-directory"))
  val developer = Person(config.get[String]("developer.name"), config.get[Int]("developer.age"))

  val message =
    s"""
       |name: $name
       |host: $host
       |port: $port
       |hotels: $hotels
       |minDuration: $minDuration
       |applicationId: $applicationId
       |sshDirectory: $sshDirectory
       |developer: $developer
       |""".stripMargin
  println(message)
  Ok(message)
}

Run the app by running run inside the sbt shell and browse to http://localhost:9000/.
You should see the config.