How do I add the resourceDirectory in Java Classpath while SBT runs tests?
For now I only have sbt jar.
My need is due to a dependency (spark-cassandra-connector EmbeddedCassandra) loading a resource via ClassLoader.getSystemResourceAsStream rather than getClass().getClassLoader().getResource ...
If you want to add a new file/folder to your Java Classpth you can add the following line in your build.sbt:
(fullClasspath in Test) := (fullClasspath in Test).value ++ Seq(Attributed.blank((resourceDirectory in Test).value))
This will add the folder given by the test:resourceDirectory setting to the Classpath under the Test configuration.
Note:
The fullClasspath task provides a classpath including both the dependencies and the products of a project. For the test classpath, this includes the main and test resources and compiled classes for the project as well as all dependencies for testing.
...
fullClasspath is the concatenation of dependencyClasspath and exportedProducts
More details can be found here.
Related
When sbt-assembly builds a fat jar, it places all the dependencies in the main folder. I need to construct a jar that looks like this
--domain
domain classes
-- lib
dependency classes
is it possible to do this with sbt assembly, or any other plugin?
If you want to seperate your app jar file and your dependecy jar files, here is the most practical method i found with sbt;
Create project/plugins.sbt file if not exists and add following line:
addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.0")
After adding this line refresh your project.
Note: Plugin version might change in time.
When sbt refresh finishes update your build.sbt file like this:
lazy val MyApp = project.in(file("."))
.settings(artifactName := {(
sv: ScalaVersion,
module: ModuleID,
artifact: Artifact) => "MyApp.jar"
})
.settings(packSettings)
Then run:
sbt pack
Or if you're doing this for child project, run this:
sbt "project childproject" clean pack
This will nicely seperate your main jar file and your dependency jars.
Your app jar will be in target scala folder.
Your dependencies will be in target/pack/lib.
In this way you can deploy your dependencies once.
And whenever you change your app, you can just deploy your app jar file.
So in every change you don't have to deploy an uber jar file.
Also in production, you can run your app like:
java -cp "MyApp.jar:dependency_jars_folder/*" com.myapp.App
I'm using sbt 0.13.8 and xsbt-web-plugin 2.0.3
I have a multi-module sbt project. When packaged, one of the modules should be in the form of a war file. All of the others in jar files.
When I add the xsbt-web plugin, packaging generates jars and wars for all modules. How can I tell the xsbt-web plugin to apply itself only to the module that should be packaged as a war?
I've already found one solution, which is to mutate the packagedArtifacts list for each non-war module:
packagedArtifacts <<= packagedArtifacts map { as => as.filter(_._1.`type` != "war") }
However, this is a non-local change which I would have to apply to each new non-war module that I (or a team member) might create.
I do not consider this a duplicate of the StackOverflow issue How to “package” some modules to jars and others to wars in multi-module build with single task? since I am not using assembly.
Note that the jars for the jar modules and the wars for the war modules, which are currently being generated, work splendidly. I'm only trying to avoid the situation where somebody tries to deploy a war that was meant to be a jar.
This was a bug in version 2.0.3 -- thanks for discovering it! I've fixed it in 2.0.4.
To enable .war file publishing for a single module in a multi-module project:
Add xsbt-web-plugin in project/plugins.sbt
Enable the WarPlugin plugin in [webproject]/build.sbt
project/plugins.sbt:
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.0.4")
[webproject]/build.sbt:
enablePlugins(WarPlugin)
You can find a full example of this at https://earldouglas.com/ext/stackoverflow.com/questions/31683637/
I have a multi-project build and I'm trying to add the jar with assets generated by sbt-web to the classpath of the launch script
The project I'm interested in is called website.
typing show website/web-assets:packageBin in sbt creates and shows the jar with the assets. I tried putting in (managedClasspath in website) += website/web-assets:packageBin, but that doesn't compile:
path/to/build.sbt:58: error: value / is not a member of sbt.Project
managedClasspath in website += website/web-assets:packageBin
How can I create the jar with assets when I run the stage task, and place it on the classpath of the launch script
You are mixing sbt-console commands with build.sbt commands.
The sbt-web docs give a clear example how you do it for a single project:
(managedClasspath in Runtime) += (packageBin in Assets).value
So now we do the same thing for a multi-module build. Assuming you have a build.sbt that looks like this
val root = (project in ".")
.aggregate(common, website)
val common = (project in "commons")
.settings(
libraryDependencies ++= Seq(...),
...
)
val website = (project in "commons")
.enablePlugins(JavaServerAppPackaging, SbtWeb)
.settings(
// ------ You configure it like a single module project
(managedClasspath in Runtime) += (packageBin in Assets).value
// ----------------------------------------------------
)
.dependsOn(common)
I have not directly tested this as I don't know your exact configuration. However this should give you the right direction.
I was a heavy Maven user and now I'm gradually using SBT for some of my projects.
I'd like to know how could I use SBT to create a standalone Java project? This project should be packaged as a JAR file and this JAR file would be used as a dependency in another SBT project.
In Maven, I could tell in my pom.xml what type of artifact it should produce when I build it. Is there something similar that I can do in SBT?
There is a difference between standalone and making a project useable as a dependency or another project. In the first case, you would use a plugin such as sbt-assembly. What it will do is create one jar file containing the project class files along with all of its dependencies. If you write an application, what you get is a double-clickable jar that you can execute from anywhere.
If you want to use your project A as a dependency for another project B, you have different options. You could just package the class files of A, using sbt package (answer of #Channing Walton). Then you could drop the resulting .jar file in the lib directory of project B. However, if A also requires libraries, you must make sure that they also end up in project B's libraries.
A better approach is to publish your project. You can do that purely on your local machine, using sbt publish-local. That will store the jar as produced by package in a special local directory which can be accessed from sbt in another project, along with a POM file that contains the dependencies of A. It will use a group-ID (organization) and artifact-ID (name) and a version of your project A. For example, in build.sbt:
name := "projecta"
version := "0.1.0-SNAPSHOT"
organization := "com.github.myname"
scalaVersion := "2.10.3"
publishMavenStyle := true
After publishing with sbt publish-local, you can add the following dependency to your project B:
libraryDependencies += "com.github.myname" %% "projecta" % "0.1.0-SNAPSHOT"
If you have a pure Java project, you can omit the Scala version suffix, i.e. in Project A:
crossPaths := false
autoScalaLibrary := false
And then in Project B:
libraryDependencies += "com.github.myname" % "projecta" % "0.1.0-SNAPSHOT"
(using only one % character between group and artifact ID).
More on publishing in the sbt documentation.
'sbt package' will produce a jar file.
If you want it to be executable you need to add the following to your .sbt config:
mainClass in Compile := Some("your.main.Class")
Sure, you can use 'sbt package' command, it creates a jar file but this jar will be without any dependencies. To run it necessary to specify 'classpath' arg to the libraries.
In your case you wish a standalone runnable file. And you need to add the dependencies.
To do this you can use 'assembly' plugin for SBT, see https://github.com/sbt/sbt-assembly/
Afterward you can just run 'sbt assembly' command, it provides a fat jar file with all dependencies that you can deploy and run anywhere and at any time.
For details see this article
publishLocal
builds the artifact and publish in the local Ivy repository making it available for your local project dependencies.
publishM2
same as above, but the artifact is published in local Maven repo instead of Ivy repo.
I think the easiest way to produce a stand-alone jar with your project in it,
is sadly not lying inside sbt.
I personally use my IDE: Intellij to make the jar (through the 'build artifact' feature).
Thanks to Intellij I can easily choose which library I want to include in the jar or not, (for instance the scala stl).
IMHO, this is by far the simplest method to get an executable jar for your project.
If you put the scala stl you can run your jar with the "java -jar" command, if you don't you have to run it somewhere with the correct version of scala installed with "scala".
I have a library compiled to a jar (not an sbt project, no source code, just the jar file) that's not available on a repository.
Is there a way to publish the jar locally so I can add the dependency using the libraryDependencies += "org.xxx" % "xxx" % "1.0" notation? (I already know how to add the file to a project by copying it to the lib folder.)
The publishLocal action is used to publish your project to a local Ivy repository. By default, this local repository is in ${user.home}/.ivy2/local. You can then use this project from other projects on the same machine source
EDIT: Sorry I misread your question. Here is an example to publish a jar or sources to your local ivy repo.
tl;dr I'd call it a trick not a feature of sbt. You've been warned.
Let's say you've got file.jar to publish. As is for any build tool, sbt including, it's to execute tasks that eventually create an artifact - a jar file in most cases - out of the files in a project.
The project sets the coordinates for the artifact.
The trick is to leverage what sbt requires to set up the environment (= the coordinates) for the jar to be published (otherwise you'd have to specify them on command line that may or may not be very user friendly).
Create a build.sbt with the necessary settings - organization, name, version and possibly scalaVersion - and save it where the jar file is.
organization := "org.abc"
name := "my-own-publish-jar"
version := "1.0.0"
scalaVersion := "2.11.3"
packageBin in Compile := file(s"${name.value}_${scalaBinaryVersion.value}.jar")
You may've noticed, the build changes compile:package task to point at the jar file.
That's it.
Execute sbt publishLocal and the jar file should be in the Ivy2 local repository, i.e. ~/.ivy2/local/org.abc/my-own-publish-jar_2.11/1.0.0/jars/my-own-publish-jar_2.11.jar.
protip Writing a plugin to do it with the coordinates specified on command line should be quite easy now.
Let's say you have wetElephant.jar and wetElephant-javadoc.jar files some 3rd party library and corresponding javadocs which you want to publish to your local repo and referrence it from another project using libraryDependencies sbt taskKey.
Here's what you need to do.
Put your libraries (wetElephant.jar and wetElephant-javadoc.jar) into modules\wetElephant
Define project in your build.sbt file (or Build.scala file)
lazy val stolenLib = project
.in(file("modules/wetElephant"))
.settings(
organization := "com.stolenLibs",
name := "wetElephant",
version := "0.1-IDonKnow",
crossPaths := false, //don't add scala version to this artifacts in repo
publishMavenStyle := true,
autoScalaLibrary := false, //don't attach scala libs as dependencies
description := "project for publishing dependency to maven repo, use 'sbt publishLocal' to install it",
packageBin in Compile := baseDirectory.value / s"${name.value}.jar",
packageDoc in Compile := baseDirectory.value / s"${name.value}-javadoc.jar"
)
Call publishLocal task from sbt/activator (I did it from activator and prefixed it with proejct name):
./activator wetElephant/publishLocal
... and read the output to see what and where was published:
/cygdrive/d/devstation-workspace/projects/m4l-patches 1
[info] Loading project definition from D:\devstation-workspace\projects\m4l-patches\project
[info] Set current project to m4l-patches (in build file:/D:/devstation-workspace/projects/m4l-patches/)
[info] Updating {file:/D:/devstation-workspace/projects/m4l-patches/}wetElephant...
[info] Packaging D:\devstation-workspace\projects\m4l-patches\modules\wetElephant\target\wetelephant-0.1-IDonKnow-sources.jar ...
[info] Done packaging.
[info] Wrote D:\devstation-workspace\projects\m4l-patches\modules\wetElephant\target\wetelephant-0.1-IDonKnow.pom
[info] Resolving org.fusesource.jansi#jansi;1.4 ...4 ....
[info] Done updating.
[info] :: delivering :: com.stolenLibs#wetelephant;0.1-IDonKnow :: 0.1-IDonKnow :: release :: Sun Dec 20 20:09:24 CET 2015
[info] delivering ivy file to D:\devstation-workspace\projects\m4l-patches\modules\wetElephant\target\ivy-0.1-IDonKnow.xml
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\poms\wetelephant.pom
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\jars\wetelephant.jar
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\srcs\wetelephant-sources.jar
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\docs\wetelephant-javadoc.jar
[info] published ivy to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\ivys\ivy.xml
[success] Total time: 1 s, completed 2015-12-20 20:09:24
Optionally use these libraries in another project
libraryDependencies += "com.stolenLibs" % "wetElephant" % "0.1-IDontKnow"
Disclaimer: I don't know how not to publish sources...
Here is a blog post I followed to push sbt artifact to a maven repository (local and remote) a few months ago.
http://brizzled.clapper.org/id/100/
Try this:
http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
I created a sample Play Framework/sbt project that creates a local repository (not just publish-local) here: https://github.com/muymoo/local-ivy-repo-sbt
Specifically look at Build.scala
makeLocalRepoSettings(publishedProjects):_*
and
localRepoArtifacts += "org.apache.ws.security" % "wss4j" % "1.6.9"
These localRepoArtifacts are found in my local ivy repo, but I think you could edit this to work with plain old jar files as well.
To run: play local-repository-created
It is a simpler version of https://github.com/sbt/sbt-remote-control which does a whole lot more in their Build.scala.