Scala Config: Include another file.conf - scala

Currently, I have a resources/application.conf file which has the following keys:
development {
server = www.myapp.com
aws_key = my_aws_key
aws_secret = my_aws_secret
}
I would like to remove my aws_key and aws_secret from the file.
I was thinking of creating another file called resources/credentials.conf and storing my personal authentications there.
credentials {
aws_key = my_aws_key
aws_secret = my_aws_secret
}
and then include it some way in my application.conf or merge that config to the Config object in addition to application.conf.
credentials.conf would be git ignored. A sample file would be checked in credentials-sample.conf which each developer would change according to his own credentials and rename the sample file to credentials.conf
I tried different variation of include like
include "credentials"
include "credentials.conf"
include "./credentials.conf"
include file("./credentials.conf")
and so on.
I know I can pass it via system variables but I would like to try it like mentioned above. If you know of a better way, please let me know.

Typesafe Config provide the way to fallback from one configuration to another. You can try the ConfigFactory.Load() to load different config and use withFallback to line them up in your designated order. Such as:
ConfigFactory.Load("credentials.conf") withFallback ConfigFactory.Load("application.conf")

Inside your conf file, add
include "another_file.conf"
ie: https://github.com/cicco94/scala-akka-slick-demo/blob/master/src/main/resources/application.conf

Related

How to get property from application.property in Gatling

I'm trying to get some properties from an application.properties file in Gatling-Scala. I tried.
val properties: Config = ConfigFactory.load("application.properties")
val clientId: String = properties.getString("api.clientId")
I keep getting "com.typesafe.config.ConfigException$Missing No configuration setting found for key 'api'". I put the application.properties file inside src/test/resources/application.properties and also in the root folder of the project.
I tried also to put the same information inside src/test/resources/gatling.conf as follows:
gatling {
api {
clientId = "..."
}
}
But I get the error:
com.typesafe.config.ConfigException$Missing No configuration setting found for key 'gatling'
Is there something I'm missing?
I managed to get the information in the gatling.conf file by installing the plugin HOCON for .conf files and formatting it correctly.

Scala config lookup secrets

I have application.conf file which contains secrets(password for DB etc..) And this secret will be mounted as a file(the file content will contain the actual secrets) in the running pod. How can scala config library be tweaked to handle this. i.e
instead of normal application.conf
db {
user = "username"
password = "xxx"
}
I would have something like this...
db {
user = "username"
password = "${file_location}"
}
As the file is parsed, it should identify that the value of key password, needs to be resolved by looking up the file and loading its contents.
A simple function can be written to load the content of this file, how can this is be integrated with seamlessly with scala config. ie. The rest of the code will continue to use
config.getString(db.password)
I assume you are using configuration of HOCON format and Typesafe configuration library for it.
I don't think it has such feature out of the box, but as an possible alternative you can take a look at include feature - you can include content of another file into your application.conf:
db {
user = "username"
}
include /path/to/pod.conf //include env specific configuration file
and put inside /path/to/pod.conf:
db {
password = "pod_db_pass"
}
So eventually contents of both files will be merged inside application during loading, and your final config will contain password at path db.password
UPDATE
Another possible option load password from file and merge into config file with withFallback method. Example:
import com.typesafe.config._
val passord = "password_from_file"
val passwordConfig = ConfigFactory.parseString(s"db.password=$passord")
val applicationConfig = ConfigFactory.parseString(s"db.user=db_user")// Replace this with `ConfigFactory.load()`
val config = applicationConfig.withFallback(passwordConfig)
println(config)
Printout result:
Config(SimpleConfigObject({"db":{"password":"password_from_file","user":"db_user"}}))
Scatie: https://scastie.scala-lang.org/WW3weuqiT9WRUKfdrZgwcw

Typesafe: Read array of configs

My tasks.conf file looks like below
tasks = [
{
prop_1 = "string-1"
prop_2 = "string-2"
prop_3 = 3
},
{
prop_1 = "string-1"
prop_2 = "string-2"
prop_3 = 3
}
]
After successfully parsing the task.conf file (located outside jar / classpath) using val config: Config = ConfigFactory.parseFile(file), I've tried reading it as follows without success
config.getObjectList("tasks")
config.getConfigList("tasks")
It complains
ConfigException$Missing: No configuration setting found for key
'tasks'
Upon asserting whether or not the path exists using config.hasPath("tasks"), it returns false.
My queries are as follows:
Is the structure of my conf file correct? Even if it's correct, is there a better way to structure it?
If the structure of conf file is correct (since parseFile succeeds), then where am I going wrong in reading the file?
Looks like your config file could not be read! Your application is probably trying to read the default application.conf, and your tasks config key is not found there.
You could probably try:
ConfigSource.FromFile(path)
Use the complete absolute path and give it a try!

No configuration setting found for key typesafe config

