Question

My project uses sbt-native-packager with packageArchetype.java_application. During sbt stage I have a task that generates some final Typesafe style configuration file that I then copy to:

target/universal/stage/conf/application.conf

I'd like to prepend this directory to the runtime classpath in the bash script, and am looking for the simplest way to do that. I'd hate to maintain a separate src/main/templates/bash-template for something so simple, and am not seeing exactly how to go about it otherwise.

Thanks!

Was it helpful?

Solution

Short Answer

Define a package mapping

mappings in Universal <+= (packageBin in Compile, sourceDirectory ) map { 
    (_, src) =>
    // we are using the reference.conf as default application.conf
    // the user can override settings here
    val conf = src / "main" / "resources" / "reference.conf"
    conf -> "conf/application.conf"
}

Create a jvmopts in src/universal/conf with

-Dconfig.file=/<installation-path>/conf/application.conf

Add to build.sbt

bashScriptConfigLocation := Some("${app_home}/../conf/jvmopts")

Example for server_archetype: Follow the example application. A bit of description can be found here.

Long answer

Changing the classpath is not supported directly by the sbt-native-packager, because it can cause problems like

  • classpath ordering
  • security issues

Like Typesafe Config, most libraries which use config files, provide a parameter to define the location of the configuration file. Use the parameters describe in the documentation.

It seems your are trying to run a server, which means you can use the

packageArchetype.java_server

which is designed to read external configurations. Take a look at the example application how to use it.

OTHER TIPS

The following setting:

scriptClasspath in bashScriptDefines ~= (cp => "../conf" +: cp),

Allows you to do exactly what you need.

In this specific example I prepend the "../conf" directory to the classpath entries.

Also, you need to import the following configuration keys to your build SBT:

import com.typesafe.sbt.packager.Keys.bashScriptDefines
import com.typesafe.sbt.packager.Keys.scriptClasspath

The question you asked in the title is a bit different from the description. I am answering the question in the title here - i.e. how can you prepend a directory into the classpath:

This is very hacky and brittle in that it will probably break if/when the sbt-native-packager makes changes to how the script is generated, but for now it works for me:

private lazy val ClasspathPattern = "declare -r app_classpath=\"(.*)\"\n".r

bashScriptDefines :=  bashScriptDefines.value.map {
                              case ClasspathPattern(classpath) => "declare -r app_classpath=\"/path/to/some/external/lib/*:" + classpath + "\"\n"
                              case _@entry => entry
                          },
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top