There are a few bits that you need to configure to create a thick jar playback application.
Starting with the asssembly plugin. There should be a file named assembly.sbt located directly in the project directory. To be precise and to eliminate confusion, if your project is called MyPlayProject, the file should be located in "MyPlayProject / project / assembly.sbt" and should contain only the following.
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3"
Obviously, the version can be changed, but it should work. This will add the build plugin to your project and will not work if it is added to the plugins.sbt file, like other plugins.
In order to cover all the bases, also make sure that you have standard sbt elements, including include / build.properties. Please note that for Play 2.5.x sbt version 13.8 or higher is required for 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 problems is part of the build.sbt file, which should include the merge strategy. There are several files that are standard in jar files (e.g. MANIFEST.MF, etc.), and you have to do something to process these duplicate files when you merge all the banks into one 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 be very different from specific cases, but it is quite simple for a standard game jar.
Some basic information about the above merge strategy:
- Combine all jar reference.conf into one file for a fat jar. I forget the specific problem that leads to this, but I donβt think you can run your application as a thick jar without this step. I have no evidence of this)
- Drop the MANIFEST.MF files for each jar. Many examples on the Internet show this as "case PathList (" META-INF ", xs @_ *) => MergeStrategy.discard." This works by deleting anything in the META-INF directory. However, when you start the Play 2.4 application, the dependency becomes very complicated during the game, and when using dependency injection, there is a library dependency on net.sf.ehcache, which includes service files necessary for using dependency injection. The fix is ββto leave all the other files and just drop the MANIFEST.MF files, as I already did, or just delete everything and not use any dependencies (not recommended).
- A common catch in all cases, which stores the first of all duplicate files and discards the others. Useful when you can have several common dependencies in the same library, and there is no reason to store multiple copies.
Since I cannot clarify with comments, here is the complete build.sbt sample 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 leave comments for more details before answering, so that I could be more accurate with my answer, but the question is a little old, and I said that my representative is not so high anyway ... hope this helps.
PS I found your question while looking for help with my merge problems moving the game from 2.3.4 to 2.5.4. This is why I changed the META-INF merge strategy to cancel MANIFEST.MF, otherwise it will result in the following exception. I am rewriting it with my answer in the hope that it can get into the search results, since I found very little initially when I searched for 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