Reputation: 3751
Is there a way to download and package all provided dependencies in sbt in one jar that I can add to the classpath of my application when I start it?
I'm using sbt-assembly but the jar generated is waaay too big for my tastes: 16 Mb including both Scala-lang, Akka and Spray. I'm planning on building about 10-15 small independent services, each as a jar and don't want to keep uploading 16 Mb files to s3 (currently my repo) whenever I create a new version deploy.
When I exclude the Scala language and the other jars mentioned above, my assembly jar goes down to about 1 Mb. So what I want to achieve is to have a way to provide a fat jar with only the provided dependencies and the scala language so I can add that to the classpath of my services when I start them.
I could grab each library from my ivy cache, deploy them manually and add them to the classpath, but basically I want to be able to build a new assembled jar whenever I change a version and upload that.
I thought of having a separate project that the other project depends on, containing all my provided jars, but is there a simpler way?
Further clarification as requested:
My larger objective is an automated deploy into a cloud server. I first build locally with sbt-assembly, for example producing service-a.jar, service-b.jar etc. Then I sync these to s3, so if only service-a.jar is updated then only that file will be uploaded to s3. Next I instruct my ec2 server to download changed files and relaunch any new services.
When using sbt-assembly I get a fat jar (just like onejar) with all dependencies. However the uploading of that jar to s3 takes a long time and 15 Mb out of 16Mb of those files are just common dependencies. So my idea was to put all those shared dependencies into a separate jar that rarely changes and just provide those on the classpath when launching java -cp "deps.jar;service-a.jar" org.myapp.StartApp
.
I just don't want to manage those common jars myself manually. I want to leverage my existing build and use the sbt/ivy dependency management system for downloading the correct files for me and preparing a package that I can distribute separately with my stand alone services.
All solutions I come up with so far seem overly complicated so far, especially when I still need to be able to run tests etc (so no "provided" in sbt build files). Other suggestions are welcome.
Upvotes: 3
Views: 1817
Reputation: 3751
I found my answer when looking in the source code of the sbt-assembly plugin:
lazy val assembly = TaskKey[File]("assembly", "Builds a single-file deployable jar.")
lazy val packageScala = TaskKey[File]("assembly-package-scala", "Produces the scala artifact.")
lazy val packageDependency = TaskKey[File]("assembly-package-dependency", "Produces the dependency artifact.")
So with the following config + commands I can get all the artifacts I need:
// Produces a jar without dependencies and scala language jar included
lazy val assemblyMicroService = assemblySettings ++
Seq(
assembleArtifact in packageScala := false,
assembleArtifact in packageDependency := false
)
Then run the commands in turn:
assembly, assembly-package-scala, assembly-package-dependency
Then I will have three jars, one for my service, one for the scala language and one for the dependencies.
Upvotes: 7