Im trying to implement a configuration tool typesafehub/config
im using this code
val conf = ConfigFactory.load()
val url = conf.getString("add.prefix") + id + "/?" + conf.getString("add.token")
And the location of the property file is /src/main/resources/application.conf
But for some reason i'm receiving
com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'add'
File content
add {
token = "access_token=6235uhC9kG05ulDtG8DJDA"
prefix = "https://graph.facebook.com/v2.2/"
limit = "&limit=250"
comments="?pretty=0&limit=250&access_token=69kG05ulDtG8DJDA&filter=stream"
feed="/feed?limit=200&access_token=623501EuhC9kG05ulDtG8DJDA&pretty=0"
}
Everything looks configured correctly ?? do i missed something .
thanks,
miki
The error message is telling you that whatever configuration got read, it didn't include a top level setting named add. The ConfigFactory.load function will attempt to load the configuration from a variety of places. By default it will look for a file named application with a suffix of .conf or .json. It looks for that file as a Java resource on your class path. However, various system properties will override this default behavior.
So, it is likely that what you missed is one of these:
Is it possible that src/main/resources is not on your class path?
Are the config.file, config.resource or config.url properties set?
Is your application.conf file empty?
Do you have an application.conf that would be found earlier in your class path?
Is the key: add defined in the application.conf?
Are you using an IDE or sbt?
I had a similar problem while using Eclipse. It simply did not find the application.conf file at first and later on failed to notice edits.
However, once I ran my program via sbt, all worked just fine, including Eclipse. So, I added 'main/resources' to the libraries (Project -> Properties -> Java Build Path -> Libraries", "add class folder"). That might help you as well.
Place your application.conf in the src folder and it should work
I ran into this issue inside a Specs2 test that was driven by SBT. It turned out that the issue was caused by https://github.com/etorreborre/specs2/issues/556. In that case, the Thread's contextClassLoader wasn't using the correct classloader. If you run into a similar error, there are other versions of ConfigFactory.load() that allow you to pass the current class's ClassLoader instead. If you're using Specs2 and you're seeing this issue, use a version <= 3.8.6 or >= 4.0.1.
Check you path. In my case I got the same issue, having application.conf placed in src/main/resources/configuration/common/application.conf
Incorrect:
val conf = ConfigFactory.load(s"/configuration/common/application.conf")
Correct
val conf = ConfigFactory.load(s"configuration/common/application.conf")
it turned out to be a silly mistake i made.
Following that, i does not matter if you use ":" or "=" in .conf file.
Getting the value from example:
server{
proc {
max = "600"
}
}
conf.getString("server.proc.max")
Even you can have the following conf:
proc {
max = "600"
}
proc {
main = "60000"
}
conf.getString("proc.max") //prints 600
conf.getString("proc.min") //prints 60000
I ran into this doing a getString on an integer in my configuration file.
I ran into exactly the same problem and the solution was to replace = with : in the application.conf. Try with the following content in your application.conf:
add {
token: "access_token=6235uhC9kG05ulDtG8DJDA"
prefix: "https://graph.facebook.com/v2.2/"
limit: "&limit=250"
comments: "?pretty=0&limit=250&access_token=69kG05ulDtG8DJDA&filter=stream"
feed: "/feed?limit=200&access_token=623501EuhC9kG05ulDtG8DJDA&pretty=0"
}
Strangely, IntelliJ doesn't detect any formatting or syntax error when using = for me.
in my case it was a stupid mistake,
i m change file name from "application.config" to "application.conf" and its works .
If the application.conf is not getting discovered, you could add this to build.sbt:
unmanagedSourceDirectories in Compile += baseDirectory.value / "main/resources"
Please don't use this to include any custom path. Follow the guidelines and best-practices
As mentioned by others, make sure the application.conf is place in: src/main/resources.
I placed the file there error went away.
Looking at these examples helped me as well:
https://github.com/lightbend/config/tree/main/examples/scala
Use ConfigFactory.parseFile for other locations

Dealing with the same setting in different config files

I was suggested to use 2 or more config files for different modes:
play -Dconfig.file=/conf/dev_application.conf run
Well, how can I deal with some common settings that are the same for different modes? Copy-pasting those is not what I'd use.
I'd use one common config file if it was possible:
play -Dconfig.file=/conf/dev_application.conf /conf/common_application.conf run
As far as I'm concerned, it's not possible. Any idea?
You can import settings in another configuration file via use of an include statement:
# Note that the name of the file being included must be quoted
include "common_application.conf"
This will import all configuration entries from your common configuration. You can then also override the values of any these common keys lower down in your mode-specific config file:
common_application.conf
foo=0
dev_application.conf
# Import common configuration
include "common_application.conf"
# Override common configuration
foo=1
# Dev configuration
bar=0
Good question, look what I found:
GlobalSettings has an onLoadConfig method, so you should be able to do something like this:
import com.typesafe.config.ConfigFactory
override def onLoadConfig(config: Configuration, path: File, classloader: ClassLoader, mode: Mode.Mode): Configuration = {
val richConfig = config ++ Configuration(ConfigFactory.load(s"${mode.toString.toLowerCase}_application.conf"))
super.onLoadConfig(richConfig, path, classloader, mode)
}
This way you can keep your common settings in application.conf and environment-specific settings in prod_application.conf or dev_application.conf (but I did not recheck the values of mode parameter so the names may differ)
EDIT
Yes, I just rechecked the Mode values. Here they are:
val Dev: Value
val Prod: Value
val Test: Value
So using this approach you can name your conf files as dev_application.conf, prod_application.conf and test_application.conf