Używam SBT (w IntelliJ IDEA) do zbudowania prostego projektu Scala.
Chciałbym wiedzieć, jaki jest najprostszy sposób na zbudowanie pliku JAR Ubera (inaczej Fat JAR, Super JAR).
Obecnie używam SBT, ale podczas przesyłania mojego pliku JAR do Apache Spark pojawia się następujący błąd:
Wyjątek w wątku „main” java.lang.SecurityException: Nieprawidłowe podsumowanie pliku podpisu dla głównych atrybutów manifestu
Lub ten błąd podczas kompilacji:
java.lang.RuntimeException: deduplicate: inna zawartość pliku znaleziona w następującym:
PATH \ DEPENDENCY.jar: META-INF / DEPENDENCIES
PATH \ DEPENDENCY.jar: META-INF / MANIFEST.MF
To wygląda to dlatego, że niektóre z moich uzależnień zawierać pliki sygnatur (meta-inf), która musi być usunięta w końcowym Uber pliku JAR.
Próbowałem użyć wtyczki sbt-assembly w następujący sposób :
/project/assembly.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
/project/plugins.sbt
logLevel := Level.Warn
/build.sbt
lazy val commonSettings = Seq(
name := "Spark-Test"
version := "1.0"
scalaVersion := "2.11.4"
)
lazy val app = (project in file("app")).
settings(commonSettings: _*).
settings(
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "1.2.0",
"org.apache.spark" %% "spark-streaming" % "1.2.0",
"org.apache.spark" % "spark-streaming-twitter_2.10" % "1.2.0"
)
)
Kiedy klikam „ Build Artifact ... ” w IntelliJ IDEA, otrzymuję plik JAR. Ale kończy się z tym samym błędem ...
Jestem nowy w SBT i niezbyt eksperymentowałem z IntelliJ IDE.
Dzięki.
META-INF
pliki - jeden blogu, że może pomóc: janschulte.wordpress.com/2014/03/20/...Odpowiedzi:
Wreszcie całkowicie pomijam używanie IntelliJ IDEA, aby uniknąć generowania hałasu w moim globalnym rozumieniu :)
Zacząłem czytać oficjalny poradnik SBT .
Stworzyłem swój projekt o następującej strukturze plików:
Dodano wtyczkę sbt-assembly w moim pliku assembly.sbt . Pozwalając mi zbudować gruby JAR:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Mój minimal build.sbt wygląda następująco:
lazy val root = (project in file(".")). settings( name := "my-project", version := "1.0", scalaVersion := "2.11.4", mainClass in Compile := Some("myPackage.MyMainObject") ) val sparkVersion = "1.2.0" libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % sparkVersion % "provided", "org.apache.spark" %% "spark-streaming" % sparkVersion % "provided", "org.apache.spark" %% "spark-streaming-twitter" % sparkVersion ) // META-INF discarding mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first } }
Uwaga :
% "provided"
środki, aby nie uwzględniać zależności w ostatecznym grubym pliku JAR (te biblioteki są już uwzględnione w moich plikach roboczych)Uwaga : odrzucanie META-INF zainspirowane tą odpowiedzią .
Uwaga : znaczenie
%
i%%
Teraz mogę zbudować mój gruby JAR za pomocą SBT ( jak go zainstalować ), uruchamiając następujące polecenie w folderze głównym mojego / my-project :
Mój gruby plik JAR znajduje się teraz w nowym folderze wygenerowanym / docelowym :
/my-project/target/scala-2.11/my-project-assembly-1.0.jar
Mam nadzieję, że to pomoże komuś innemu.
Dla tych, którzy chcą wprowadzić SBT do IntelliJ IDE: Jak uruchamiać zadania składania sbt z poziomu IntelliJ IDEA?
źródło
3-etapowy proces tworzenia Uber JAR / Fat JAR w IntelliJ Idea:
Uber JAR / Fat JAR : plik JAR zawierający wszystkie zewnętrzne zależności bibliotek.
Dodanie wtyczki SBT Assembly w IntelliJ Idea
Przejdź do pliku ProjectName / project / target / plugins.sbt i dodaj tę linię
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Dodawanie strategii scalania, odrzucania i nie dodawania w pliku build.sbt
Przejdź do pliku ProjectName / build.sbt i dodaj strategię pakowania pliku JAR Uber
Strategia scalania: Jeśli występuje konflikt między dwoma pakietami dotyczącymi wersji biblioteki, to który z nich należy spakować w Uber JAR.
Odrzuć strategię: aby usunąć niektóre pliki z biblioteki, których nie chcesz pakować do Uber JAR.
Nie dodawaj strategii: Nie dodawaj żadnego pakietu do Uber JAR.
Na przykład:
spark-core
będzie już obecny w Twoim Spark Cluster, więc nie powinniśmy tego pakować w Uber JARPodstawowy kod strategii scalania i odrzucania strategii:
assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }
Więc prosisz o odrzucenie plików META-INF za pomocą tego polecenia,
MergeStrategy.discard
a dla pozostałych plików pobierasz pierwsze wystąpienie pliku biblioteki, jeśli wystąpi konflikt za pomocą tego poleceniaMergeStrategy.first
.Nie dodawaj podstawowego kodu strategii:
libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1" %"provided"
Jeśli nie chcemy dodawać iskiernika do naszego pliku JAR Ubera, ponieważ będzie on już na naszym sprzęcie, dodajemy
% "provided"
na końcu zależność od biblioteki.Tworzenie Uber JAR ze wszystkimi jego zależnościami
W typie terminala
sbt assembly
do tworzenia pakietuVoila !!! Uber JAR jest zbudowany. JAR będzie w ProjectName / target / scala-XX
źródło
Dodaj następujący wiersz do swojego projektu / plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Dodaj następujące elementy do pliku build.sbt
mainClass in assembly := some("package.MainClass") assemblyJarName := "desired_jar_name_after_assembly.jar" val meta = """META.INF(.)*""".r assemblyMergeStrategy in assembly := { case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first case n if n.startsWith("reference.conf") => MergeStrategy.concat case n if n.endsWith(".conf") => MergeStrategy.concat case meta(_) => MergeStrategy.discard case x => MergeStrategy.first }
Strategia scalania zestawów służy do rozwiązywania konfliktów występujących podczas tworzenia słoika tłuszczu.
źródło