read a scala conf file from a maven jar - scala

I would like to read two scala conf file from a maven jar named myconfiguration1.conf and myconfiguration2.conf:
driver= oracle.jdbc.driver.OracleDriver
user = myUser
password = pass
url = myUrl
table = my_table
before generate my jar, i used a line like this:
val myconfig1 = ConfigFactory.parseFile(new File("./my-project/src/main/resources/myconfiguration1.conf"))
val myconfig2 = ConfigFactory.parseFile(new File("./my-project/src/main/resources/myconfiguration2.conf"))
Inside my jar, i have a tree like this
my-project-0.0.1.jar
|___ myconfiguration1.conf
|___ myconfiguration2.conf
Do you have any idea since the two lines don't work with the jar file.

Seems you are using typesafe config to load the conf file, you can directly use ConfigFactory.load("myconfiguration1.conf") and ConfigFactory.load("myconfiguration2.conf") to load the classpath configuration file.
public static load(java.lang.String resourceBasename)

Related

Merging configurations for spark using typesafe library and extraJavaOptions

I'm trying to merge 2 config file (or create a config file based on a single reference file) using
lazy val finalConfig:
Option(System.getProperty("user.resource"))
.map(ConfigFactory.load)
.map(_.withFallback(ConfigFactory.load(System.getProperty("config.resource"))).resolve())
.getOrElse(ConfigFactory.load(System.getProperty("config.resource")))
I'm defining my java variable inside spark using spark-submit ....... --conf spark.driver.extraJavaOptions=-Dconfig.resource=./reference.conf,-Duser.resource=./user.conf ...
My goal is to be able to point a file that is not inside my jar to be used by System.getProperty("..") in my code. I changed the folder for testing (cd ..) and keep getting the same error so I guess spark doesn't care about my java arguments..?
Is there a way to point to a file (or even 2 files in my case) so that they can be merged?
I also tried to include the reference.conf file but not the user.conf file: it recognizes the reference.conf but not the user.conf that i gave with --conf spark.driver.extraJavaOptions=-Duser.resource=./user.conf .
Is there a way to do that? Thanks if you can help
I don't see you doing ConfigFactory.parseFile to loaded a file containing properties.
Typesafe automatically read any .properties file in the class path, all -D parameters passed in to the JVM and then merges them.
I am reading an external property file which is not part of the jar as following. The file "application.conf" is placed on the same directory where the jar is kept.
val applicationRootPath = System.getProperty("user.dir")
val config = Try {
ConfigFactory.parseFile(new File(applicationRootPath + "/" + "application.conf"))
}.getOrElse(ConfigFactory.empty())
appConfig = config.withFallback(ConfigFactory.load()).resolve
ConfigFactory.load() already contains all the properties present on the properties files in the class path and -d parameters. I am giving priority to my external "application.conf" and falling back on default values. For matching keys "application.conf" take precedence over other sources.

Unable to access file in relative path in Scala for test resource

I have setup my SCALA project using Maven, now I am writing test and need to access a file under sub directory of resource path is like:
src/test/resource/abc/123.sql
Now I am doing following:
val relativepath = "/setup/setup/script/test.sql"
val path = getClass.getResource(relativepath).getPath
println(path)
but this is pointing to src/main/resource folder instead of test resource, anyone has the idea what I am doing wrong here?
Just like in Java, it is a good practice to put your resource files under src/main/resources and src/test/resources, as Scala provides a nice API from retrieving resource files.
Considering you put your test.sql file under src/test/resources/setup/setup/script/test.sql, you can easily read the file by doing the following:
Scala 2.12
import scala.io.Source
val relativePath = "setup/setup/script/test.sql"
val sqlFile : Iterator[String] = Source.fromResource(relativePath).getLines
Prior Scala versions
import scala.io.Source
val relativePath = "setup/setup/script/test.sql"
val stream : InputStream = getClass.getResourceAsStream(relativePath)
val sqlFile : Iterator[String] = Source.fromInputStream(stream).getLines
Doing so, you can even have the same file put under the same relative path in src/main/resources. When trying to access the resource file in a test, the file from the src/test/resources will be considered.
I hope this is helpful.

Pick the right config file

