How to make properties file available to FileInputStream in Scala script? - scala

I have a Scala script that I want to call from sbt. This Scala script refers to some dependencies. One of those dependencies uses a properties file. This properties file is provided by the run time as this dependency is run as a separate application.
Just to have the possibility to run that property-using dependency as a standalone, I wrote this Scala script that I want to call from sbt.
val fis = new FileInputStream("my.properties") // Fails here
val props = new Properties()
When I run the above code, it fails with an exception in my dependency where the properties file is loaded.
How to make this properties file available to the script under sbt?

Place the file my.properties in src/main/resources and use Source.fromURL(getClass.getResource("/my.properties")) instead (as it gives you more flexibility in where you can place the file on file systems as long as it's on CLASSPATH).
As a helper, use the following code to learn about the place where the file is expected when a "bare" File* types are in use:
println(new java.io.File("my.properties").getAbsolutePath)
Since the current working directory is the top-level directory of a project, the file is searched in $PROJECT_ROOT_DIR/my.properties.

Related

Get relative path from inside a scala library (while developing that library)

I'm currently developing a scala library and wanted to get a file that is inside it, event when compiled as a Jar dependency. The problem is that when executed from another project where the library is imported, the path is relative to that project. Here is the code to get the file :
private val pathToDocker: Path = Paths.get("src", "main", "resources", "docker-compose")
What can I do to look for my file inside the imported dependency ?
The file won't be in a file system -- it'll be in the compiled JAR.
You can get a JAR resource using a class loader. Here's an example of how to do that in another codebase.
Utility function:
https://github.com/hail-is/hail/blob/6db198ae06/hail/src/main/scala/is/hail/utils/package.scala#L468
Usage to load version info:
https://github.com/hail-is/hail/blob/6db198ae06/hail/src/main/scala/is/hail/package.scala#L21
There is a JarUtil - from an answer of access-file-in-jar-file translate to Scala:
import java.util.jar.JarFile
val jar = new JarFile("path_to_jar/shapeless_2.12-2.3.3.jar")
val entry = jar.getEntry("shapeless/Annotation.class")
val inStream = jar.getInputStream(entry)
As you mentioned scala.io.Source.fromResource works only within your project:
Source.fromResource("tstdir/source.txt")
Make sure the file is in the resources directory, like:
The way I found to achieve getting the path inside a jar depedency was creating a singleton (scala object) that has a method that loads the files. Since it is inside the Jar, the resulting path is relative to the jar itself. Here is the code :
object ClassLoaderTest {
def dockerFile: File =
new File(getClass.getClassLoader.getResource("docker/docker-compose.yml").getPath)
}
When called from a Trait (or an interface), the resulting path is :
jar:file:/home/myname/.ivy2/cache/com.mypackage/libraryname/jars/libraryname.libraryversion.jar!/docker/docker-compose.yml

Scala Standalone JAR with a conf Folder

I'm using the sbt assembly jar plugin to create a standalone jar file. My project folder structure would look like this:
MyProject
-src
- main
- scala
- mypackages and source files
- conf // contains application.conf, application.test.conf and so on
- test
-project // contains all the build related files
- README.md
I now want to be able to run the fat jar that I produce against a version of the application.conf that I specify as a System property!
So here is what I do in my unit test!
System.setProperty("environment", "test")
And this is how I load the config in one of the files in my src folder:
val someEnv = Option(System.getProperty("environment", "")).filter(_.nonEmpty) // gives me some(test)
val name = s"application.${someEnv.get}.conf"
I can see that the environment variable is set and I get the environment passed it. But later on I load the application.test.conf as below:
ConfigFactory.load(name).resolve()
It however loads just the edfault application.conf and not the one that I specify!
What is wrong in my case? Where should I put the conf folder? I'm trying to run it against my unit test which is inside the test folder!
I believe you need to specify the full name of the configuration file. The .conf is optional. Try
ConfigFactory.load(s"application.${someEnv.get}").resolve()
The docs for ConfigFactory.load(String) indicate you need to supply
name (optionally without extension) of a resource on classpath
Ok! Here is what I had to do! Change the name of the folder where the config file is located. I originally had it as conf and I had to rename it to resources and bang it worked!

Compile scala code mix with java code

I need to compile a scala code which calls a java code from it.
What I did:
1]I have a scala main file check.scala
package com.code
class check {
var Rectvalue = Array.ofDim[Int](5)
val str = Array.ofDim[String](1)
def nativeacces(arg: String, loop: Integer) {
val test = new testing()
test.process(arg, Rectvalue,str)
}
}
2.For creating instance val test = new testing() ,i added two .class(sample.class,testJNI.class) file from java source code inside the folder(package) com/code.
3.When I compile the scala code using
scalac check.scala
It generates the class file for the scala file.
What I have to do:
1.Instead of .class(sample.class,testJNI.class) file added inside the package ,i need to add jar file.
2.I tried, created jar file for the .class file and compile the Scala, it shows the error:
scala:6: error: not found: type testing
val test = new testing()
3.I need to link the .jar file and compile the scala main file
You can reference classes/directories/JARs via classpath option:
scalac -classpath your.jar check.scala
Related question: Adding .jar's to classpath (Scala).
If you want a proper build use SBT, put your JAR in lib directory in the root of project and it will figure out what to do for you. Here is Hello World of SBT.

