Skip to content

zoosky/pureconfig

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

99 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PureConfig

A boilerplate-free Scala library for loading configuration files

Build Status Maven Central Join the chat at https://gitter.im/melrief/pureconfig

Why

Loading configurations has always been a tedious and error-prone procedure. A common way to do it consists in writing code to deserialize each fields of the configuration. The more fields there are, the more code must be written (and tested and maintained...) and this must be replicated for each project.

This kind of code is boilerplate because most of the times the code can be automatically generated by the compiler based on what must be loaded. For instance, if you are going to load an Int for a field named foo, then probably you want some code that gets the values associated with the key foo in the configuration and assigns it to the proper field after converting it to Int.

The goal of this library is to create at compile-time the boilerplate necessary to load a configuration of a certain type. In other words, you define what to load and PureConfig provides how to load it.

Not yet another configuration library

PureConfig is not a configuration library in the sense that it doesn't search for files or parse them. It can be seen as a better front-end for the existing libraries. It uses typesafe config library for loading raw configurations and then uses the raw configurations to do its magic.

Add PureConfig to your project

In the sbt configuration file:

use scala 2.10 or 2.11:

scalaVersion := "2.11.8" // or "2.10.5"

Add the library. For scala 2.11

libraryDependencies ++= Seq(
  "com.github.melrief" %% "pureconfig" % "0.3.0"
)

For scala 2.10 you need also the scala macro paradise plugin:

libraryDependencies ++= Seq(
  "com.github.melrief" %% "pureconfig" % "0.3.0",
compilerPlugin("org.scalamacros" % "paradise" % "2.0.1" cross CrossVersion.full)
)

For a full example of build.sbt you can have a look at this build.sbt used for the example.

Example

In the example directory there is an example of usage of pureconfig. In the example, the idea is to load a configuration for a directory watcher service. The configuration file (a real one is available here) for this program will look like

dirwatch.path="/path/to/observe"
dirwatch.filter="*"
dirwatch.email.host=host_of_email_service
dirwatch.email.port=port_of_email_service
dirwatch.email.message="Dirwatch new path found report"
dirwatch.email.recipients=["recipient1,recipient2"]
dirwatch.email.sender="sender"

To load it, we define some classes that have proper fields and names

import java.nio.file.Path

case class Config(dirwatch: DirWatchConfig)
case class DirWatchConfig(path: Path, filter: String, email: EmailConfig)
case class EmailConfig(host: String, port: Int, message: String, recipients: Set[String], sender: String)

The use of Path gives us a chance to use a custom converter

import pureconfig._

import java.nio.file.Paths
import scala.util.Try

implicit val deriveStringConvertForPath = fromString[Path](Paths.get)

And then we load the configuration

val config = loadConfig[Config].get // loadConfig returns a Try

And that's it.

You can then use the configuration as you want:

println("dirwatch.path: " + config.dirwatch.path)
println("dirwatch.filter: " + config.dirwatch.filter)
println("dirwatch.email.host: " + config.dirwatch.email.host)
println("dirwatch.email.port: " + config.dirwatch.email.port)
println("dirwatch.email.message: " + config.dirwatch.email.message)
println("dirwatch.email.recipients: " + config.dirwatch.email.recipients)
println("dirwatch.email.sender: " + config.dirwatch.email.sender)

It's also possible to operate directly on Config and ConfigValue types of typesafe config with the implicit helpers provided in the pureconfig.syntax package:

import com.typesafe.config.ConfigFactory
import pureconfig.syntax._

val config = ConfigFactory.load().to[Config].get
println("The loaded configuration is: " + config.toString)

Whence the config files?

By default, PureConfig's loadConfig() methods load all resources in the classpath named:

  • application.conf,
  • application.json,
  • application.properties, and
  • reference.conf.

The various pureconfig.loadConfig() methods defer to typesafe config's ConfigFactory to select where to load the config files from. Typesafe Config has well-documented rules for configuration loading which we'll not repeat. Please see Typesafe Config's documentation for a full telling of the subtleties. If you need greater control over how config files are loaded, refer to ConfigFactory's options.

Alternatively, PureConfig also provides pureconfig.loadConfigFromFiles() which builds a configuration from an explicit list of files. Files earlier in the list have greater precedence than later ones. Each file can include a partial configuration as long as the whole list produces a complete configuration. For an example, see the test of loadConfigFromFiles() in PureconfSuite.scala.

Because PureConfig uses Typesafe Config to load configuration, it supports reading files in HOCON, JSON, and Java .properties formats. HOCON is a delightful superset of both JSON and .properties that is highly recommended. As an added bonus it supports advanced features like variable substitution and file sourcing.

License

Mozilla Public License, version 2.0

Special Thanks

To the Shapeless and to the Typesafe config developers.

About

A boilerplate-free library for loading configuration files

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Scala 99.3%
  • Shell 0.7%