I have created two files in my src/main/resources folder
application-dev.conf
which contains
dev {
oracle {
host = "foo"
}
}
and
application-qa.conf
which contains
qa {
oracle {
host = "bar"
}
}
I read this configuration with the following code
val env = args.lift(0).getOrElse("dev")
val parsedConfig = ConfigFactory.parseFile(new File(s"src/main/resources/application-${env}.conf"))
val conf = ConfigFactory.load(parsedConfig)
val config = conf.getConfig(env)
println(config.getString("oracle.host"))
Everything works great at development time and I am able to read the right configuration file based on the environment specified. If I don't specify anything then development is chosen.
However now when I package my jar file as an assembly using sbt assembly and now try to run my application from the command line java -jar ./target/MyApplication.jar
I get an error
Exception in thread "main" com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'dev'
at com.typesafe.config.impl.SimpleConfig.findKeyOrNull(SimpleConfig.java:152)
at com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:170)
at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:184)
at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:189)
My objective is that I should have multiple configuration files and I should be able to choose between them at dev time and also when the application is packaged as a jar.
Based on the suggestion below I modified my code to
val env = args.lift(0).getOrElse("dev")
val parsedConfig = ConfigFactory.parseFile(new File(getClass.getResource(s"/application-${env}.conf").toURI))
val conf = ConfigFactory.load(parsedConfig)
val config = conf.getConfig(env)
println(config.getString("oracle.host"))
works in dev, but when I try to run my assembly it throws an exception
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.<init>(File.java:418)
The config file is not in src/main/resources in your assembly. It usually is at the root of the classpath (unless you have configured the plugin to package it somewhere else).
Try using like below.
ConfigFactory.load(s"application-${env}.conf")
This loads the config file from the classpath.

Load application.conf from folder in deployed Scala app

I have an application that loads configuration from application.conf using ConfigFactory: lazy val myConfig = ConfigFactory.load(pathToConfig)
The application.conf is initially located in src/main/resources
When I deploy my application I want it to load the config from APP_HOME/conf/application.conf
To do so, I excluded the application.conf from the resource folder when building the Rmp and I have added my APP_HOME/conf to the class path.
jar {
exclude '*.conf'
}
and
startScripts {
classpath += files('src/main/resources')
doLast {
def windowsScriptFile = file getWindowsScript()
def unixScriptFile = file getUnixScript()
println('unix script is ' + unixScriptFile.text)
windowsScriptFile.text = windowsScriptFile.text.replace('%APP_HOME%\\lib\\resources', '%APP_HOME%\\conf')
unixScriptFile.text = unixScriptFile.text.replace('\$APP_HOME/lib/resources', '\$APP_HOME/conf')
println('after unix script is ' + unixScriptFile.text)
}
}
The odd thing is that when I modify the $APP_HOME/conf/application.conf and restart the app, the changes are not picked up: ie the old configuration is still being used
Any idea what might cause this or how I can print where the config is being loaded from would be helpful
With many attempts, I got it to work by calling lazy val myConfig = ConfigFactory.load() without specifying the conf file name or path.
Although it solved my issue I still don't understand why calling load with the file name or file path didn't work

application.conf for Scala SBT Akka Actors

I was wondering.. where do you put the application.conf file that configures actors in a file? I'm trying to do what is being done here but SBT is not picking up on the file - I was under the impression that SBT will find the application.conf and automatically add it to my -classpath. I currently have application.conf in /project/application.conf
The error I'm getting is:
[ERROR] [04/11/2012 16:08:13.174] [HittingTimeSystem-akka.actor.default-dispatcher-2] [akka://HittingTimeSystem/user/master] error while creating actor
akka.config.ConfigurationException:router Actor[akka://HittingTimeSystem/user/master/workerRouter] needs external configuration from file (e.g. application.conf)
Thanks!
-kstruct
It should end up on the classpath if you put it in src/main/resources/application.conf
just update:
// val conffactory = ConfigFactory.load() // from 'src/test/resources' if 'sbt test'
// val conffactory = ConfigFactory.load() // from 'src/main/resources' if 'sbt run'
val conf = ConfigFactory.parseFile(new File("config/application.conf")).getConfig("my") // from '/config' where / - root of app