Pick the right config file - scala

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.

Related

read a scala conf file from a maven jar

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)

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

how to get values from addition conf files included in application.conf in scala

Hi I am trying to create additional conf files and include them in application.conf but i am unable to fetch my values I am definitely making mistakes here is my files
application.conf
include "DirectUserWriteMongoActor"
akka {
loggers = ["akka.event.slf4j.Slf4jLogger"]
loglevel = "DEBUG"
}
DirectUserWriteMongoActor.conf
akka {
actor{
my-dispatcher {
throughput = 10
}
}
}
i want to get the throughput value in my code but i am getting badpath exception Here is my code
val config = ConfigFactory.load("application/DirectUserWriteMongoActor")
println("throughput is "+config.getString("akka.actor.my-dispatcher.throughput"))
All you should need to do here is to call ConfigFactory.load(). When you do that, as long as it can find application.conf on the classpath, it will load it and then properly include the other conf file DirectUserWriteMongoActor due to your use of the include directive.

How to access static resources in jar (that correspond to src/main/resources folder)?

I have a Spark Streaming application built with Maven (as jar) and deployed with the spark-submit script. The application project layout follows the standard directory layout:
myApp
src
main
scala
com.mycompany.package
MyApp.scala
DoSomething.scala
...
resources
aPerlScript.pl
...
test
scala
com.mycompany.package
MyAppTest.scala
...
target
...
pom.xml
In the DoSomething.scala object I have a method (let's call it doSomething()) that tries to execute a Perl script -- aPerlScript.pl (from the resources folder) -- using scala.sys.process.Process and passing two arguments to the script (the first one is the absolute path to a binary file used as input, the second one is the path/name of the produced output file). I call then DoSomething.doSomething().
The issue is that I was not able to access the script, not with absolute paths, relative paths, getClass.getClassLoader.getResource, getClass.getResource, I have specified the resources folder in my pom.xml. None of my attempts succeeded. I don't know how to find the stuff I put in src/main/resources.
I will appreciate any help.
SIDE NOTES:
I use an external Process instead of a Spark pipe because, at this step of my workflow, I must handle binary files as input and output.
I'm using Spark-streaming 1.1.0, Scala 2.10.4 and Java 7. I build the jar with "Maven install" from within Eclipse (Kepler)
When I use the getClass.getClassLoader.getResource "standard" method to access resources I find that the actual classpath is the spark-submit script's one.
There are a few solutions. The simplest is to use Scala's process infrastructure:
import scala.sys.process._
object RunScript {
val arg = "some argument"
val stream = RunScript.getClass.getClassLoader.getResourceAsStream("aPerlScript.pl")
val ret: Int = (s"/usr/bin/perl - $arg" #< stream).!
}
In this case, ret is the return code for the process and any output from the process is directed to stdout.
A second (longer) solution is to copy the file aPerlScript.pl from the jar file to some temporary location and execute it from there. This code snippet should have most of what you need.
object RunScript {
// Set up copy destination from the Java temporary directory. This is /tmp on Linux
val destDir = System.getProperty("java.io.tmpdir") + "/"
// Get a stream to the script in the resources dir
val source = Channels.newChannel(RunScript.getClass.getClassLoader.getResourceAsStream("aPerlScript.pl"))
val fileOut = new File(destDir, "aPerlScript.pl")
val dest = new FileOutputStream(fileOut)
// Copy file to temporary directory
dest.getChannel.transferFrom(source, 0, Long.MaxValue)
source.close()
dest.close()
}
// Schedule the file for deletion for when the JVM quits
sys.addShutdownHook {
new File(destDir, "aPerlScript.pl").delete
}
// Now you can execute the script.
This approach allows you to bundle native libraries in JAR files. Copying them out allows the libraries to be loaded at runtime for whatever JNI mischief you have planned.

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