So we progress with the series of posts for .NET devs that may want to try their luck with Scala. This time, we will be talking about configuration.
As I have stated quite a lot already, I am a seasoned .NET developer that is getting into Scala.
Those of you that have worked in the .NET space will know that you can use the CofigurationManager
class to help you read App.Config, or Web.Config file. Where the XXX.Config files are stored as XML, a typical example being something like the ones shown below:
="1.0" ="utf-8"
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="ConsoleAppender"
type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date
[%4.4thread] %-5level %20.20logger{1} - %message%newline" />
</layout>
</appender>
<appender name="RollingLogFileAppender"
type="log4net.Appender.RollingFileAppender">
<file value="Client.log" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="yyyyMMdd" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="1MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%4.4thread]
%-5level %20.20logger{1} - %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<runtime>
<loadFromRemoteSources enabled="true" />
</runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin"
publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0"
newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security"
publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0"
newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json"
publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0"
newVersion="7.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Cors"
publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.2.0"
newVersion="5.2.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
The .NET configuration system is also quite flexible in that it allows you to create custom sections, but this requires a lot of code.
Here is an example: https://msdn.microsoft.com/en-us/library/2tw134k3.aspx up on date 12/11/15
We want to add a custom section which contains 2 properties:
So we would have to add code similar to this to the actual XXXX.config file:
<configuration>
-->
<configSections>
<sectionGroup name="pageAppearanceGroup">
<section
name="pageAppearance"
type="Samples.AspNet.PageAppearanceSection"
allowLocation="true"
allowDefinition="Everywhere"
/>
</sectionGroup>
-->
</configSections>
-->
<pageAppearanceGroup>
<pageAppearance remoteOnly="true">
<font name="TimesNewRoman" size="18"/>
<color background="000000" foreground="FFFFFF"/>
</pageAppearance>
</pageAppearanceGroup>
</configuration>
And also create the following C# code to create this custom set of XML tags:
using System;
using System.Collections;
using System.Text;
using System.Configuration;
using System.Xml;
namespace Samples.AspNet
{
public class PageAppearanceSection : ConfigurationSection
{
[ConfigurationProperty("remoteOnly",
DefaultValue = "false", IsRequired = false)]
public Boolean RemoteOnly
{
get
{
return (Boolean)this["remoteOnly"];
}
set
{
this["remoteOnly"] = value;
}
}
[ConfigurationProperty("font")]
public FontElement Font
{
get
{
return (FontElement)this["font"]; }
set
{ this["font"] = value; }
}
[ConfigurationProperty("color")]
public ColorElement Color
{
get
{
return (ColorElement)this["color"];
}
set
{ this["color"] = value; }
}
}
public class FontElement : ConfigurationElement
{
[ConfigurationProperty("name",
DefaultValue="Arial", IsRequired = true)]
[StringValidator(InvalidCharacters =
"~!@#$%^&*()[]{}/;'\"|\\", MinLength = 1, MaxLength = 60)]
public String Name
{
get
{
return (String)this["name"];
}
set
{
this["name"] = value;
}
}
[ConfigurationProperty("size",
DefaultValue = "12", IsRequired = false)]
[IntegerValidator(ExcludeRange = false, MaxValue = 24, MinValue = 6)]
public int Size
{
get
{ return (int)this["size"]; }
set
{ this["size"] = value; }
}
}
// Define the "color" element
// with "background" and "foreground" attributes.
public class ColorElement : ConfigurationElement
{
[ConfigurationProperty("background",
DefaultValue = "FFFFFF", IsRequired = true)]
[StringValidator(InvalidCharacters =
"~!@#$%^&*()[]{}/;'\"|\\GHIJKLMNOPQRSTUVWXYZ", MinLength = 6, MaxLength = 6)]
public String Background
{
get
{
return (String)this["background"];
}
set
{
this["background"] = value;
}
}
[ConfigurationProperty("foreground",
DefaultValue = "000000", IsRequired = true)]
[StringValidator(InvalidCharacters =
"~!@#$%^&*()[]{}/;'\"|\\GHIJKLMNOPQRSTUVWXYZ", MinLength = 6, MaxLength = 6)]
public String Foreground
{
get
{
return (String)this["foreground"];
}
set
{
this["foreground"] = value;
}
}
}
}
Which we can then access from code like this:
Samples.AspNet.PageAppearanceSection config =
(Samples.AspNet.PageAppearanceSection)System.Configuration.ConfigurationManager.GetSection(
"pageAppearanceGroup/pageAppearance");
var cfgFont = config.Font.Name
Phew, that’s a lot of work.
There are other ways to do this in C#. I am thinking of the awesome SimpleConfig
GitHub repo, which in my opinion is well underrated and something that we should all use in our .NET projects.
https://github.com/mikeobrien/SimpleConfig up on date 12/11/15
Using this, we can now write code like this (instead of the above, which is a BIG improvement if you ask me).
First, create your configuration types:
public class MyApplication
{
public Build Build { get; set; }
}
public enum Target { Dev, CI }
public class Build
{
public string Version { get; set; }
public DateTime Date { get; set; }
public Target DeployTarget { get; set; }
}
Next, you need to register the SimpleConfig
section handler in your web/app.config and create your configuration section as shown below. The default convention for the section name is the camel cased name of the root configuration type (Although you can override this as we’ll see later). The section name under configSections
must match the section element name. All other element and attribute names in the configuration section are case insensitive but must otherwise match the property names of your configuration types (You can override this as well).
<configuration>
<configSections>
<section name="myApplication"
type="SimpleConfig.Section, SimpleConfig"/>
</configSections>
<myApplication>
<build version="0.0.0.0"
date="10/25/1985" deployTarget="Dev"/>
</myApplication>
</configuration>
Now you can load the section either by calling the convenience static
method or newing up a new instance:
ar config = Configuration.Load<MyApplication>();
var config = new Configuration().LoadSection<MyApplication>();
config.Build.Date.ShouldEqual(DateTime.Parse("10/25/1985"));
config.Build.DeployTarget.ShouldEqual(Target.Dev);
config.Build.Version.ShouldEqual("0.0.0.0");
This is cool, however Scala does it even better. The rest of this post will be about the awesome Typesafe Config library (Typesafe are the people behind Akka (I like Akka)).
Typesafe Config Library
The guys from Typesafe have an awesome config library (https://github.com/typesafehub/config) that you may use with either Java/Scala, and it supports the following 3 formats:
- JSON
- Java properties
- HOCON (Human-Optimized Config Object Notation)
For everything I demonstrate here, I will be using the following HOCON file.
sachas.business {
owner {
name = "sacha barber"
description = ${sachas.business.owner.name} "is the owner"
}
team {
members = [
"sacha barber"
"chris baker"
"paul freeman"
"ryan the mad one"
]
}
}
sachas.business.team.avgAge = 35
If you want to try this out in your own scala project, you will need to add it as a SBT library dependency, using this (the version shown here was right at the time of this post being published).
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "0.4.0"
)
So what can this Typesafe library do?
Well it essentially reads configuration information from file(s). This would typically be done using a application.conf file, which would be placed in your resources folder.

