Как сказать Maven построить исполняемый файл jar - PullRequest
1 голос
/ 24 февраля 2011

Кажется, это должно быть просто, но я не понял этого и не получил большой помощи от чтения документов и поиска в Интернете. В попытке научиться использовать Maven (2.2.1) с многомодульным проектом, я использовал Maven для создания простого проекта P с классом C (содержащим main) и подклассом S. Когда я запускаю mvn install, сборка запускается и создает сообщение BUILD SUCCESSFUL. Однако, когда я запускаю полученный C jar, я получаю исключение: «Исключение в потоке» main »java.lang.NoClassDefFoundError: P / S"

Структура каталогов (без отображения подкаталогов src и т. Д.):

P
| * 1007-C * | * 1008-S *

pom.xml в каталоге P в настоящее время:

<?xml version="1.0" encoding="UTF-8"?>
<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>P</groupId>
  <artifactId>P</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>P</name>
  <url>http://maven.apache.org</url>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>P</groupId>
        <artifactId>C</artifactId>
        <version>${project.version}</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>P</groupId>
        <artifactId>S</artifactId>
        <version>${project.version}</version>  
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>P.C</mainClass>
              <packageName>P.C</packageName>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <modules>
    <module>C</module>
    <module>S</module>
  </modules>

</project>

Pom.xml в C:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>P</artifactId>
    <groupId>P</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>P</groupId>
  <artifactId>C</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>C</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>P</groupId>
      <artifactId>S</artifactId>
      <version>${project.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

и pom.xml в S:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>P</artifactId>
    <groupId>P</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>P</groupId>
  <artifactId>S</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>S</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Выше приведены все последние версии после нескольких попыток.

Для этого простого учебного упражнения классы Java:

* * 1 022 P / C / SRC / Основной / Java / P / C.java:
package P;

public class C
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        S o = new S();
        o.sayHey();
    }
}

и S / src / main / java / P / S.java:

package P;

public class S
{
    public void sayHey()
    {
        System.out.println("Hey!");
    }
}

Итак, как мне сказать Maven включить класс S в банку C?

Ответы [ 3 ]

3 голосов
/ 24 февраля 2011

Maven не включает зависимости в артефакты по умолчанию: для запуска P вам все еще нужен S в вашем пути к классам.

Обычно это не проблема, так как сам maven использует транзитивные зависимости: например, если у вас естьдругой проект зависит от P, он автоматически поместит P и S в ваш classpath.

Если вы хотите создать 'uber-jar': автономный jar, содержащий все зависимости, посмотрите на 'shade'Плагин: http://maven.apache.org/plugins/maven-shade-plugin/

3 голосов
/ 24 февраля 2011

После дополнительных исследований я нашел способ сообщить Maven о создании файла jar, который включает все необходимые классы. Единственная помпа, которую я должен был изменить, была в каталоге P. Во-первых, следующий раздел должен быть удален из раздела build-plugins:

    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <mainClass>P.C</mainClass>
          <packageName>P.C</packageName>
        </manifest>
      </archive>
    </configuration>

На его место я положил:

    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
      <execution>
        <id>create-executable-jar</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>P.C</mainClass>
              <packageName>P.C</packageName>
            </manifest>
          </archive>
        </configuration>
      </execution>
    </executions>
1 голос
/ 24 февраля 2011

Плагин maven exec может решить вашу проблему.Вы можете использовать его для запуска C.jar, и он будет управлять путем к классам (и убедитесь, что S.jar включен).

Добавьте что-то похожее на этот файл P pom.xml:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.1</version>
        <executions>
          <execution>
            ...
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>P.C</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
   ...
</project>

Тогда вы сможете запустить программу следующим образом:

mvn exec:java -Dexec.mainClass="P.C"
...