Афоризм
Рецепт молодости — радуйтесь каждой мелочи, и не нервничайте из-за каждой сволочи.
Последние статьи

 • Компонент JDatePicker
Описание и пример компонента JDatePicker
сентябрь 2019
 • Компонент Tree
Описание и пример дерева Tree
сентябрь 2019
 • Grid с навигатором
Описание и пример Gridp с навигатором
сентябрь 2019
 • Компонент Grid
Описание и пример Grid библиотеки base-gui
август 2019
 • Библиотека base-gui
Описание компонентов библиотеки base-gui
август 2019
 • Оператор SELECT
Использование SQL-оператора SELECT
август 2019
 • Сокеты в Android
Использование сокетов в Android
июль 2019
 • Многомодульный maven
Пример создания многомодульного maven проекта
июнь 2019
 • Maven плагин launch4j
Создание exe-файла из исполняемого jar
июнь 2019

Многомодульный maven проект

Maven позволяет собирать проект из нескольких модулей. Каждый программный модуль включает свой проектный файл pom.xml. Один из проектных pom.xml файлов является корневым. Корневой pom.xml позволяет объединить все модули в единый проект. При этом в корневой проектный файл можно вынести общие для всех модулей свойства. А каждый модульный pom.xml должен включать параметры GAV (groupId, artifactId, version) корневого pom.xml.

Общие положения разработки многомодульного maven-приложения рассмотрены на странице Наследование проектов в maven. В данной статье рассмотрим пример сборки многомодульного приложения. В качестве «подопытного» приложения используем пример, представленный на странице Pluggable решение. На выходе данного примера мы должны получить 3 архивных и один исполняемый jar-файлов. Главный исполняемый jar-модуль динамически «при необходимости» загружает остальные архивные jar'ники. Данный «подопытный» пример был использован для «оборачивания» jar'ника в exe-файл с использованием maven-плагина launch4j.

Описание многомодульного проекта

На скриншоте представлена структура проекта pluggable, включающая следующие проектные модули :

• hello-plugin1 – динамически загружаемый плагин №1 (hello1.jar);
• hello-plugin2 – динамически загружаемый плагин №2 (hello2.jar);
• plugin-api – интерфейсы описания плагинов (plugin-api.jar);
• plugin-loader – главный исполняемый jar модуль.

Дополнительные поддиректории проекта, используемые для размещения jar-модулей :

• commons – поддиректория размещения архивного jar-модуля описания интерфейса плагинов;
• plugins – поддиректория размещения jar-модулей (плагинов);

Главный исполняемый модуль plugin-loader.jar размещается в корневой директории проекта, где размещается и проектный/корневой pom.xml. Файл run.bat можно использовать для старта plugin-loader.jar из консоли в Windows.


Примечание : в исходные коды классов внесены изменения, связанные с из размещением в пакетах. В исходном примере все классы располагаются в «корне».

Начнем рассмотрение примера с корневого многомодульного pom.xml.

Листинг многомодульного корневого pom.xml

Корневой pom.xml включает параметры GAV (groupId, artifactId, Version), общую для всех модулей проекта секцию <properties> и секцию описания модулей <modules>. Обратите внимание на атрибут <packaging>, значение которого должно быть «pom».

Следует отметить, что порядок включения программных модулей проекта составлен таким образом, что сначала представлены исполняемый модуль plugin-loader.jar и плагины (hello-plugin1.jar, hello-plugin2.jar), после чего следует интерфейсный модуль plugin-api.jar. Если собирать проект по-отдельности, то модуль plugin-api.jar должен быть собран в первую очередь и размещен в репозитории командой «mvn install». В этом случае зависимые модули plugin-loader.jar и плагины (hello-plugin1, hello-plugin2) собрались бы нормально. Ну, а мы в этом примере посмотрим, как поступит Maven в случае, если порядок описания модулей для сборки «нарушен».

<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>ru.pluggable.main</groupId>
    <artifactId>pluggable</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <name>MultiModule application</name>

    <properties>
        <maven.test.skip>true</maven.test.skip>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>
            UTF-8
        </project.build.sourceEncoding>
    </properties>
  
    <modules>
        <module>plugin-loader</module>
        <module>hello-plugin1</module>
        <module>hello-plugin2</module>
        <module>plugin</module>
    </modules>