After you have a file, we can proceed to load it using the ConfigFactory, which you can use like this:
import com.typesafe.config.ConfigFactory
object ClassesDemo {
def main(args: Array[String]) : Unit =
{
val config = ConfigFactory.load("application.conf")
.....
.....
.....
System.in.read()
}
}
Well, let’s start simple by using the HOCON file we outlined above:
import com.typesafe.config.ConfigFactory
object ClassesDemo {
def main(args: Array[String]) : Unit =
{
val config = ConfigFactory.load("application.conf")
val ownerName = config.getString
("sachas.business.owner.name") val desc = config.getString
("sachas.business.owner.description") val age = config.getInt
("sachas.business.team.avgAge ") val members = config.getStringList
("sachas.business.team.members")
System.in.read()
}
}
It can be seen that we can easily drill into the tree of properties, and use the getXXX
methods to grab string
s, list and all sorts of goodness.
The above code gives this result:

Pretty simple huh!
The Config
object has these helper methods to enable you to read configuration values:
getAnyRef
getAnyRefList
getBoolean
getBooleanList
getByte
getByteList
getConfig
getConfigList
getDouble
getDoubleList
getInt
getIntList
getList
getLong
getLongList
getMilliSeconds
getMilliSecondsList
getNanoSeconds
getNanoSecondsList
getNumber
getNumberList
getObject
getObjectList
getString
getStringList
getValue
I think most of these are quite obvious, perhaps the only one that I personally feel may need a bit more of an explanation are the getObject
/getObjectList
methods. So let’s have a look at a specific example for this.
Say we have this HOCON file:
ecoders = [ { a : "socket://1.2.3.4:9000" },
{ b : "socket://1.2.3.4:8080" },
{ c : "socket://9.9.9.9:9001" },
{ d : "socket://9.9.8.8:9000" },
{ e : "socket://4.3.2.1:8081" } ]
Which we then read in like this:
import com.typesafe.config.{ConfigObject, ConfigValue, ConfigFactory, Config}
import scala.collection.JavaConverters._
import java.net.URI
import java.util.Map.Entry
case class Settings(config: Config) {
lazy val decoders : Map[String, URI] = {
val list : Iterable[ConfigObject] = config.getObjectList("decoders").asScala
(for {
item : ConfigObject <- list
entry : Entry[String, ConfigValue] <- item.entrySet().asScala
key = entry.getKey
uri = new URI(entry.getValue.unwrapped().toString)
} yield (key, uri)).toMap
}
}
object ClassesDemo {
def main(args: Array[String]) : Unit =
{
val config = ConfigFactory.load("smallerList.conf")
val decoders = new Settings(config).decoders
System.in.read()
}
}
Which gives us the following results:

I have shamelessly stolen this example from this blog, which is a very nice example in my opinion:
Further Readings
I came across a couple of good blogs on this whilst writing my own post. These are outlined here: