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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With