Управление многомодульными зависимостями с помощью подключаемого модуля Maven - PullRequest
8 голосов
/ 27 января 2012

Я использую плагин сборки Maven для создания сборки для моего многомодульного проекта.Из этого многомодульного проекта построено два отдельных приложения, каждое из которых имеет отдельный набор зависимостей.Я сделал собственный дескриптор сборки, который собирает две директории (для каждого приложения) со сборками модулей и соответствующими им зависимостями.Он делает все отлично, но одно - он помещает зависимости для обоих модулей в сборку друг друга.

Ниже приведена упрощенная версия моего проекта, которая имеет точно такое же поведение.

РассмотримПроект, состоящий из двух модулей и модуля сборки:

APP
  module1
  module2
  assembly

Я добавил зависимости исключительно для демонстрации:

com.test.app:module1:jar:1.0
\- commons-cli:commons-cli:jar:1.2:compile

com.test.app:module2:jar:1.0
\- commons-daemon:commons-daemon:jar:1.0.8:compile

Вот родительский POM:

<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test</groupId>
  <artifactId>app</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>

  <modules>
    <module>module1</module>
    <module>module2</module>
    <module>assembly</module>
  </modules>
</project>

module1 POM:

<project>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>app</artifactId>
    <version>1.0</version>
  </parent>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test.app</groupId>
  <artifactId>module1</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
      <groupId>commons-cli</groupId>
      <artifactId>commons-cli</artifactId>
      <version>1.2</version>
    </dependency>
  </dependencies>
</project>

module2 POM:

<project>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>app</artifactId>
    <version>1.0</version>
  </parent>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test.app</groupId>
  <artifactId>module2</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
      <groupId>commons-daemon</groupId>
      <artifactId>commons-daemon</artifactId>
      <version>1.0.8</version>
    </dependency>
  </dependencies>
</project>

POM сборки:

<project>
  <parent>
    <groupId>com.test</groupId>
    <artifactId>app</artifactId>
    <version>1.0</version>
  </parent>

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test.app</groupId>
  <artifactId>assembly</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2.2</version>

        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>

            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>

        <configuration>
          <appendAssemblyId>false</appendAssemblyId>

          <descriptors>
            <descriptor>src/main/assembly/descriptor.xml</descriptor>
          </descriptors>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

И, наконец, дескриптор сборки:

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>

  <formats>
    <format>dir</format>
  </formats>

  <moduleSets>
    <moduleSet>
      <useAllReactorProjects>true</useAllReactorProjects>

      <includes>
        <include>com.test.app:module1:jar</include>
      </includes>

      <binaries>
        <outputDirectory>module1</outputDirectory>
        <unpack>false</unpack>

        <dependencySets>
          <dependencySet>
            <unpack>false</unpack>
          </dependencySet>
        </dependencySets>
      </binaries>
    </moduleSet>

    <moduleSet>
      <useAllReactorProjects>true</useAllReactorProjects>

      <includes>
        <include>com.test.app:module2:jar</include>
      </includes>

      <binaries>
        <outputDirectory>module2</outputDirectory>
        <unpack>false</unpack>

        <dependencySets>
          <dependencySet>
            <unpack>false</unpack>
          </dependencySet>
        </dependencySets>
      </binaries>
    </moduleSet>
  </moduleSets>
</assembly>

Как видите, сборка привязана к фазе упаковки.Итак, когда я выполняю

mvn package

из родительского каталога, у меня появляется следующая сборка

module1/
  commons-cli-1.2.jar
  commons-daemon-1.0.8.jar
  module1-1.0.jar
module2/
  commons-cli-1.2.jar
  commons-daemon-1.0.8.jar
  module2-1.0.jar

В принципе, проблема здесь в том, что module1 не зависит от commons-daemon, ноСборка плагина включила зависимость.Аналогично, с module2 и commons-cli.

Может кто-нибудь объяснить, почему плагин сборки ведет себя таким образом?

А что было бы решением?

1 Ответ

10 голосов
/ 28 января 2012

У меня всегда был похожий опыт использования плагина сборки с многомодульными проектами, где конечный результат оказался не таким, как я ожидал. Я надеюсь, что кто-то другой сможет дать более точный ответ о том, почему это происходит и как лучше использовать эти две концепции в тандеме.

Тем не менее, возможный обходной путь заключается в том, чтобы module1 и module2 генерировали свои собственные артефакты сборки, которые содержат их соответствующие jar-файлы и зависимости. Затем вы можете изменить pom-файл подмодуля сборки, чтобы иметь зависимости от сгенерированных артефактов распространения из его родственных модулей, а затем распаковать их в новую сборку.

В pom-файлах как Module1, так и Module2 вы можете добавить конфигурацию подключаемого модуля к фазе пакета так же, как вы делали с субмодулем сборки.

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2.2</version>

        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>

        <configuration>
          <descriptors>
            <descriptor>src/main/assembly/descriptor.xml</descriptor>
          </descriptors>
        </configuration>
      </plugin>
    </plugins>
  </build>

Module1 будет иметь такой src / main / assembly / descriptor.xml, как этот

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>

  <formats>
    <format>zip</format>
  </formats>

  <dependencySets>
    <dependencySet>
      <outputDirectory>module1</outputDirectory>
      <unpack>false</unpack>
    </dependencySet>
  </dependencySets>
</assembly>

И у Module2 будет аналогичный файл src / main / assembly / descriptor.xml

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>

  <formats>
    <format>zip</format>
  </formats>

  <dependencySets>
    <dependencySet>
      <outputDirectory>module2</outputDirectory>
      <unpack>false</unpack>
    </dependencySet>
  </dependencySets>
</assembly>

Затем в сборку / pom.xml вы добавилие артефакты zip модуля 1 и 2 в качестве зависимостей

  <dependencies>
    <dependency>
      <groupId>com.test.app</groupId>
      <artifactId>module1</artifactId>
      <version>1.0</version>
      <type>zip</type>
      <classifier>distribution</classifier>
    </dependency>
    <dependency>
      <groupId>com.test.app</groupId>
      <artifactId>module2</artifactId>
      <version>1.0</version>
      <type>zip</type>
      <classifier>distribution</classifier>
    </dependency>
  </dependencies>

... и обрежьте файл assembly / src / main / assembly / descriptor.xml так, чтобы он выглядел следующим образом

<assembly>
  <id>distribution</id>
  <includeBaseDirectory>false</includeBaseDirectory>

  <formats>
    <format>dir</format>
  </formats>

  <dependencySets>
    <dependencySet>
      <useTransitiveDependencies>false</useTransitiveDependencies>
      <unpack>true</unpack>
    </dependencySet>
  </dependencySets>

</assembly>

Как я уже говорил, это будет одним из возможных способов обхода, и, к сожалению, он добавляет значительный объем дополнительной конфигурации XML в ваш процесс сборки. Но это работает.

...