</project>

Модуль описания интерфейсов плагинов plugin-api.jar

На следующем скриншоте представлена структура проекта plugin-api. Интерфейсные классы Plugin, PluginContext располагаются в пакете «ru.plugin».

Листинг pom.xml

Проектный pom.xml модуля plugin-api.jar включает GAV-параметры, секцию описания родительского GAV (<parent>) и секцию сборки <build>, где в качестве выходной директории размещения (<outputDirectory>) указана поддиректория «${basedir}/../commons».

<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>ru.pluggable</groupId>
    <artifactId>plugin-api</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <name>Plugin API</name>

    <parent>
        <groupId>ru.pluggable.main</groupId>
        <artifactId>pluggable</artifactId>
        <version>1.0.0</version>
    </parent>
  
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>
                    org.apache.maven.plugins
                </groupId>
                <artifactId>
                    maven-jar-plugin
                </artifactId>
                <version>2.3.1</version>
                <configuration>
                    <outputDirectory>
                        ${basedir}/../commons
                    </outputDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Модуль описания плагина hello-plugin1.jar

Структура проекта hello-plugin1 представлена на следующем скриншоте.

Класс HelloPlugin, расположенный в пакете «ru.plugins», реализует свойства интерфейса Plugin. При инициализации класса в методе init определяется значение контекста PluginContext родительского/вызвавшего объекта. Метод invoke выводит в консоль сообщение и изменяет надпись на кнопке родительского объекта.

package ru.plugins;

import ru.plugin.Plugin;
import ru.plugin.PluginContext;

public class HelloPlugin implements Plugin
{
    private PluginContext pc;

    @Override
    public void invoke() {
        System.out.println("Hello world. I am a plugin 1");
        pc.getButton().setText("Other text 1");
    }
    @Override
    public void init(PluginContext context) {
        this.pc = context;
    }
}

Листинг pom.xml

Проектный pom.xml модуля hello-plugin1.jar включает GAV-параметры, секцию описания родительского GAV (<parent>), секцию зависимостей (<dependencies>) и секцию сборки <build>. В секции зависимостей указываются параметры модуля plugin-api. В описании секции сборки используется 2 плагина (maven-resources-plugin, maven-jar-plugin). Первый плагин включает в сборку ресурсы (resources/settings.properties), второй плагин создает jar и размещяет его в выходной директории (<outputDirectory>) «${basedir}/../plugins».

