I try to build jar from clean project with sbt-assembly
how describes in docs:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
import AssemblyKeys._
assemblySettings
mainClass in assembly := Some("play.core.server.ProdServerStart")
fullClasspath in assembly += Attributed.blank(PlayKeys.playPackageAssets.value)
but it gives me a lot of deduplicate errors. How to build "fat" jar from play with sbt-assembly
?
There are several bits that need to be setup to build a play application as a fat jar.
Starting with the asssembly plugin. There must be a file named assembly.sbt located directly in the project directory. To be exact and eliminate confusion if your project is named MyPlayProject the file must be located at "MyPlayProject/project/assembly.sbt" and should contain only the following.
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3"
Obviously the version is subject to changed but it should work. This will add the assembly plugin to your project and does not work if added to the plugins.sbt file like other plugins.
As a matter of covering all basis also make sure you have the standard sbt items covered including project/build.properties. Note that for Play 2.5.x sbt version 13.8 or greater is required per https://www.playframework.com/documentation/2.5.x/Migration25#sbt-upgrade-to-0.13.11
sbt.version=0.13.11
And the likely critical part causing your issues is part of the build.sbt file which should include the merge strategy. There are a number of files that are standard in jar files (e.g. MANIFEST.MF etc) and you must do something to handle these duplicated files when you combine all the jars into a single fat jar. Basic example
assemblyMergeStrategy in assembly := {
case r if r.startsWith("reference.conf") => MergeStrategy.concat
case PathList("META-INF", m) if m.equalsIgnoreCase("MANIFEST.MF") => MergeStrategy.discard
case x => MergeStrategy.first
}
Your mileage may very with the specific cases to be handled but this is pretty basic for a standard a play fat jar.
Some basic details on the above merge strategy as follows:
Since I can't clarify with comments here is a complete sample build.sbt file.
name := """MyPlayProject"""
version := "1.0"
lazy val `root` = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.8"
// Set JS Engine to use
JsEngineKeys.engineType := JsEngineKeys.EngineType.Node
// Set repository details for resolving additional depenecies
resolvers ++= Seq(
"scalaz-bintray" at "https://dl.bintray.com/scalaz/releases",
"ClouderaRepo" at "https://repository.cloudera.com/content/repositories/releases"
)
// Specifies dependencies to use in project
libraryDependencies ++= Seq(
"org.apache.kafka" % "kafka_2.11" % "0.9.0.1",
jdbc,
cache,
ws,
specs2 % Test
)
// Add an additional source content route besides the default
unmanagedResourceDirectories in Test <+= baseDirectory ( _ /"target/web/public/test" )
unmanagedSourceDirectories in Compile += baseDirectory.value / "src2" / "main" / "scala"
sourceDirectory in Compile <<= baseDirectory / "src2/main/scala"
scalaSource in Compile <<= baseDirectory / "src2/main/scala"
// Informs SBT Assembly how to handle duplicated files when combining project and dependency jars into a single fat jar
assemblyMergeStrategy in assembly := {
case n if n.startsWith("reference.conf") => MergeStrategy.concat
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
I would have left comments for more details before answering so I could have been more exact with my answer but the question is a bit old and that said my rep is not high enough anyways... hope this helps.
P.S. I found your question while searching for help with my own merge issues migrating play 2.3.4 to 2.5.4. This is why I changed the META-INF merge strategy to only discard the MANIFEST.MF, otherwise it causes the below exception. I am re-posting it with my answer in hopes it might get picked up in search results since I found very few initially when I was searching it.
Oops, cannot start the server.
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, net.sf.ehcache.CacheException: java.lang.AssertionError: No net.sf.ehcache.EhcacheInit services found
while locating play.api.cache.CacheManagerProvider
while locating net.sf.ehcache.CacheManager
for field at play.api.cache.NamedEhCacheProvider.manager(Cache.scala:211)
while locating play.api.cache.NamedEhCacheProvider
at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
at play.api.cache.EhCacheModule.play$api$cache$EhCacheModule$$bindCache$1(Cache.scala:184):
Binding(interface net.sf.ehcache.Ehcache qualified with QualifierInstance(@play.cache.NamedCache(value=play)) to ProviderTarget(play.api.cache.NamedEhCacheProvider@45312be2)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:176)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
at com.google.inject.Guice.createInjector(Guice.java:96)
at com.google.inject.Guice.createInjector(Guice.java:84)
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.ProdServerStart$.start(ProdServerStart.scala:47)
at play.core.server.ProdServerStart$.main(ProdServerStart.scala:22)
at play.core.server.ProdServerStart.main(ProdServerStart.scala)
Caused by: net.sf.ehcache.CacheException: java.lang.AssertionError: No net.sf.ehcache.EhcacheInit services found
at net.sf.ehcache.LibraryInit.init(LibraryInit.java:55)
at net.sf.ehcache.CacheManager.init(CacheManager.java:366)
at net.sf.ehcache.CacheManager.<init>(CacheManager.java:259)
at net.sf.ehcache.CacheManager.newInstance(CacheManager.java:1037)
at net.sf.ehcache.CacheManager.newInstance(CacheManager.java:936)
at net.sf.ehcache.CacheManager.create(CacheManager.java:904)
at play.api.cache.CacheManagerProvider.get$lzycompute(Cache.scala:205)
at play.api.cache.CacheManagerProvider.get(Cache.scala:202)
at play.api.cache.CacheManagerProvider.get(Cache.scala:201)
at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
at com.google.inject.internal.BoundProviderFactory.provision(BoundProviderFactory.java:72)
at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61)
at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:62)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:54)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:93)
at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:80)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
at com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:80)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:62)
at com.google.inject.internal.InjectorImpl.injectMembers(InjectorImpl.java:984)
at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
at com.google.inject.util.Providers$GuicifiedProviderWithDependencies$$FastClassByGuice$$2a7177aa.invoke(<generated>)
at com.google.inject.internal.cglib.reflect.$FastMethod.invoke(FastMethod.java:53)
at com.google.inject.internal.SingleMethodInjector$1.invoke(SingleMethodInjector.java:57)
at com.google.inject.internal.SingleMethodInjector.inject(SingleMethodInjector.java:91)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:93)
at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:80)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)
at com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:80)
at com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:174)
at com.google.inject.internal.Initializer.injectAll(Initializer.java:108)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:174)
... 9 more
Caused by: java.lang.AssertionError: No net.sf.ehcache.EhcacheInit services found
at net.sf.ehcache.LibraryInit.initService(LibraryInit.java:78)
at net.sf.ehcache.LibraryInit.init(LibraryInit.java:50)
... 42 more
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