PlayFramework2 Scala File Map

I'm just starting with Scala and have run into a problem that has me stumped, but I'm guessing that I'm missing something easy.
I was following instructions to use the Clapper ClassFinder:
http://thoughts.inphina.com/2011/09/15/building-a-plugin-based-architecture-in-scala/
val classpath = List("./plugins").map(new File(_))
val finder = ClassFinder(classpath)
val classes = finder.getClasses
val classMap = ClassFinder.classInfoMap(classes)
After executing the first line, I see that classpath is set simply to
List(.\plugins)
I'm running this on windows, so the swapping of the slash seems to be OK.
But I expected to see a list of File objects, although I am not sure about this Scala syntax, and perhaps I'm missing something in the Scala IDE. The value for classes shows an "empty iterator".
It seems not to be finding any files in the path that I specified. I tried using an absolute path, but I had the same results. I have a single jar file in the plugins directory that I'm hoping it will find. The plugins directory is at the root of the Play2 project I'm using.
Edit ---
I did find that when I explicitly list the path to one jar that it is able to find it:
val classpath = List("./plugins/myPlugin.jar").map(new File(_))
But I want to find all jar files in the directory.
The following didn't work:
val classpath = List("./plugins/*").map(new File(_))
Nor did this:
val classpath = List("./plugins/*.jar").map(new File(_))
Judging by this issue on the ClassFinder repo on Github it may be a bug.
I think you need to create an explicit list of jar files or to list the ones contained in your folder like:
val classpath =(new File("./plugins")).listFiles.filter(_.getName.endsWith(".jar"))
EDIT: from a cursory glance at ClassFinder's source on GitHub I think it's not a bug. ClassFinder searches for .class files either in jars or in zip files or directly in folders but it looks like it does not mix these things recursively (i.e. if you give it a folder it will look for classes directly in the folder but it won't look for classes in jars in the folder)
if you objective is to list all jar files, you can use following code:
val classpath = List("./plugins").map(path => Option(new File(path).listFiles).getOrElse(Array.empty[java.io.File]) filter(file => file.isFile && file.getName.endsWith(".jar"))).flatten

How to create a compiler Action for SBT

I want to create an Action to automate GCJ compilation. Since I couldn't make it work with Ant, I decided to try SBT. The docs say how to create an Action and how to run an external process. What I don't yet see is how to reuse the directory tree traversal which exists for java and scala compiler Actions. In this case my input files would be all the .class files under a certain root folder. I would also need to specify a specific classpath for GCJ. Any pointers for this would be appreciated too.
I haven't used GCJ much at all and I'm still pretty new at SBT, but this is how I believe you could write a quick task to do exactly what you are looking for with SBT 0.7.1. You can use a PathFinder to grab all of the class files like so:
val allClasses = (outputPath ##) ** "*.class"
Using that PathFinder and the "compileClasspath" top level method, you can construct a task like this which will run gcj using the current project's classpath and compose all of the .class files into one gcjFile:
val gcj = "/usr/local/bin/gcj"
val gcjFile = "target/my_executable.o"
val allClasses = (outputPath ##) ** "*.class"
lazy val gcjCompile = execTask {
<x>{gcj} --classpath={compileClasspath.get.map(_.absolutePath).mkString(":")} -c {allClasses.get.map(_.absolutePath).mkString("-c ")} -o {gcjFile}</x>
} dependsOn(compile) describedAs("Create a GCJ executable object")