1

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 ?

Ismail H
  • 4,226
  • 2
  • 38
  • 61

3 Answers3

3

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

Tim
  • 3,675
  • 12
  • 25
1

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:

enter image description here

pme
  • 14,156
  • 3
  • 52
  • 95
  • Actually, using fromRessource will look for the file inside the current project and not the jar dependency as expected. – Ismail H Nov 27 '18 at 18:27
  • @IsmailH - sorry I missed that - see my edited answer - not as elegant - but I tested it;) – pme Nov 27 '18 at 19:26
  • Thanks for the answer @pme, I've managed to walk trough it and found a solution, I'll post an answer as son as it is validated. – Ismail H Nov 28 '18 at 14:18
0

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
Ismail H
  • 4,226
  • 2
  • 38
  • 61