<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>ru.plugins</groupId>
    <artifactId>hello1</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <name>Plugin Hello1</name>

    <parent>
        <groupId>ru.pluggable.main</groupId>
        <artifactId>pluggable</artifactId>
        <version>1.0.0</version>
    </parent>
  
    <dependencies>
       <dependency>
            <groupId>ru.pluggable</groupId>
            <artifactId>plugin-api</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

    <build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <artifactId>
                maven-resources-plugin
            </artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <configuration>
                        <outputDirectory>
                            ${basedir}/target/resources
                        </outputDirectory>
                        <resources>
                            <directory>
                                src/main/resources
                            </directory>
                            <resource>
                                <includes>
                                    <include>
                                        **/*.properties
                                    </include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.1</version>
            <configuration>
                <outputDirectory>
                    ${basedir}/../plugins
                </outputDirectory>
            </configuration>
        </plugin>
    </plugins>
  </build>
</project>

Примечание : второй плагин hello-plugin2 структурно ничем не отличается от hello-plugin1. Отличия касаются текста сообщения в консоли, надписи на кнопке и параметров GAV в pom.xml.

Проектный pom.xml модуля plugin-loader

Проектный pom.xml включает GAV-параметры jar-модуля, секцию описания родительского GAV (<parent>), секцию зависимостей (<dependencies>) и секцию сборки <build>. В секции зависимостей указываются параметры модуля plugin-api. В описании секции сборки используется плагин maven-jar-plugin, который создает jar и размещяет его в корневой директории проекта (<outputDirectory>).

<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>ru.pluggable.loader</groupId>
    <artifactId>plugin-loader</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <name>Plugin Loader</name>

    <parent>
        <groupId>ru.pluggable.main</groupId>
        <artifactId>pluggable</artifactId>
        <version>1.0.0</version>
    </parent>
  
    <dependencies>
        <dependency>
            <groupId>ru.pluggable</groupId>
            <artifactId>plugin-api</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <outputDirectory>
                        ${basedir}/..
                    </outputDirectory>
                    <archive>
                        <manifest>
                            <mainClass>
                                ru.pluggable.loader.Boostrap
                            </mainClass>
                        </manifest>
                    </archive>
	            </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Сборка проекта

Сборка всех проектов выполняется одной командой «mvn package» для корневого pom.xml. Maven сначала просматривает проектные файлы pom.xml всех модулей, определенных в корневом pom.xml, и после этого определяет порядок сборки модулей. Как следует из представленных ниже сообщений, выводимых Maven в консоль, порядок сборки был изменен и первым собирается модуль Plugin API, после чего формируются зависимые от него Plugin Loader, Plugin Hello1, Plugin Hello2.


D:\pluggable>mvn package
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] MultiModule application
[INFO] Plugin API
[INFO] Plugin Loader
[INFO] Plugin Hello1
[INFO] Plugin Hello2
[INFO]
[INFO] ----------------------------------------------------
[INFO] Building MultiModule application 1.0.0
[INFO] ----------------------------------------------------
[INFO]
[INFO] ----------------------------------------------------
[INFO] Building Plugin API 1.0.0
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources \
            (default-resources) @ plugin-api ---
[INFO] Using 'UTF-8' encoding to copy filtered \
            resources.
[INFO] skip non existing resourceDirectory \
            D:\pluggable\plugin\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile \
           (default-compile) @ plugin-api ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to \
            D:\pluggable\plugin\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources \
            (default-testResources) @ plugin-api ---
[INFO] Not copying test resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile \
            (default-testCompile) @ plugin-api ---
[INFO] Not compiling test sources
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test \
            (default-test) @ plugin-api ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) \
            @ plugin-api ---
[INFO] Building jar: \
            D:\pluggable\plugin\..\commons\plugin-api.jar
[INFO]
[INFO] ----------------------------------------------------
[INFO] Building Plugin Loader 1.0.0
[INFO] ----------------------------------------------------
[INFO]
. . .
[INFO]
[INFO] ----------------------------------------------------
[INFO] Building Plugin Hello1 1.0.0
[INFO] ----------------------------------------------------
[INFO]
. . .
[INFO]
[INFO] ----------------------------------------------------
[INFO] Building Plugin Hello2 1.0.0
[INFO] ----------------------------------------------------
. . .
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) \
          @ hello2 ---
[INFO] Building jar: \
          D:\pluggable\hello-plugin2\..\plugins\hello2.jar
[INFO] ----------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] MultiModule application ...... SUCCESS [  0.006 s]
[INFO] Plugin API ................... SUCCESS [  1.957 s]
[INFO] Plugin Loader ................ SUCCESS [  0.391 s]
[INFO] Plugin Hello1 ................ SUCCESS [  0.183 s]
[INFO] Plugin Hello2 ................ SUCCESS [  0.115 s]
[INFO] ----------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ----------------------------------------------------
[INFO] Total time: 2.802 s
[INFO] Finished at: 2019-06-05T11:07:45+03:00
[INFO] Final Memory: 18M/199M
[INFO] ----------------------------------------------------
 

Примечание :
1. При первой сборке проекта maven не нашел в репозитории модуль plugin-api.jar, прекратил сборку и вывел соответствующее сообщение. После размещения модуля plugin-api.jar в локальном репозитории командой «mvn install» сборка всего проекта прошла успешно.
2. После первой сборки проекта из локального репозитория был удален модуль plugin-api.jar. При дальнейших запусках сборки проекта Maven больше не ругался и сборка проходила нормально. Каким образом Maven собирает проект при отсутствии в локальном репозитории зависимого plugin-api.jar для меня осталось загадкой.

Скачать проект

Вы можете скачать рассмотренный пример по ссылке maven-mulimodule.zip (54.6 Кб)

Связанные страницы

Наследование проектов в maven
«Оборачивание» jar в exe-файл с использованием launch4j

  Рейтинг@Mail.ru