2016-04-25 45 views
5

罐子我嘗試從清潔工程與sbt-assembly建立罐子如何在docs描述:如何建立從遊戲框架2.5.X

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) 

,但它給了我很多重複數據刪除的錯誤。如何用sbt-assembly打造「胖」罐?

+0

你確定這個jar是最好的選擇。 Sbt-native packager構建安裝包幾乎開箱即用 – mgosk

+0

@zella,粘貼一些錯誤日誌。一年後的 – Nio

回答

9

需要設置幾個位來構建一個播放應用程序作爲一個胖罐子。

從asssembly插件開始。必須有一個名爲assembly.sbt的文件直接位於項目目錄中。爲了確切並消除混淆,如果您的項目名爲MyPlayProject,則該文件必須位於「MyPlayProject/project/assembly.sbt」中,並且應僅包含以下內容。

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3" 

很明顯,版本可能會改變,但它應該工作。這會將程序集插件添加到您的項目中,如果像其他插件一樣添加到plugins.sbt文件中,它將不起作用。

作爲一個涵蓋所有基礎的問題,還要確保你有標準的sbt項目,包括project/build.properties。請注意,對於玩2.5.X版本SBT 13.8或更高每https://www.playframework.com/documentation/2.5.x/Migration25#sbt-upgrade-to-0.13.11

sbt.version=0.13.11 

需要,造成您的問題可能的關鍵部分是build.sbt 文件,其中應該包括合併戰略的一部分。在JAR文件中有許多標準文件(例如MANIFEST.MF等),當您將所有JAR文件合併到一個胖JAR文件中時,您必須執行一些操作來處理這些重複的文件。基本示例

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 
} 

您的里程可能與特定情況下的處理方式很相似,但這對於標準的播放式胖罐而言非常基本。

上述合併策略的一些基本情況如下:

  • 合併所有jar的reference.conf爲脂肪JAR單個文件。我忘記了導致這個問題的具體問題,但我認爲,如果沒有這一步驟,您就無法將您的遊戲應用作爲胖罐子來運行。我沒有證據)
  • 放棄每個jar的MANIFEST.MF文件。許多在線的例子都顯示爲'case PathList(「META-INF」,xs @ _ *)=> MergeStrategy.discard'。這可以通過刪除jar的META-INF目錄中的任何東西來實現。然而,開始播放2.4依賴注入已被推到很難玩,如果使用依賴注入有一個庫依賴net.sf.ehcache其中包括使用依賴注入所需的服務文件。修復是留下所有其他文件,只是丟棄MANIFEST.MF文件,具體如我所做的或只是刪除一切,不要使用任何依賴注入(不推薦)
  • 一般捕獲所有情況下,保持第一任何重複的文件並丟棄其他文件。當你可能在同一個庫上有多個公共依賴關係並且沒有保存多個副本的理由時很有用。

由於我無法澄清與評論這裏是一個完整的示例build.sbt文件。

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 
} 

我會留下更多細節意見回答,所以我本來可以更精確地對我的回答,但問題是有點老了,並且說我的聲望不夠高反正之前...希望這有助於。

P.S.我在尋找幫助時遇到了自己的合併問題,將play 2.3.4遷移到2.5.4。這就是爲什麼我將META-INF合併策略更改爲僅丟棄MANIFEST.MF,否則會導致以下異常。我將其與我的答案一起重新發布,希望它可能會在搜索結果中找到,因爲我最初在搜索時發現它很少。

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([email protected])) (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 
+0

,謝謝!我確實找到了你編輯的PS文字。我做了你的建議,但是我得到了一個'Invalid Signature'錯誤。不過,我還是有一個線索要感謝你。我得到的錯誤:'org.apache.flink.client.program.ProgramInvocationException:程序的入口點類'net.tagtog.services.documents.flink.Job'在初始化期間導致了一個異常:Manifest主要屬性的無效簽名文件摘要' – juanmirocks

+0

找到解決方案! (至少爲我工作)。這個:'''case PathList(「META-INF」,「services」,xs @ _ *)=> MergeStrategy.concat case PathList(「META-INF」,xs @ _ *)=> MergeStrategy.discard'' ' - 你需要所有的服務文件 – juanmirocks