How to determine resources for fatjar? - scala

I build my scala project with https://github.com/sbt/sbt-assembly to get a fatjar.
The structure of the project looks as following(You can see the resources folder, that contains a file SapConfig.json):
Then, I tried to execute the fatjar as following:
java -jar SapEvents-assembly-0.1.0.jar
java.nio.file.FileSystemNotFoundException
at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
at java.nio.file.Paths.get(Paths.java:143)
at ch.micarna.SapEventServer$.stream(SapEventServer.scala:22)
at ch.micarna.SapEventServer$.stream(SapEventServer.scala:16)
at fs2.StreamApp.$anonfun$runStream$1(StreamApp.scala:66)
at cats.effect.internals.IORunLoop$.cats$effect$internals$IORunLoop$$loop(IORunLoop.scala:128)
at cats.effect.internals.IORunLoop$.start(IORunLoop.scala:35)
at cats.effect.IO.unsafeRunAsync(IO.scala:257)
at cats.effect.IO.$anonfun$runAsync$1(IO.scala:175)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
at cats.effect.internals.IORunLoop$.step(IORunLoop.scala:167)
at cats.effect.IO.unsafeRunTimed(IO.scala:304)
at cats.effect.IO.unsafeRunSync(IO.scala:239)
at fs2.StreamApp.main(StreamApp.scala:83)
at ch.micarna.SapEventServer.main(SapEventServer.scala)
As you can recognize, I assume that the resource file could not be found.
The code, that read the resource file looks as following:
Paths.get(getClass.getClassLoader.getResource("SapConfig.json")
Where should I put my resource file?

I think your solution is in this post.
Change only
src/main/webapp to src/main/resources

Related

Unable to find file under resources folder

When I run my app in sbt console my-app/run (my-app is a module), I get this error
java.io.FileNotFoundException: file:.../target/bg-jobs/sbt_eea980c4/job-3/target/aaa32a5e/b2227e4f/my-app_2.13-0.1.0-SNAPSHOT.jar!/my_file.csv
My directory structure is my-app->src->main->resources->my_file.csv. The way I am accessing the file in my code is:
val file = new File(getClass.getResource("/my_file.csv").getPath)
What am I missing here?
sbt stuck your resources in a jar, so you can't access them as a file. You can use getClass().getResourceAsStream("/my_file.csv") instead.

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!

Custom deployment with sbt

I have a Scala application and i want to setup a deployment process result similar to one Akka sbt plugin gives, but i it requires project to be a microkernel. Sbt-assembly is a very cool plugin, but i want to have a free access to my config files, basically i want to have the following app structure:
/app/bin - start script bash file
/config - all my application .conf files
/deploy - my project .jar with classes
/lib - all my dependencies .jar files
/logs - log files
I we checked typesafe sbt-native-packager, it's better, but it could place my .conf file and logs out of jars. All those settings in SBT looks confusing to me, what can i do to with this?
Actually this is not hard to update akka-sbt-plugin to make it work in general, add this file to your project folder and somewhere in your build the following settings:
.settings(Distribution.distSettings: _*)
.settings(mappings in Compile in packageBin ~= { _.filter(!_._1.getName.endsWith(".conf")) })
The first line adds all dist settings to your project and the second one excludes all .conf files from your .jar and reads them from config folder.
Now you have to commands: dist - creates a folder with a structure you've discribed and zipDist which packs it all into .zip file, later you can add this to you publish setting:
addArtifact(Artifact(someName, "zip", "zip"), zipDist)

scala :How to read file in jar

I have directory structure like this
src
main
resources
text.txt
scala
hello
world.scala
test
same as main folder
pom.xml
When in IDE (Intellij10), I could access it with relative path ("src/main/resource/text.txt") but it seems I can not do that when I compile in jar. How to read that file ?
also, I found that test.txt is copy into root of jar. Is this normal behavior ? Since I fear this will be clash with other resources file in src/test/resources.
thanks
From http://www.java-forums.org/advanced-java/5356-text-image-files-within-jar-files.html -
Once the file is inside the jar, you cannot access it with standard FileReader streams since it is treated as a resource. You will need to use Class.getResourceAsStream().
The test.txt being copied into the root is not normal behavior and is probably a setting with your IDE.
8 years later, I am also facing the same question. To ease the life of future developers, here is the answer:
Being copied into the root is normal behaviour, as:
the resources folder is like a src folder and so the content is
copied, not the folder itself.
Now concerning the how-to question:
import scala.io.Source
val name = "text.txt"
val source: Source = Source.fromInputStream(getClass.getClassLoader.getResourceAsStream(name))
// Add the new line character as a separator as by getLines removes it
val resourceAsString: String = source.getLines.mkString("\n")
// Don't forget to close
source.close

Copy sources files into target directory with SBT

I recently decided to use SBT to build an existing project.
In this project I have some .glsl files within the scala packages which I need to copy during the compilation phase.
The project is structured like this :
- myapp.opengl
- Shader.scala
- myapp.opengl.shaders
- vertex_shader.glsl
- fragment_shader.glsl
Is this file structure correct for SBT or do I need to put the .glsl files into an other directory. And do you know a clean way to copy these files into the target folder ?
I would prefer not putting these files into the resources directory since they are (non-compiled) sources files
Thanks
I would not recommend putting those files into src/main/scala as they do not belong there. If you want to keep them separate from your resource files, you can put them in a custom path, e.g. src/main/glsl and add the following lines to your project definition to have them copied into output directory:
val shaderSourcePath = "src"/"main"/"glsl"
// use shaderSourcePath as root path, so directory structure is
// correctly preserved (relative to the source path)
def shaderSources = (shaderSourcePath ##) ** "*.glsl"
override def mainResources = super.mainResources +++ shaderSources