Zbudowanie działającego słoika za pomocą Maven 2

82

Jestem stosunkowo nowy w mantrze Maven, ale próbuję zbudować słoik uruchamiany z wiersza poleceń z Mavenem. Skonfigurowałem zależności, ale kiedy uruchamiam mvn installi próbuję uruchomić jar, dzieją się dwie rzeczy. Po pierwsze, nie znaleziono żadnej klasy głównej, którą można poprawić. Kiedy to poprawiłem, podczas uruchamiania pojawiają się błędy informujące, że nie można znaleźć klas.

Maven nie pakuje moich bibliotek zależności wewnątrz jar, więc nie mogę uruchomić jar jako samodzielnej aplikacji. Jak to poprawić?

Stefan Kendall
źródło
Możesz użyć IDE dla mavena, takiego jak Netbenas
Sajad Bahmani,
7
@SjB: i to magicznie rozwiązuje problem? Nie sądzę.
Joachim Sauer
1
Dokładny duplikat czego dokładnie?
Stefan Kendall,
Może ten stackoverflow.com/questions/1832853/… lub ten stackoverflow.com/questions/574594/… (ale zaakceptowana odpowiedź jest nieprawidłowa), albo ten stackoverflow.com/questions/1814526/… . Właściwie to wydaje się być jednym z najczęściej zadawanych pytań na temat
mavena
1
Pozostałe odpowiedzi nie są tak czyste, a jar Uber (niepoprawnie napisany ueber) nie wspomina o wykonywalności. Co więcej, inne tematy są zaśmiecone nieistotnymi materiałami, takimi jak poziom źródłowy itp.
Stefan Kendall

Odpowiedzi:

113

Najłatwiejszym sposobem byłoby utworzenie zestawu przy użyciu maven-assembly-pluginpredefiniowanego jar-with-dependenciesdeskryptora i. Będziesz także musiał wygenerować manifest z wpisem klasy głównej dla tego jar Uber. Poniższy fragment kodu pokazuje, jak skonfigurować wtyczkę zespołu, aby to zrobić:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

Następnie, aby wygenerować zestaw, po prostu uruchom:

mvn assembly:assembly

Jeśli chcesz wygenerować zestaw jako część swojej kompilacji, po prostu assembly:singlepołącz mojo z fazą pakietu:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
      </configuration>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

I po prostu uruchom:

mvn package
Pascal Thivent
źródło
1
Wtyczka maven-shadow-plugin również działa podobnie i jest przeznaczona do tego celu.
Dominic Mitchell
4
Nie działa to w przypadku spring i innych bibliotek, które oczekują wielu zasobów o tej samej nazwie w ścieżce klas. W przypadku wiosny META-INF \ spring.schemas znajduje się w kilku plikach jar (beanie, jdbc itp.) I służy do konfigurowania obsługi przestrzeni nazw XML dla parsera XML. Jeśli spróbujesz 'jar-with-dependencies', przekazanie application-context.xml nie powiedzie się w czasie wykonywania i wyświetli coś takiego jak "org.xml.sax.SAXParseException: cvc-elt.1: Nie można znaleźć deklaracji elementu 'beans'."
David Roussel
@David Maven nie rozwiąże „ograniczenia” Java. W takim przypadku po prostu spakuj aplikację w czysty sposób (tj. Nie w uberjar).
Pascal Thivent
Działa to z konfiguracją Spring bez problemów. Moja główna klasa ładuje wszystkie inne klasy z kontekstem Classpath Application i to rozwiązanie działa doskonale.
vsingh
2
assembly:assemblyCelem jest przestarzała
Jared Beck
25

Maven nie pakuje zależności w Twoim pliku jar, ponieważ zazwyczaj nie robisz tego w programach Java.

Zamiast dostarczyć zależności razem z plikiem jar i wymienić je w Class-Pathnagłówku manifest .

Aby przejść tę trasę, musisz włączyć addClasspathwłaściwość (udokumentowaną tutaj ) dla maven-jar-plugin.

Jeśli naprawdę chcesz uwzględnić wszystkie zależności w pliku jar, możesz użyć wtyczki Maven Assembly, aby utworzyć plik jar-with-dependencies.

Joachim Sauer
źródło
4
+1 Trudno mi było znaleźć informacje o tym, jak programy Java są zwykle budowane i dystrybuowane, zwłaszcza z Maven.
Ed Brannin
8

To właśnie zrobiłbym dla małych projektów. W większości przypadków nie chcesz jednego dużego słoika.

zbudować: mvn clean dependency: copy-dependencies pakiet

do wykonania ( w katalogu docelowym ): java -cp myjar.jar: ./ dependency / * com.something.MyClass

user2409824
źródło
Świetny! Zapisałem to w moim Makefile, w tym samym katalogu z pom.xml. build: \ n mvn .... (co powiedziałeś)
Roboprog
Dzięki. Po przeszukaniu internetu przez ponad 2 godziny znalazłem tę bardzo przydatną odpowiedź ...
Shekhar
6

Zgadzam się z Joachimem Sauerem,

Zamiast używać jar-with-dependency, powinieneś skonfigurować wtyczkę jar w taki sposób, jak w pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <index>true</index>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>[mainClassFullName]</mainClass>
            </manifest>
            <manifestEntries>
                <mode>development</mode>
                <url>${project.url}</url>
                <key>value</key>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

I użyj tej konfiguracji zestawu, aby dodać zależności jar do swojego zestawu:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
  <id>zip-with-jars</id>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySets>
    <dependencySet>
    <outputDirectory>/</outputDirectory>
    <useProjectArtifact>true</useProjectArtifact>
    <unpack>false</unpack>
    <scope>runtime</scope>
    </dependencySet>
</dependencySets>
  </dependencySets>
</assembly>
formixian
źródło
2

Po prostu dodaj poniższy kod w pom.xml i uruchom jako: maven: install. Jar zostanie utworzony w folderze docelowym eclipse, którego można użyć jako „java -jar Hello.jar”. ale upewnij się, że nazwa klasy głównej to com.abc.HelloWorld.java

<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-shade-plugin</artifactid>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalname>HelloW</finalname>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestentries>
<main-class>com.abc.HelloWorld.java</main-class>
<build-number>1</build-number>
</manifestentries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

</build>
Patelnia
źródło