Budujesz plik wykonywalny jar z Maven?

122

Próbuję wygenerować plik jar wykonywalny dla małego projektu domowego o nazwie "logmanager" przy użyciu mavena, tak jak to:

Jak mogę utworzyć wykonywalny plik JAR z zależnościami za pomocą Maven?

Dodałem pokazany tam fragment do pom.xml i uruchomiłem mvn assembly: assembly. Generuje dwa pliki jar w logmanager / target: logmanager-0.1.0.jar i logmanager-0.1.0-jar-with-dependencies.jar. Po dwukrotnym kliknięciu pierwszego słoika pojawia się błąd:

Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.

Nieco inny błąd po dwukrotnym kliknięciu pliku jar-with-dependencies.jar:

Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar

Skopiowałem i wkleiłem ścieżkę i nazwę klasy oraz sprawdziłem pisownię w POM. Moja główna klasa uruchamia się dobrze z konfiguracji uruchamiania zaćmienia. Czy ktoś może mi pomóc dowiedzieć się, dlaczego mój plik jar nie działa? Poza tym, dlaczego na początek są dwa słoiki? Daj mi znać, jeśli potrzebujesz więcej informacji.

Oto pełna pom.xmltreść w celach informacyjnych:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.gorkwobble</groupId>
  <artifactId>logmanager</artifactId>
  <name>LogManager</name>
  <version>0.1.0</version>
  <description>Systematically renames specified log files on a scheduled basis. Designed to help manage MUSHClient logging and prevent long, continuous log files.</description>
  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.2</version>
            <!-- nothing here -->
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2-beta-4</version>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
              <archive>
                <manifest>
                  <mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
                </manifest>
              </archive>
            </configuration>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.6</source>
              <target>1.6</target>
            </configuration>
          </plugin>
    </plugins>
  </build>
  <dependencies>
    <!-- commons-lang -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.4</version>
    </dependency> 

    <!-- Quartz scheduler -->
    <dependency>
        <groupId>opensymphony</groupId>
        <artifactId>quartz</artifactId>
        <version>1.6.3</version>
    </dependency>
    <!-- Quartz 1.6.0 depends on commons collections -->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
    <!-- Quartz 1.6.0 depends on commons logging -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1</version>
    </dependency>
    <!-- Quartz 1.6.0 requires JTA in non J2EE environments -->
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
      <scope>runtime</scope>
    </dependency>

    <!-- junitx test assertions -->
    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>

    <!-- junit dependency; FIXME: make this a separate POM -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.1</version>
    </dependency>

  </dependencies>
  <dependencyManagement>
  </dependencyManagement>
</project>
RMorrisey
źródło

Odpowiedzi:

244

Właściwie uważam, że odpowiedź udzielona w pytaniu , o którym wspomniałeś, jest po prostu błędna ( AKTUALIZACJA - 20101106: ktoś to poprawił , ta odpowiedź odnosi się do wersji poprzedzającej edycję ) i to przynajmniej częściowo wyjaśnia, dlaczego masz kłopoty.


Generuje dwa pliki jar w logmanager / target: logmanager-0.1.0.jar i logmanager-0.1.0-jar-with-dependencies.jar.

Pierwszym z nich jest JAR modułu logmanager generowany podczas packagefazy przez jar:jar(ponieważ moduł ma opakowanie typu jar). Drugi to zestaw wygenerowany przez assembly:assemblyi powinien zawierać klasy z bieżącego modułu i jego zależności (jeśli użyłeś deskryptora jar-with-dependencies).

Po dwukrotnym kliknięciu pierwszego słoika pojawia się błąd:

Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.

Jeśli zastosowałeś sugerowaną konfigurację linku opublikowanego jako odniesienie, skonfigurowałeś wtyczkę jar tak, aby tworzyła wykonywalny artefakt, coś takiego:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

Tak więc logmanager-0.1.0.jarjest rzeczywiście wykonywalny, ale 1. nie jest tym, czego chcesz (ponieważ nie ma wszystkich zależności) i 2. nie zawiera com.gorkwobble.logmanager.LogManager(tak mówi błąd, sprawdź zawartość jar).

Nieco inny błąd po dwukrotnym kliknięciu pliku jar-with-dependencies.jar:

Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar

Ponownie, jeśli skonfigurowałeś wtyczkę asemblera zgodnie z sugestią, masz coś takiego:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
  </plugin>

W tej konfiguracji logmanager-0.1.0-jar-with-dependencies.jarzawiera klasy z bieżącego modułu i jego zależności, ale zgodnie z błędem META-INF/MANIFEST.MF nie zawiera Main-Classwpisu (prawdopodobnie nie jest to ten sam plik MANIFEST.MF, jak w logmanager-0.1.0.jar). Jar faktycznie nie jest wykonywalny, co znowu nie jest tym, czego chcesz.


