Можно ли настроить многомодульный архетип maven, чтобы иметь дополнительные модули?

Я собираюсь создать многомодульный архетип. Он будет генерировать несколько модулей. Некоторым пользователям архетипа может понадобиться все они, в то время как некоторые из них нуждаются только в некоторых из них.

Может ли мой архетип взять аргументы из командной строки и решить, какие модули сгенерировать? Я проверил https://maven.apache.org/archetype/archetype-models/archetype-descriptor/archetype-descriptor.html и, похоже, это не поддерживает.

Ответы

Ответ 1

В этом конкретном случае архетип всегда может создавать все необходимые модули и перемещать различные варианты (набор модулей) в профили. Только один профиль будет активным по умолчанию, как указано во время шага archetype:generate.

Как таковой, если я хочу иметь набор модулей для aromA, я буду запускать архетип как

mvn archetype:generate -DarchetypeGroupId=.. -DflavorA=true

И архетип передаст эту переменную элементу activeByDefault профиля aromA, переопределяющему элемент modules для набора модулей, требуемых пользователями flavorA.

То же самое можно сделать и для flavorB и flavorB (например), каждый из которых определяет другой набор модулей.

Примером такого агрегатора/родительского ПОМ как части архетипа будет:

<profiles>
    <profile>
        <id>flavourA</id>
        <activation>
            <activeByDefault>${flavourA}</activeByDefault>
        </activation>
        <modules>
            <module>profiled-module2</module>
            <module>profiled-module3</module>
        </modules>
    </profile>
    <profile>
        <id>flavourB</id>
        <activation>
            <activeByDefault>${flavourB}</activeByDefault>
        </activation>
        <modules>
            <module>profiled-module3</module>
        </modules>
    </profile>
    <profile>
        <id>flavourC</id>
        <activation>
            <activeByDefault>${flavourC}</activeByDefault>
        </activation>
        <modules>
            <module>profiles-module1</module>
            <module>profiled-module2</module>
            <module>profiled-module3</module>
        </modules>
    </profile>
</profiles>

В файле archetype-metadata.xml можно указать:

<requiredProperties>
    <requiredProperty key="flavourA">
        <defaultValue>false</defaultValue>
    </requiredProperty>
    <requiredProperty key="flavourB">
        <defaultValue>false</defaultValue>
    </requiredProperty>
    <requiredProperty key="flavourC">
        <defaultValue>false</defaultValue>
    </requiredProperty>
</requiredProperties>

И архетип, вызывается с опцией -DflavorB=true, затем генерирует pom следующим образом:

<profiles>
    <profile>
        <id>flavourA</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <modules>
            <module>profiled-module2</module>
            <module>profiled-module3</module>
        </modules>
    </profile>
    <profile>
        <id>flavourB</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <modules>
            <module>profiled-module3</module>
        </modules>
    </profile>
    <profile>
        <id>flavourC</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <modules>
            <module>profiles-module1</module>
            <module>profiled-module2</module>
            <module>profiled-module3</module>
        </modules>
    </profile>
</profiles>

Такой подход имеет следующие преимущества и недостатки:

<сильные > Преимущества

  • Вы сохраняете общие модули и обслуживание архетипа в одном централизованном месте, оставляя выбор вкусов пользователю архетипа
  • Пользователи архетипа могут, при желании и с нулевой стоимостью, переключаться с одного аромата на другой, просто активируя/дезактивируя профили.
  • Этот подход использует стандартные функции Maven.

Недостатки

  • Каждый архетип будет генерировать весь набор модулей, хотя не все из них потребуются
  • Если действительно "шум", пользователь может вручную удалить нежелательные модули, но все же это будет ручное действие.

Кроме того, помимо вышеприведенного подхода, мы могли бы также настроить Maven Clean Plugin в каждом профиле, чтобы удалить модули, не соответствующие его вкусу, так что при его первой сборке (a maven clean) любой не требуемый модуль будут удалены. Такой подход оставил бы POM с несогласованными профилями, хотя он мог бы также рассматриваться (не рекомендуется).

Что-то вроде:

<profile>
    <id>flavourA</id>
    <activation>
        <activeByDefault>${flavorA}</activeByDefault>
    </activation>
    <modules>
        <module>profiled-module2</module>
        <module>profiled-module3</module>
    </modules>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>${basedir}/profiled-module1</directory>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>
        </plugins>
    </build>
</profile>

Ответ 2

Я разветкил проект и добавил функцию, чтобы включить или отключить генерацию подмодулей на основе свойств, переданных в сеанс Maven.

См. https://github.com/manouti/maven-archetype.

Установив -DgenerateEnableProperties=true при вызове цели create-from-project, плагин создаст свойства enabler для каждого дочернего модуля в форме generate.module.X. При вызове цели generate после этого можно исключить модуль, передав -Dgenerate.module.X=false.

В качестве альтернативы:

Возможно, вы сможете обойти это с помощью частичных архетипов, установив partial="true" в дескриптор, что позволяет генерировать проект поверх существующего проекта. Этот пост, похоже, решает ту же проблему.

Затем вы можете написать script, который берет требуемые свойства и генерирует соответствующие части проекта, используя частичные архетипы, например. используя Ant:

<target name="mvn.generate.project.module1" if="generate.module1">
    <exec dir="." executable="sh">
        <arg value="-c" />
        <arg value="mvn archetype:generate -DarchetypeGroupId="com.example.project" -DarchetypeArtifactId="archetype1" ..." />
    </exec>
</target>

<target name="mvn.generate.project.module2" if="generate.module2">
    <exec dir="." executable="sh">
        <arg value="-c" />
        <arg value="mvn archetype:generate -DarchetypeGroupId="com.example.project" -DarchetypeArtifactId="archetype2" ..." />
    </exec>
</target>

Обновление (6/11/16):

Связанная проблема https://issues.apache.org/jira/browse/ARCHETYPE-494. Из описания коммиттера:

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

Ответ 3

Я думаю, что вы спрашиваете в контексте этой проблемы:

https://issues.apache.org/jira/browse/ARCHETYPE-494

Я уже реализовал его и буду включен в следующую версию плагина maven archetype. Там вы можете указать файл groovy, который будет выполнен после генерации архетипа. Я лично использую этот файл groovy для выполнения чего-то подобного: я читаю свойства из командной строки, а затем удаляю объявленные зависимости, классы и файлы jsp, которые пользователю не нужны.

Пожалуйста, дайте мне знать, если это поможет.