2016-04-25 11 views
5

staram się budować słoik z czystym projektu z sbt-assembly jak opisano w docs:Jak zbudować słoik z ramowym zabaw 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) 

ale daje mi dużo błędów deduplikuj. Jak zbudować "gruby" słoik z gry z sbt-assembly?

+0

Czy na pewno słoik jest najlepszym rozwiązaniem. Pakiety instalacyjne Sbt-build kompilują pakiety prawie po wyjęciu z pudełka – mgosk

+0

@zella, wklej część swojego dziennika błędów. – Nio

Odpowiedz

9

Istnieje kilka bitów, które należy skonfigurować, aby zbudować aplikację jako słoik.

Począwszy od wtyczki asssembly. Musi być plik o nazwie assembly.sbt znajdujący się bezpośrednio w katalogu projektu. Aby być dokładnym i wyeliminować zamieszanie, jeśli twój projekt ma nazwę MyPlayProject, plik musi znajdować się w "MyPlayProject/project/assembly.sbt" i powinien zawierać tylko następujące elementy.

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

Oczywiście wersja może ulec zmianie, ale powinna działać. Spowoduje to dodanie wtyczki zespołu do projektu i nie będzie działać po dodaniu do pliku plugins.sbt, tak jak inne wtyczki.

W celu objęcia wszystkich podstaw upewnij się, że posiadasz standardowe elementy sbt, w tym projekt/build.properties. Zauważ, że dla wersji 2.5.x play SBT 13.8 lub nowszy jest wymagany za https://www.playframework.com/documentation/2.5.x/Migration25#sbt-upgrade-to-0.13.11

sbt.version=0.13.11 

I prawdopodobnie część krytyczna powodując swoje problemy jest częścią pliku build.sbt która powinna obejmować strategię scalania. Istnieje wiele plików, które są standardowe w plikach jar (np. MANIFEST.MF itp.) I musisz zrobić coś, aby obsłużyć te zduplikowane pliki, gdy połączysz wszystkie słoiki w pojedynczy słoik. Podstawowy przykład:

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 
} 

Twój przebieg może być bardzo duży w przypadku konkretnych przypadków, ale jest to dość podstawowe dla standardowego słoika do gry.

Niektóre podstawowe informacje na temat powyższej strategii łączenia się następująco:

  • Scalanie reference.conf wszystko Jar do pojedynczego pliku do tłuszczu słoiku. Zapomniałem o konkretnym problemie, który do tego doprowadził, ale nie sądzę, że będziesz mógł uruchomić aplikację do odtwarzania jako słoik bez tego kroku. Nie mam na to żadnego dowodu)
  • Odrzuć pliki MANIFEST.MF dla każdego słoika. Wiele przykładów online pokazuje to jako "PathList przypadku (" META-INF ", xs @ _ *) => MergeStrategy.discard". Działa to poprzez usunięcie czegokolwiek z katalogu słoików META-INF. Jednak uruchamianie wtyczki zależnej Play 2.4 zostało mocno zepchnięte podczas gry, a przy użyciu wtyczki zależnej istnieje zależność biblioteki od net.sf.ehcache, która zawiera pliki serwisowe wymagane do użycia wtyczki zależności. Rozwiązaniem jest pozostawienie wszystkich innych plików i po prostu wyrzucenie plików MANIFEST.MF specjalnie jak to zrobiłem lub po prostu usunąć wszystko i nie używać niczego wtrysku zależnego (niezalecane)
  • Ogólny haczyk w każdym przypadku, który utrzymuje pierwsze wszystkich duplikatów plików i odrzuca pozostałe. Przydatne, gdy możesz mieć wiele wspólnych zależności w tej samej bibliotece i nie ma powodu, aby przechowywać wiele kopii.

Ponieważ nie mogę wyjaśnić z komentarzami tutaj, jest to kompletny przykładowy plik 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 
} 

bym opuścił komentarzy dla więcej szczegółów przed odebraniem więc mogłem być bardziej dokładny z moją odpowiedź, ale pytanie jest nieco stary i to powiedział mój rep nie jest wystarczająco wysoki, tak czy inaczej ... mam nadzieję, że to pomoże .

P.S. Znalazłem twoje pytanie podczas szukania pomocy w moich własnych kwestiach scalania migracji gier 2.3.4 do 2.5.4. Właśnie dlatego zmieniłem strategię scalania META-INF, aby odrzucić tylko MANIFEST.MF, w przeciwnym razie spowoduje to poniższy wyjątek. Przesyłam ją ponownie z moją odpowiedzią, mając nadzieję, że zostanie ona pobrana w wynikach wyszukiwania, ponieważ na początku znalazłem bardzo niewiele.

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

rok później, dziękuję !! Znalazłem twój tekst edytowany w PS. Zrobiłem to, co zasugerowałeś, ale dostaję błąd "Nieprawidłowy podpis" na słoiku. Wciąż mam pojęcie, gdzie na ciebie spojrzeć dzięki. Błąd, który dostaję: 'org.apache.flink.client.program.ProgramInvocationException: Klasa punktu wejścia programu 'net.tagtog.services.documents.flink.Job' spowodowała wyjątek podczas inicjalizacji: niepoprawny plik podpisu dla głównych atrybutów Manifestu ' – juanmirocks

+0

Znaleziono rozwiązanie! (to przynajmniej dla mnie działało). To: '' 'case PathList (" META-INF "," usługi ", xs @ _ *) => MergeStrategy.concat case PathList (" META-INF ", xs @ _ *) => MergeStrategy.discard'' '- Potrzebujesz wszystkich plików usług – juanmirocks