Tak więc moja sugestia byłaby taka, aby usunąć configurationelement z wtyczki maven-jar-plugin i skonfigurować wtyczkę maven-assembly-plugin w następujący sposób:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.2</version>
    <!-- nothing here -->
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2-beta-4</version>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>org.sample.App</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

Oczywiście zamień org.sample.Appna klasę, którą chcesz wykonać. Mały bonus, związałem assembly:singlesię z packagefazą, więc nie musisz assembly:assemblyjuż biec . Po prostu uruchom, mvn installa montaż zostanie wyprodukowany podczas standardowej kompilacji.

Dlatego zaktualizuj swój pom.xml z konfiguracją podaną powyżej i uruchom mvn clean install. Następnie przejdź do plikutarget katalogu i spróbuj ponownie:

java -jar logmanager-0.1.0-jar-with-dependencies.jar

Jeśli pojawi się błąd, zaktualizuj swoje pytanie i opublikuj zawartość META-INF/MANIFEST.MFpliku oraz odpowiednią część swojego pom.xml(części konfiguracyjne wtyczek). Prosimy również o opublikowanie wyniku:

java -cp logmanager-0.1.0-jar-with-dependencies.jar com.gorkwobble.logmanager.LogManager

aby zademonstrować, że działa dobrze w wierszu poleceń (niezależnie od tego, co mówi eclipse).

EDYCJA: W przypadku Java 6 musisz skonfigurować wtyczkę maven-compiler-plugin. Dodaj to do swojego pom.xml:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
Pascal Thivent
źródło
4
Dzięki za komentarze! Zmieniłem plik pom.xml zgodnie z opisem. Kiedy uruchamiam czystą instalację mvn, otrzymuję kilka błędów kompilacji z mojego kodu, które mówią, że adnotacje i tak dalej nie są obsługiwane w -source 1.3. Używam jdk1.6 i kompiluje się w eclipse; Nie jestem pewien, jak wprowadzono 1.3. Może jedna z wersji biblioteki we fragmencie pom jest starsza?
RMorrisey
Dzięki! Przekroczyłem problem 1.3. Musiałem również dodać zależność junit4 do mojego POM. Pracuję nad rozwiązywaniem innych problemów; jeśli utknę, opublikuję ponownie! Jeśli uruchomię słoik, zaznaczę to jako odpowiedź. Mój obecny POM został zaktualizowany w powyższym pytaniu.
RMorrisey
Czy istnieje sposób na wykluczenie zasobów z wygenerowanego pliku jar?
2
Czy możliwe jest, aby utworzony słoik miał „normalną” nazwę?
Daniil Shevelev,
1
Uważam również, że ten post na blogu Sonatype jest przydatny
15

Pomogła mi również odpowiedź Pascala Thiventa . Ale jeśli zarządzasz wtyczkami w <pluginManagement>elemencie, musisz ponownie zdefiniować zestaw poza zarządzaniem wtyczkami, w przeciwnym razie zależności nie są pakowane w jar po uruchomieniu mvn install.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>


    <build>
        <pluginManagement>
            <plugins>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.4</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>main.App</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>

        </pluginManagement>

        <plugins> <!-- did NOT work without this  -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
            </plugin>
        </plugins>

    </build>


    <dependencies>
       <!--  dependencies commented out to shorten example -->
    </dependencies>

</project>
mikrofon
źródło
1
Dzięki Mike, pomogło mi. Początkowo mój pakiet był generowany bez użycia <pluginManagement>. Ale Eclipse dawało błąd w pom.xml "maven - wykonanie wtyczki nie jest objęte cyklem życia". Co mnie rozprasza. Aby rozwiązać ten problem, dodałem <pluginManagement>, teraz błąd zaćmienia zniknął, ale mój pakiet przestał być budowany. Twój powyższy fragment pom zadziałał dla mnie. :)
shashaDenovo
2
Było to przydatne ... podczas korzystania z <pluginManagement> pierwsza odpowiedź nie zadziała.
ininprsr
5

Jeśli nie chcesz wykonywać celu montażu na pakiecie, możesz użyć następnego polecenia:

mvn package assembly:single

Tutaj pakiet jest słowem kluczowym.

leonidv
źródło
-1

Kliknij prawym przyciskiem myszy projekt i daj maven build, maven clean, maven generowanie zasobów i maven install. Plik jar zostanie wygenerowany automatycznie.

lalka dolly
źródło